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 * Constructs 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 * @throws ClassNotFoundException if the class referenced by this type can't be found 058 */ 059 public boolean accessibleTo(final ObjectType accessor) throws ClassNotFoundException { 060 final JavaClass jc = Repository.lookupClass(className); 061 if (jc.isPublic()) { 062 return true; 063 } 064 final JavaClass acc = Repository.lookupClass(accessor.className); 065 return acc.getPackageName().equals(jc.getPackageName()); 066 } 067 068 /** 069 * @return true if both type objects refer to the same class. 070 */ 071 @Override 072 public boolean equals(final Object type) { 073 return type instanceof ObjectType && ((ObjectType) type).className.equals(className); 074 } 075 076 /** 077 * @return name of referenced class 078 */ 079 @Override 080 public String getClassName() { 081 return className; 082 } 083 084 /** 085 * @return a hash code value for the object. 086 */ 087 @Override 088 public int hashCode() { 089 return className.hashCode(); 090 } 091 092 /** 093 * If "this" doesn't reference a class, it references an interface or a non-existant entity. 094 * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be 095 * found: use referencesClassExact() instead 096 */ 097 @Deprecated 098 public boolean referencesClass() { 099 try { 100 final JavaClass jc = Repository.lookupClass(className); 101 return jc.isClass(); 102 } catch (final ClassNotFoundException e) { 103 return false; 104 } 105 } 106 107 /** 108 * Return true if this type references a class, false if it references an interface. 109 * 110 * @return true if the type references a class, false if it references an interface 111 * @throws ClassNotFoundException if the class or interface referenced by this type can't be found 112 */ 113 public boolean referencesClassExact() throws ClassNotFoundException { 114 final JavaClass jc = Repository.lookupClass(className); 115 return jc.isClass(); 116 } 117 118 /** 119 * If "this" doesn't reference an interface, it references a class or a non-existant entity. 120 * 121 * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be 122 * found: use referencesInterfaceExact() instead 123 */ 124 @Deprecated 125 public boolean referencesInterface() { 126 try { 127 final JavaClass jc = Repository.lookupClass(className); 128 return !jc.isClass(); 129 } catch (final ClassNotFoundException e) { 130 return false; 131 } 132 } 133 134 /** 135 * Return true if this type references an interface, false if it references a class. 136 * 137 * @return true if the type references an interface, false if it references a class 138 * @throws ClassNotFoundException if the class or interface referenced by this type can't be found 139 */ 140 public boolean referencesInterfaceExact() throws ClassNotFoundException { 141 final JavaClass jc = Repository.lookupClass(className); 142 return !jc.isClass(); 143 } 144 145 /** 146 * Return true if this type is a subclass of given ObjectType. 147 * 148 * @throws ClassNotFoundException if any of this class's superclasses can't be found 149 */ 150 public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException { 151 if (referencesInterfaceExact() || superclass.referencesInterfaceExact()) { 152 return false; 153 } 154 return Repository.instanceOf(this.className, superclass.className); 155 } 156}