KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > generic > ReferenceType


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.generic;
18
19 import org.apache.bcel.Constants;
20 import org.apache.bcel.Repository;
21 import org.apache.bcel.classfile.JavaClass;
22
23 /**
24  * Super class for object and array types.
25  *
26  * @version $Id: ReferenceType.java 386056 2006-03-15 11:31:56Z tcurdt $
27  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
28  */

29 public abstract class ReferenceType extends Type {
30
31     protected ReferenceType(byte t, String JavaDoc s) {
32         super(t, s);
33     }
34
35
36     /** Class is non-abstract but not instantiable from the outside
37      */

38     ReferenceType() {
39         super(Constants.T_OBJECT, "<null object>");
40     }
41
42
43     /**
44      * Return true iff this type is castable to another type t as defined in
45      * the JVM specification. The case where this is Type.NULL is not
46      * defined (see the CHECKCAST definition in the JVM specification).
47      * However, because e.g. CHECKCAST doesn't throw a
48      * ClassCastException when casting a null reference to any Object,
49      * true is returned in this case.
50      *
51      * @throws ClassNotFoundException if any classes or interfaces required
52      * to determine assignment compatibility can't be found
53      */

54     public boolean isCastableTo( Type t ) throws ClassNotFoundException JavaDoc {
55         if (this.equals(Type.NULL)) {
56             return true; // If this is ever changed in isAssignmentCompatible()
57
}
58         return isAssignmentCompatibleWith(t);
59         /* Yes, it's true: It's the same definition.
60          * See vmspec2 AASTORE / CHECKCAST definitions.
61          */

62     }
63
64
65     /**
66      * Return true iff this is assignment compatible with another type t
67      * as defined in the JVM specification; see the AASTORE definition
68      * there.
69      * @throws ClassNotFoundException if any classes or interfaces required
70      * to determine assignment compatibility can't be found
71      */

72     public boolean isAssignmentCompatibleWith( Type t ) throws ClassNotFoundException JavaDoc {
73         if (!(t instanceof ReferenceType)) {
74             return false;
75         }
76         ReferenceType T = (ReferenceType) t;
77         if (this.equals(Type.NULL)) {
78             return true; // This is not explicitely stated, but clear. Isn't it?
79
}
80         /* If this is a class type then
81          */

82         if ((this instanceof ObjectType) && (((ObjectType) this).referencesClassExact())) {
83             /* If T is a class type, then this must be the same class as T,
84              or this must be a subclass of T;
85              */

86             if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
87                 if (this.equals(T)) {
88                     return true;
89                 }
90                 if (Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T)
91                         .getClassName())) {
92                     return true;
93                 }
94             }
95             /* If T is an interface type, this must implement interface T.
96              */

97             if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
98                 if (Repository.implementationOf(((ObjectType) this).getClassName(),
99                         ((ObjectType) T).getClassName())) {
100                     return true;
101                 }
102             }
103         }
104         /* If this is an interface type, then:
105          */

106         if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterfaceExact())) {
107             /* If T is a class type, then T must be Object (§2.4.7).
108              */

109             if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
110                 if (T.equals(Type.OBJECT)) {
111                     return true;
112                 }
113             }
114             /* If T is an interface type, then T must be the same interface
115              * as this or a superinterface of this (§2.13.2).
116              */

117             if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
118                 if (this.equals(T)) {
119                     return true;
120                 }
121                 if (Repository.implementationOf(((ObjectType) this).getClassName(),
122                         ((ObjectType) T).getClassName())) {
123                     return true;
124                 }
125             }
126         }
127         /* If this is an array type, namely, the type SC[], that is, an
128          * array of components of type SC, then:
129          */

130         if (this instanceof ArrayType) {
131             /* If T is a class type, then T must be Object (§2.4.7).
132              */

133             if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
134                 if (T.equals(Type.OBJECT)) {
135                     return true;
136                 }
137             }
138             /* If T is an array type TC[], that is, an array of components
139              * of type TC, then one of the following must be true:
140              */

141             if (T instanceof ArrayType) {
142                 /* TC and SC are the same primitive type (§2.4.1).
143                  */

144                 Type sc = ((ArrayType) this).getElementType();
145                 Type tc = ((ArrayType) T).getElementType();
146                 if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc)) {
147                     return true;
148                 }
149                 /* TC and SC are reference types (§2.4.6), and type SC is
150                  * assignable to TC by these runtime rules.
151                  */

152                 if (tc instanceof ReferenceType && sc instanceof ReferenceType
153                         && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) {
154                     return true;
155                 }
156             }
157             /* If T is an interface type, T must be one of the interfaces implemented by arrays (§2.15). */
158             // TODO: Check if this is still valid or find a way to dynamically find out which
159
// interfaces arrays implement. However, as of the JVM specification edition 2, there
160
// are at least two different pages where assignment compatibility is defined and
161
// on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
162
// 'java.io.Serializable'"
163
if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
164                 for (int ii = 0; ii < Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS.length; ii++) {
165                     if (T.equals(new ObjectType(Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS[ii]))) {
166                         return true;
167                     }
168                 }
169             }
170         }
171         return false; // default.
172
}
173
174
175     /**
176      * This commutative operation returns the first common superclass (narrowest ReferenceType
177      * referencing a class, not an interface).
178      * If one of the types is a superclass of the other, the former is returned.
179      * If "this" is Type.NULL, then t is returned.
180      * If t is Type.NULL, then "this" is returned.
181      * If "this" equals t ['this.equals(t)'] "this" is returned.
182      * If "this" or t is an ArrayType, then Type.OBJECT is returned;
183      * unless their dimensions match. Then an ArrayType of the same
184      * number of dimensions is returned, with its basic type being the
185      * first common super class of the basic types of "this" and t.
186      * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
187      * If not all of the two classes' superclasses cannot be found, "null" is returned.
188      * See the JVM specification edition 2, "§4.9.2 The Bytecode Verifier".
189      *
190      * @throws ClassNotFoundException on failure to find superclasses of this
191      * type, or the type passed as a parameter
192      */

