1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.bcel.generic; 18 19 import org.apache.bcel.Const; 20 import org.apache.bcel.Repository; 21 import org.apache.bcel.classfile.JavaClass; 22 import org.apache.bcel.classfile.Utility; 23 24 /** 25 * Denotes reference such as {@link String}. 26 */ 27 public class ObjectType extends ReferenceType { 28 29 /** 30 * Constructs a new instance. 31 * 32 * @param className fully qualified class name, e.g. java.lang.String 33 * @return a new instance. 34 * @since 6.0 35 */ 36 public static ObjectType getInstance(final String className) { 37 return new ObjectType(className); 38 } 39 40 private final String className; // Class name of type 41 42 /** 43 * Constructs a new instance. 44 * 45 * @param className fully qualified class name, e.g. {@link String} 46 */ 47 public ObjectType(final String className) { 48 super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";"); 49 this.className = Utility.pathToPackage(className); 50 } 51 52 /** 53 * Java Virtual Machine Specification edition 2, � 5.4.4 Access Control 54 * 55 * @throws ClassNotFoundException if the class referenced by this type can't be found 56 */ 57 public boolean accessibleTo(final ObjectType accessor) throws ClassNotFoundException { 58 final JavaClass jc = Repository.lookupClass(className); 59 if (jc.isPublic()) { 60 return true; 61 } 62 final JavaClass acc = Repository.lookupClass(accessor.className); 63 return acc.getPackageName().equals(jc.getPackageName()); 64 } 65 66 /** 67 * @return true if both type objects refer to the same class. 68 */ 69 @Override 70 public boolean equals(final Object type) { 71 return type instanceof ObjectType && ((ObjectType) type).className.equals(className); 72 } 73 74 /** 75 * @return name of referenced class 76 */ 77 @Override 78 public String getClassName() { 79 return className; 80 } 81 82 /** 83 * @return a hash code value for the object. 84 */ 85 @Override 86 public int hashCode() { 87 return className.hashCode(); 88 } 89 90 /** 91 * If "this" doesn't reference a class, it references an interface or a non-existant entity. 92 * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be 93 * found: use referencesClassExact() instead 94 */ 95 @Deprecated 96 public boolean referencesClass() { 97 try { 98 final JavaClass jc = Repository.lookupClass(className); 99 return jc.isClass(); 100 } catch (final ClassNotFoundException e) { 101 return false; 102 } 103 } 104 105 /** 106 * Return true if this type references a class, false if it references an interface. 107 * 108 * @return true if the type references a class, false if it references an interface 109 * @throws ClassNotFoundException if the class or interface referenced by this type can't be found 110 */ 111 public boolean referencesClassExact() throws ClassNotFoundException { 112 final JavaClass jc = Repository.lookupClass(className); 113 return jc.isClass(); 114 } 115 116 /** 117 * If "this" doesn't reference an interface, it references a class or a non-existant entity. 118 * 119 * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be 120 * found: use referencesInterfaceExact() instead 121 */ 122 @Deprecated 123 public boolean referencesInterface() { 124 try { 125 final JavaClass jc = Repository.lookupClass(className); 126 return !jc.isClass(); 127 } catch (final ClassNotFoundException e) { 128 return false; 129 } 130 } 131 132 /** 133 * Return true if this type references an interface, false if it references a class. 134 * 135 * @return true if the type references an interface, false if it references a class 136 * @throws ClassNotFoundException if the class or interface referenced by this type can't be found 137 */ 138 public boolean referencesInterfaceExact() throws ClassNotFoundException { 139 final JavaClass jc = Repository.lookupClass(className); 140 return !jc.isClass(); 141 } 142 143 /** 144 * Return true if this type is a subclass of given ObjectType. 145 * 146 * @throws ClassNotFoundException if any of this class's superclasses can't be found 147 */ 148 public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException { 149 if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) { 150 return false; 151 } 152 return Repository.instanceOf(this.className, superclass.className); 153 } 154 }