View Javadoc
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 }