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  */
18 package org.apache.bcel.generic;
19 
20 import org.apache.bcel.Const;
21 import org.apache.bcel.Repository;
22 import org.apache.bcel.classfile.JavaClass;
23 
24 /**
25  * Denotes reference such as java.lang.String.
26  *
27  * @version $Id$
28  */
29 public class ObjectType extends ReferenceType {
30 
31     private final String class_name; // Class name of type
32 
33     /**
34      * @since 6.0
35      */
getInstance(final String class_name)36     public static ObjectType getInstance(final String class_name) {
37         return new ObjectType(class_name);
38     }
39 
40     /**
41      * @param class_name fully qualified class name, e.g. java.lang.String
42      */
ObjectType(final String class_name)43     public ObjectType(final String class_name) {
44         super(Const.T_REFERENCE, "L" + class_name.replace('.', '/') + ";");
45         this.class_name = class_name.replace('/', '.');
46     }
47 
48 
49     /** @return name of referenced class
50      */
getClassName()51     public String getClassName() {
52         return class_name;
53     }
54 
55 
56     /** @return a hash code value for the object.
57      */
58     @Override
hashCode()59     public int hashCode() {
60         return class_name.hashCode();
61     }
62 
63 
64     /** @return true if both type objects refer to the same class.
65      */
66     @Override
equals( final Object type )67     public boolean equals( final Object type ) {
68         return (type instanceof ObjectType)
69                 ? ((ObjectType) type).class_name.equals(class_name)
70                 : false;
71     }
72 
73 
74     /**
75      * If "this" doesn't reference a class, it references an interface
76      * or a non-existant entity.
77      * @deprecated (since 6.0) this method returns an inaccurate result
78      *   if the class or interface referenced cannot
79      *   be found: use referencesClassExact() instead
80      */
81     @Deprecated
referencesClass()82     public boolean referencesClass() {
83         try {
84             final JavaClass jc = Repository.lookupClass(class_name);
85             return jc.isClass();
86         } catch (final ClassNotFoundException e) {
87             return false;
88         }
89     }
90 
91 
92     /**
93      * If "this" doesn't reference an interface, it references a class
94      * or a non-existant entity.
95      * @deprecated (since 6.0) this method returns an inaccurate result
96      *   if the class or interface referenced cannot
97      *   be found: use referencesInterfaceExact() instead
98      */
99     @Deprecated
referencesInterface()100     public boolean referencesInterface() {
101         try {
102             final JavaClass jc = Repository.lookupClass(class_name);
103             return !jc.isClass();
104         } catch (final ClassNotFoundException e) {
105             return false;
106         }
107     }
108 
109 
110     /**
111      * Return true if this type references a class,
112      * false if it references an interface.
113      * @return true if the type references a class, false if
114      *   it references an interface
115      * @throws ClassNotFoundException if the class or interface
116      *   referenced by this type can't be found
117      */
referencesClassExact()118     public boolean referencesClassExact() throws ClassNotFoundException {
119         final JavaClass jc = Repository.lookupClass(class_name);
120         return jc.isClass();
121     }
122 
123 
124     /**
125      * Return true if this type references an interface,
126      * false if it references a class.
127      * @return true if the type references an interface, false if
128      *   it references a class
129      * @throws ClassNotFoundException if the class or interface
130      *   referenced by this type can't be found
131      */
referencesInterfaceExact()132     public boolean referencesInterfaceExact() throws ClassNotFoundException {
133         final JavaClass jc = Repository.lookupClass(class_name);
134         return !jc.isClass();
135     }
136 
137 
138     /**
139      * Return true if this type is a subclass of given ObjectType.
140      * @throws ClassNotFoundException if any of this class's superclasses
141      *  can't be found
142      */
subclassOf( final ObjectType superclass )143     public boolean subclassOf( final ObjectType superclass ) throws ClassNotFoundException {
144         if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) {
145             return false;
146         }
147         return Repository.instanceOf(this.class_name, superclass.class_name);
148     }
149 
150 
151     /**
152      * Java Virtual Machine Specification edition 2, � 5.4.4 Access Control
153      * @throws ClassNotFoundException if the class referenced by this type
154      *   can't be found
155      */
accessibleTo( final ObjectType accessor )156     public boolean accessibleTo( final ObjectType accessor ) throws ClassNotFoundException {
157         final JavaClass jc = Repository.lookupClass(class_name);
158         if (jc.isPublic()) {
159             return true;
160         }
161         final JavaClass acc = Repository.lookupClass(accessor.class_name);
162         return acc.getPackageName().equals(jc.getPackageName());
163     }
164 }
165