KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > asm > tree > analysis > SimpleVerifier


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package com.tc.asm.tree.analysis;
31
32 import java.util.List JavaDoc;
33
34 import com.tc.asm.Type;
35
36 /**
37  * An extended {@link BasicVerifier} that performs more precise verifications.
38  * This verifier computes exact class types, instead of using a single "object
39  * reference" type (as done in the {@link BasicVerifier}).
40  *
41  * @author Eric Bruneton
42  * @author Bing Ran
43  */

44 public class SimpleVerifier extends BasicVerifier {
45
46     /**
47      * The class that is verified.
48      */

49     private final Type currentClass;
50
51     /**
52      * The super class of the class that is verified.
53      */

54     private final Type currentSuperClass;
55
56     /**
57      * The interfaces implemented by the class that is verified.
58      */

59     private final List JavaDoc currentClassInterfaces;
60
61     /**
62      * If the class that is verified is an interface.
63      */

64     private final boolean isInterface;
65
66     /**
67      * Constructs a new {@link SimpleVerifier}.
68      */

69     public SimpleVerifier() {
70         this(null, null, false);
71     }
72
73     /**
74      * Constructs a new {@link SimpleVerifier} to verify a specific class. This
75      * class will not be loaded into the JVM since it may be incorrect.
76      *
77      * @param currentClass the class that is verified.
78      * @param currentSuperClass the super class of the class that is verified.
79      * @param isInterface if the class that is verified is an interface.
80      */

81     public SimpleVerifier(
82         final Type currentClass,
83         final Type currentSuperClass,
84         final boolean isInterface)
85     {
86         this(currentClass, currentSuperClass, null, isInterface);
87     }
88
89     /**
90      * Constructs a new {@link SimpleVerifier} to verify a specific class. This
91      * class will not be loaded into the JVM since it may be incorrect.
92      *
93      * @param currentClass the class that is verified.
94      * @param currentSuperClass the super class of the class that is verified.
95      * @param currentClassInterfaces the interfaces implemented by the class
96      * that is verified.
97      * @param isInterface if the class that is verified is an interface.
98      */

99     public SimpleVerifier(
100         final Type currentClass,
101         final Type currentSuperClass,
102         final List JavaDoc currentClassInterfaces,
103         final boolean isInterface)
104     {
105         this.currentClass = currentClass;
106         this.currentSuperClass = currentSuperClass;
107         this.currentClassInterfaces = currentClassInterfaces;
108         this.isInterface = isInterface;
109     }
110
111     public Value newValue(final Type type) {
112         Value v = super.newValue(type);
113         if (v == BasicValue.REFERENCE_VALUE) {
114             v = new BasicValue(type);
115         }
116         return v;
117     }
118
119     protected boolean isArrayValue(final Value value) {
120         Type t = ((BasicValue) value).getType();
121         if (t != null) {
122             return t.getDescriptor().equals("Lnull;")
123                     || t.getSort() == Type.ARRAY;
124         }
125         return false;
126     }
127
128     protected Value getElementValue(final Value objectArrayValue)
129             throws AnalyzerException
130     {
131         Type arrayType = ((BasicValue) objectArrayValue).getType();
132         if (arrayType != null) {
133             if (arrayType.getSort() == Type.ARRAY) {
134                 return newValue(Type.getType(arrayType.getDescriptor()
135                         .substring(1)));
136             } else if (arrayType.getDescriptor().equals("Lnull;")) {
137                 return objectArrayValue;
138             }
139         }
140         throw new AnalyzerException("Not an array type");
141     }
142
143     protected boolean isSubTypeOf(final Value value, final Value expected) {
144         Type expectedType = ((BasicValue) expected).getType();
145         Type type = ((BasicValue) value).getType();
146         if (expectedType == null) {
147             return type == null;
148         }
149         switch (expectedType.getSort()) {
150             case Type.INT:
151             case Type.FLOAT:
152             case Type.LONG:
153             case Type.DOUBLE:
154                 return type == expectedType;
155             case Type.ARRAY:
156             case Type.OBJECT:
157                 if (expectedType.getDescriptor().equals("Lnull;")) {
158                     return type.getSort() == Type.OBJECT
159                             || type.getSort() == Type.ARRAY;
160                 }
161                 if (type.getDescriptor().equals("Lnull;")) {
162                     return true;
163                 } else if (type.getSort() == Type.OBJECT
164                         || type.getSort() == Type.ARRAY)
165                 {
166                     return isAssignableFrom(expectedType, type);
167                 } else {
168                     return false;
169                 }
170             default:
171                 throw new RuntimeException JavaDoc("Internal error");
172         }
173     }
174
175     public Value merge(final Value v, final Value w) {
176         if (!v.equals(w)) {
177             Type t = ((BasicValue) v).getType();
178             Type u = ((BasicValue) w).getType();
179             if (t != null
180                     && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY))
181             {
182                 if (u != null
183                         && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY))
184                 {
185                     if (t.getDescriptor().equals("Lnull;")) {
186                         return w;
187                     }
188                     if (u.getDescriptor().equals("Lnull;")) {
189                         return v;
190                     }
191                     if (isAssignableFrom(t, u)) {
192                         return v;
193                     }
194                     if (isAssignableFrom(u, t)) {
195                         return w;
196                     }
197                     // TODO case of array classes of the same dimension
198
// TODO should we look also for a common super interface?
199
// problem: there may be several possible common super
200
// interfaces
201
do {
202                         if (t == null || isInterface(t)) {
203                             return BasicValue.REFERENCE_VALUE;
204                         }
205                         t = getSuperClass(t);
206                         if (isAssignableFrom(t, u)) {
207                             return newValue(t);
208                         }
209                     } while (true);
210                 }
211             }
212             return BasicValue.UNINITIALIZED_VALUE;
213         }
214         return v;
215     }
216
217     private boolean isInterface(final Type t) {
218         if (currentClass != null && t.equals(currentClass)) {
219             return isInterface;
220         }
221         return getClass(t).isInterface();
222     }
223
224     private Type getSuperClass(final Type t) {
225         if (currentClass != null && t.equals(currentClass)) {
226             return currentSuperClass;
227         }
228         Class JavaDoc c = getClass(t).getSuperclass();
229         return c == null ? null : Type.getType(c);
230     }
231
232     private boolean isAssignableFrom(final Type t, final Type u) {
233         if (t.equals(u)) {
234             return true;
235         }
236         if (currentClass != null && t.equals(currentClass)) {
237             return isAssignableFrom(t, getSuperClass(u));
238         }
239         if (currentClass != null && u.equals(currentClass)) {
240             if (isAssignableFrom(t, currentSuperClass)) {
241                 return true;
242             }
243             if (currentClassInterfaces != null) {
244                 for (int i = 0; i < currentClassInterfaces.size(); ++i) {
245                     Type v = (Type) currentClassInterfaces.get(i);
246                     if (isAssignableFrom(t, v)) {
247                         return true;
248                     }
249                 }
250             }
251             return false;
252         }
253         return getClass(t).isAssignableFrom(getClass(u));
254     }
255
256     protected Class JavaDoc getClass(final Type t) {
257         try {
258             if (t.getSort() == Type.ARRAY) {
259                 return Class.forName(t.getDescriptor().replace('/', '.'));
260             }
261             return Class.forName(t.getClassName());
262         } catch (ClassNotFoundException JavaDoc e) {
263             throw new RuntimeException JavaDoc(e.toString());
264         }
265     }
266 }
267
Popular Tags