001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.generic; 020 021import org.apache.bcel.Const; 022import org.apache.bcel.Repository; 023import org.apache.bcel.classfile.JavaClass; 024import org.apache.bcel.classfile.Utility; 025 026/** 027 * Denotes reference such as {@link String}. 028 */ 029public class ObjectType extends ReferenceType { 030 031 /** 032 * Gets a new instance. 033 * 034 * @param className fully qualified class name, for example {@link String}. 035 * @return A new instance. 036 * @since 6.0 037 */ 038 public static ObjectType getInstance(final String className) { 039 return new ObjectType(className); 040 } 041 042 private final String className; // Class name of type 043 044 /** 045 * Constructs a new instance. 046 * 047 * @param className fully qualified class name, for example {@link String}. 048 */ 049 public ObjectType(final String className) { 050 super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";"); 051 this.className = Utility.pathToPackage(className); 052 } 053 054 /** 055 * Java Virtual Machine Specification edition 2, 5.4.4 Access Control. 056 * 057 * @param accessor The accessing type. 058 * @return true if accessible. 059 * @throws ClassNotFoundException Thrown if the class referenced by this type can't be found. 060 */ 061 public boolean accessibleTo(final ObjectType accessor) throws ClassNotFoundException { 062 final JavaClass jc = Repository.lookupClass(className); 063 if (jc.isPublic()) { 064 return true; 065 } 066 final JavaClass acc = Repository.lookupClass(accessor.className); 067 return acc.getPackageName().equals(jc.getPackageName()); 068 } 069 070 /** 071 * @return true if both type objects refer to the same class. 072 */ 073 @Override 074 public boolean equals(final Object type) { 075 return type instanceof ObjectType && ((ObjectType) type).className.equals(className); 076 } 077 078 /** 079 * Gets the name of the referenced class. 080 * 081 * @return name of referenced class. 082 */ 083 @Override 084 public String getClassName() { 085 return className; 086 } 087 088 /** 089 * Gets the hash code. 090 * 091 * @return A hash code value for the object. 092 */ 093 @Override 094 public int hashCode() { 095 return className.hashCode(); 096 } 097 098 /** 099 * If "this" doesn't reference a class, it references an interface or a nonexistent entity. 100 * 101 * @return true if it references a class, false otherwise. 102 * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be 103 * found: use referencesClassExact() instead 104 */ 105 @Deprecated 106 public boolean referencesClass() { 107 try { 108 return Repository.lookupClass(className).isClass(); 109 } catch (final ClassNotFoundException e) { 110 return false; 111 } 112 } 113 114 /** 115 * Return true if this type references a class, false if it references an interface. 116 * 117 * @return true if the type references a class, false if it references an interface. 118 * @throws ClassNotFoundException Thrown if the class or interface referenced by this type can't be found 119 */ 120 public boolean referencesClassExact() throws ClassNotFoundException { 121 return Repository.lookupClass(className).isClass(); 122 } 123 124 /** 125 * If "this" doesn't reference an interface, it references a class or a nonexistent entity. 126 * 127 * @return true if it references an interface, false otherwise. 128 * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be 129 * found: use referencesInterfaceExact() instead 130 */ 131 @Deprecated 132 public boolean referencesInterface() { 133 try { 134 return !Repository.lookupClass(className).isClass(); 135 } catch (final ClassNotFoundException e) { 136 return false; 137 } 138 } 139 140 /** 141 * Return true if this type references an interface, false if it references a class. 142 * 143 * @return true if the type references an interface, false if it references a class. 144 * @throws ClassNotFoundException Thrown if the class or interface referenced by this type can't be found 145 */ 146 public boolean referencesInterfaceExact() throws ClassNotFoundException { 147 return !Repository.lookupClass(className).isClass(); 148 } 149 150 /** 151 * Return true if this type is a subclass of given ObjectType. 152 * 153 * @param superclass The superclass to check against. 154 * @return true if this is a subclass. 155 * @throws ClassNotFoundException Thrown if any of this class's superclasses can't be found. 156 */ 157 public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException { 158 if (referencesInterfaceExact() || superclass.referencesInterfaceExact()) { 159 return false; 160 } 161 return Repository.instanceOf(this.className, superclass.className); 162 } 163 164 /** 165 * Return the string representation of this type. 166 * 167 * @return the string representation of this type. 168 * @since 6.14.0 169 */ 170 @Override 171 public String toString() { 172 return className; 173 } 174}