KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > 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 org.objectweb.asm.tree.analysis;
31
32 import org.objectweb.asm.Type;
33
34 /**
35  * An extended {@link BasicVerifier} that performs more precise verifications.
36  * This verifier computes exact class types, instead of using a single "object
37  * reference" type (as done in the {@link BasicVerifier}).
38  *
39  * @author Eric Bruneton
40  * @author Bing Ran
41  */

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

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

52     private final Type currentSuperClass;
53
54     /**
55      * If the class that is verified is an interface.
56      */

57     private final boolean isInterface;
58
59     /**
60      * Constructs a new {@link SimpleVerifier}.
61      */

62     public SimpleVerifier() {
63         this(null, null, false);
64     }
65
66     /**
67      * Constructs a new {@link SimpleVerifier} to verify a specific class. This
68      * class will not be loaded into the JVM since it may be incorrect.
69      *
70      * @param currentClass the class that is verified.
71      * @param currentSuperClass the super class of the class that is verified.
72      * @param isInterface if the class that is verified is an interface.
73      */

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