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