KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > bcel > internal > generic > ReferenceType


1 package com.sun.org.apache.bcel.internal.generic;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" and
29  * "Apache BCEL" must not be used to endorse or promote products
30  * derived from this software without prior written permission. For
31  * written permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * "Apache BCEL", nor may "Apache" appear in their name, without
35  * prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56 import com.sun.org.apache.bcel.internal.Constants;
57 import com.sun.org.apache.bcel.internal.Repository;
58 import com.sun.org.apache.bcel.internal.classfile.JavaClass;
59
60 /**
61  * Super class for objects and arrays.
62  *
63  * @version $Id: ReferenceType.java,v 1.1.1.1 2001/10/29 20:00:26 jvanzyl Exp $
64  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
65  */

66 public class ReferenceType extends Type {
67   protected ReferenceType(byte t, String JavaDoc s) {
68     super(t, s);
69   }
70
71   /** Class is non-abstract but not instantiable from the outside
72    */

73   ReferenceType() {
74     super(Constants.T_OBJECT, "<null object>");
75   }
76
77   /**
78    * Return true iff this type is castable to another type t as defined in
79    * the JVM specification. The case where this is Type.NULL is not
80    * defined (see the CHECKCAST definition in the JVM specification).
81    * However, because e.g. CHECKCAST doesn't throw a
82    * ClassCastException when casting a null reference to any Object,
83    * true is returned in this case.
84    */

85   public boolean isCastableTo(Type t){
86     if(this.equals(Type.NULL))
87       return true; // If this is ever changed in isAssignmentCompatible()
88

89     return isAssignmentCompatibleWith(t); /* Yes, it's true: It's the same definition.
90                        * See vmspec2 AASTORE / CHECKCAST definitions.
91                        */

92   }
93
94   /**
95    * Return true iff this is assignment compatible with another type t
96    * as defined in the JVM specification; see the AASTORE definition
97    * there.
98    */

99   public boolean isAssignmentCompatibleWith(Type t) {
100     if(!(t instanceof ReferenceType))
101       return false;
102
103     ReferenceType T = (ReferenceType)t;
104
105     if(this.equals(Type.NULL))
106       return true; // This is not explicitely stated, but clear. Isn't it?
107

108     /* If this is a class type then
109      */

110     if((this instanceof ObjectType) && (((ObjectType) this).referencesClass())) {
111       /* If T is a class type, then this must be the same class as T,
112          or this must be a subclass of T;
113       */

114       if((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
115     if(this.equals(T))
116       return true;
117
118     if(Repository.instanceOf( ((ObjectType) this).getClassName(),
119                   ((ObjectType) T).getClassName()))
120       return true;
121       }
122
123       /* If T is an interface type, this must implement interface T.
124        */

125       if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
126     if (Repository.implementationOf( ((ObjectType) this).getClassName(),
127                      ((ObjectType) T).getClassName() ))
128       return true;
129       }
130     }
131
132     /* If this is an interface type, then:
133      */

134     if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterface())){
135       /* If T is a class type, then T must be Object (&#247;2.4.7).
136        */

137       if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())){
138     if (T.equals(Type.OBJECT)) return true;
139       }
140
141       /* If T is an interface type, then T must be the same interface
142          as this or a superinterface of this (&#247;2.13.2).
143       */

144       if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())){
145     if (this.equals(T)) return true;
146     if (Repository.implementationOf( ((ObjectType) this).getClassName(),
147                      ((ObjectType) T).getClassName() )) return true;
148       }
149     }
150
151     /* If this is an array type, namely, the type SC[], that is, an
152        array of components of type SC, then:
153     */

154     if(this instanceof ArrayType){
155       /* If T is a class type, then T must be Object (&#247;2.4.7).
156        */

157       if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())){
158     if (T.equals(Type.OBJECT)) return true;
159       }
160
161       /* If T is an array type TC[], that is, an array of components
162          of type TC, then one of the following must be true:
163       */

164       if (T instanceof ArrayType) {
165     /* TC and SC are the same primitive type (&#247;2.4.1).
166      */

167     Type sc = ((ArrayType) this).getElementType();
168     Type tc = ((ArrayType) this).getElementType();
169
170     if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc))
171       return true;
172
173     /* TC and SC are reference types (&#247;2.4.6), and type SC is
174            assignable to TC by these runtime rules.*/

175     if (tc instanceof ReferenceType && sc instanceof ReferenceType &&
176         ((ReferenceType) sc).isAssignmentCompatibleWith((ReferenceType) tc)) return true;
177       }
178
179       /* If T is an interface type, T must be one of the interfaces implemented by arrays (&#247;2.15). */
180       // TODO: Check if this is still valid or find a way to dynamically find out which
181
// interfaces arrays implement. However, as of the JVM specification edition 2, there
182
// are at least two different pages where assignment compatibility is defined and
183
// on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
184
// 'java.io.Serializable'"
185
if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())){
186     for (int ii=0; ii<Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS.length; ii++){
187       if (T.equals(new ObjectType(Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS[ii]))) return true;
188   }
189       }
190     }
191     return false; // default.
192
}
193
194  /**
195    * This commutative operation returns the first common superclass (narrowest ReferenceType
196    * referencing a class, not an interface).
197    * If one of the types is a superclass of the other, the former is returned.
198    * If "this" is Type.NULL, then t is returned.
199    * If t is Type.NULL, then "this" is returned.
200    * If "this" equals t ['this.equals(t)'] "this" is returned.
201    * If "this" or t is an ArrayType, then Type.OBJECT is returned.
202    * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
203    * If not all of the two classes' superclasses cannot be found, "null" is returned.
204    * See the JVM specification edition 2, "&247;4.9.2 The Bytecode Verifier".
205    */

206   public ReferenceType firstCommonSuperclass(ReferenceType t){
207     if (this.equals(Type.NULL)) return t;
208
209     if (t.equals(Type.NULL)) return this;
210
211     if (this.equals(t)) return this;
212
213     // TODO: This sounds a little arbitrary. On the other hand, there is
214
// no object referenced by Type.NULL so we can also say all the objects
215
// referenced by Type.NULL were derived from java.lang.Object.
216
// However, the Java Language's "instanceof" operator proves us wrong:
217
// "null" is not referring to an instance of java.lang.Object :)
218

219     if ((this instanceof ArrayType) || (t instanceof ArrayType))
220       return Type.OBJECT;
221     // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
222

223     if ( ((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) ||
224      (( t instanceof ObjectType) && ((ObjectType) t).referencesInterface()) )
225       return Type.OBJECT;
226     // TODO: The above line is correct comparing to the vmspec2. But one could
227
// make class file verification a bit stronger here by using the notion of
228
// superinterfaces or even castability or assignment compatibility.
229

230
231     // this and t are ObjectTypes, see above.
232
ObjectType thiz = (ObjectType) this;
233     ObjectType other = (ObjectType) t;
234     JavaClass[] thiz_sups = Repository.getSuperClasses( thiz.getClassName());
235     JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
236
237     if ((thiz_sups == null) || (other_sups==null)){
238       return null;
239     }
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
249     for (int i=0; i<t_sups.length; i++){
250       for (int j=0; j<this_sups.length; j++){
251     if (this_sups[j].equals(t_sups[i])) 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
Popular Tags