193     public ReferenceType getFirstCommonSuperclass( ReferenceType t ) throws ClassNotFoundException JavaDoc {
194         if (this.equals(Type.NULL)) {
195             return t;
196         }
197         if (t.equals(Type.NULL)) {
198             return this;
199         }
200         if (this.equals(t)) {
201             return this;
202             /*
203              * TODO: Above sounds a little arbitrary. On the other hand, there is
204              * no object referenced by Type.NULL so we can also say all the objects
205              * referenced by Type.NULL were derived from java.lang.Object.
206              * However, the Java Language's "instanceof" operator proves us wrong:
207              * "null" is not referring to an instance of java.lang.Object :)
208              */

209         }
210         /* This code is from a bug report by Konstantin Shagin <konst@cs.technion.ac.il> */
211         if ((this instanceof ArrayType) && (t instanceof ArrayType)) {
212             ArrayType arrType1 = (ArrayType) this;
213             ArrayType arrType2 = (ArrayType) t;
214             if ((arrType1.getDimensions() == arrType2.getDimensions())
215                     && arrType1.getBasicType() instanceof ObjectType
216                     && arrType2.getBasicType() instanceof ObjectType) {
217                 return new ArrayType(((ObjectType) arrType1.getBasicType())
218                         .getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()), arrType1
219                         .getDimensions());
220             }
221         }
222         if ((this instanceof ArrayType) || (t instanceof ArrayType)) {
223             return Type.OBJECT;
224             // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
225
}
226         if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface())
227                 || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) {
228             return Type.OBJECT;
229             // TODO: The above line is correct comparing to the vmspec2. But one could
230
// make class file verification a bit stronger here by using the notion of
231
// superinterfaces or even castability or assignment compatibility.
232
}
233         // this and t are ObjectTypes, see above.
234
ObjectType thiz = (ObjectType) this;
235         ObjectType other = (ObjectType) t;
236         JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
237         JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
238         if ((thiz_sups == null) || (other_sups == null)) {
239             return null;
240         }
241         // Waaahh...
242
JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
243         JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
244         System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
245         System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
246         this_sups[0] = Repository.lookupClass(thiz.getClassName());
247         t_sups[0] = Repository.lookupClass(other.getClassName());
248         for (int i = 0; i < t_sups.length; i++) {
249             for (int j = 0; j < this_sups.length; j++) {
250                 if (this_sups[j].equals(t_sups[i])) {
251                     return new ObjectType(this_sups[j].getClassName());
252                 }
253             }
254         }
255         // Huh? Did you ask for Type.OBJECT's superclass??
256
return null;
257     }
258
259
260     /**
261      * This commutative operation returns the first common superclass (narrowest ReferenceType
262      * referencing a class, not an interface).
263      * If one of the types is a superclass of the other, the former is returned.
264      * If "this" is Type.NULL, then t is returned.
265      * If t is Type.NULL, then "this" is returned.
266      * If "this" equals t ['this.equals(t)'] "this" is returned.
267      * If "this" or t is an ArrayType, then Type.OBJECT is returned.
268      * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
269      * If not all of the two classes' superclasses cannot be found, "null" is returned.
270      * See the JVM specification edition 2, "§4.9.2 The Bytecode Verifier".
271      *
272      * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has
273      * slightly changed semantics.
274      * @throws ClassNotFoundException on failure to find superclasses of this
275      * type, or the type passed as a parameter
276      */

277     public ReferenceType firstCommonSuperclass( ReferenceType t ) throws ClassNotFoundException JavaDoc {
278         if (this.equals(Type.NULL)) {
279             return t;
280         }
281         if (t.equals(Type.NULL)) {
282             return this;
283         }
284         if (this.equals(t)) {
285             return this;
286             /*
287              * TODO: Above sounds a little arbitrary. On the other hand, there is
288              * no object referenced by Type.NULL so we can also say all the objects
289              * referenced by Type.NULL were derived from java.lang.Object.
290              * However, the Java Language's "instanceof" operator proves us wrong:
291              * "null" is not referring to an instance of java.lang.Object :)
292              */

293         }
294         if ((this instanceof ArrayType) || (t instanceof ArrayType)) {
295             return Type.OBJECT;
296             // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
297
}
298         if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface())
299                 || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) {
300             return Type.OBJECT;
301             // TODO: The above line is correct comparing to the vmspec2. But one could
302
// make class file verification a bit stronger here by using the notion of
303
// superinterfaces or even castability or assignment compatibility.
304
}
305         // this and t are ObjectTypes, see above.
306
ObjectType thiz = (ObjectType) this;
307         ObjectType other = (ObjectType) t;
308         JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
309         JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
310         if ((thiz_sups == null) || (other_sups == null)) {
311             return null;
312         }
313         // Waaahh...
314
JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
315         JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
316         System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
317         System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
318         this_sups[0] = Repository.lookupClass(thiz.getClassName());
319         t_sups[0] = Repository.lookupClass(other.getClassName());
320         for (int i = 0; i < t_sups.length; i++) {
321             for (int j = 0; j < this_sups.length; j++) {
322                 if (this_sups[j].equals(t_sups[i])) {
323                     return new ObjectType(this_sups[j].getClassName());
324                 }
325             }
326         }
327         // Huh? Did you ask for Type.OBJECT's superclass??
328
return null;
329     }
330 }
331
Popular Tags