1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.verifier;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23 import org.apache.bcel.classfile.JavaClass;
24 import org.apache.bcel.verifier.statics.Pass1Verifier;
25 import org.apache.bcel.verifier.statics.Pass2Verifier;
26 import org.apache.bcel.verifier.statics.Pass3aVerifier;
27 import org.apache.bcel.verifier.structurals.Pass3bVerifier;
28
29 /***
30 * A Verifier instance is there to verify a class file according to The Java Virtual
31 * Machine Specification, 2nd Edition.
32 *
33 * Pass-3b-verification includes pass-3a-verification;
34 * pass-3a-verification includes pass-2-verification;
35 * pass-2-verification includes pass-1-verification.
36 *
37 * A Verifier creates PassVerifier instances to perform the actual verification.
38 * Verifier instances are usually generated by the VerifierFactory.
39 *
40 * @version $Id: Verifier.java 386056 2006-03-15 11:31:56Z tcurdt $
41 * @author Enver Haase
42 * @see org.apache.bcel.verifier.VerifierFactory
43 * @see org.apache.bcel.verifier.PassVerifier
44 */
45 public class Verifier {
46
47 /***
48 * The name of the class this verifier operates on.
49 */
50 private final String classname;
51 /*** A Pass1Verifier for this Verifier instance. */
52 private Pass1Verifier p1v;
53 /*** A Pass2Verifier for this Verifier instance. */
54 private Pass2Verifier p2v;
55 /*** The Pass3aVerifiers for this Verifier instance. Key: Interned string specifying the method number. */
56 private Map p3avs = new HashMap();
57 /*** The Pass3bVerifiers for this Verifier instance. Key: Interned string specifying the method number. */
58 private Map p3bvs = new HashMap();
59
60
61 /*** Returns the VerificationResult for the given pass. */
62 public VerificationResult doPass1() {
63 if (p1v == null) {
64 p1v = new Pass1Verifier(this);
65 }
66 return p1v.verify();
67 }
68
69
70 /*** Returns the VerificationResult for the given pass. */
71 public VerificationResult doPass2() {
72 if (p2v == null) {
73 p2v = new Pass2Verifier(this);
74 }
75 return p2v.verify();
76 }
77
78
79 /*** Returns the VerificationResult for the given pass. */
80 public VerificationResult doPass3a( int method_no ) {
81 String key = Integer.toString(method_no);
82 Pass3aVerifier p3av;
83 p3av = (Pass3aVerifier) (p3avs.get(key));
84 if (p3avs.get(key) == null) {
85 p3av = new Pass3aVerifier(this, method_no);
86 p3avs.put(key, p3av);
87 }
88 return p3av.verify();
89 }
90
91
92 /*** Returns the VerificationResult for the given pass. */
93 public VerificationResult doPass3b( int method_no ) {
94 String key = Integer.toString(method_no);
95 Pass3bVerifier p3bv;
96 p3bv = (Pass3bVerifier) (p3bvs.get(key));
97 if (p3bvs.get(key) == null) {
98 p3bv = new Pass3bVerifier(this, method_no);
99 p3bvs.put(key, p3bv);
100 }
101 return p3bv.verify();
102 }
103
104
105 /***
106 * Instantiation is done by the VerifierFactory.
107 *
108 * @see VerifierFactory
109 */
110 Verifier(String fully_qualified_classname) {
111 classname = fully_qualified_classname;
112 flush();
113 }
114
115
116 /***
117 * Returns the name of the class this verifier operates on.
118 * This is particularly interesting when this verifier was created
119 * recursively by another Verifier and you got a reference to this
120 * Verifier by the getVerifiers() method of the VerifierFactory.
121 * @see VerifierFactory
122 */
123 public final String getClassName() {
124 return classname;
125 }
126
127
128 /***
129 * Forget everything known about the class file; that means, really
130 * start a new verification of a possibly different class file from
131 * BCEL's repository.
132 *
133 */
134 public void flush() {
135 p1v = null;
136 p2v = null;
137 p3avs.clear();
138 p3bvs.clear();
139 }
140
141
142 /***
143 * This returns all the (warning) messages collected during verification.
144 * A prefix shows from which verifying pass a message originates.
145 */
146 public String[] getMessages() throws ClassNotFoundException {
147 ArrayList messages = new ArrayList();
148 if (p1v != null) {
149 String[] p1m = p1v.getMessages();
150 for (int i = 0; i < p1m.length; i++) {
151 messages.add("Pass 1: " + p1m[i]);
152 }
153 }
154 if (p2v != null) {
155 String[] p2m = p2v.getMessages();
156 for (int i = 0; i < p2m.length; i++) {
157 messages.add("Pass 2: " + p2m[i]);
158 }
159 }
160 Iterator p3as = p3avs.values().iterator();
161 while (p3as.hasNext()) {
162 Pass3aVerifier pv = (Pass3aVerifier) p3as.next();
163 String[] p3am = pv.getMessages();
164 int meth = pv.getMethodNo();
165 for (int i = 0; i < p3am.length; i++) {
166 messages.add("Pass 3a, method " + meth + " ('"
167 + org.apache.bcel.Repository.lookupClass(classname).getMethods()[meth]
168 + "'): " + p3am[i]);
169 }
170 }
171 Iterator p3bs = p3bvs.values().iterator();
172 while (p3bs.hasNext()) {
173 Pass3bVerifier pv = (Pass3bVerifier) p3bs.next();
174 String[] p3bm = pv.getMessages();
175 int meth = pv.getMethodNo();
176 for (int i = 0; i < p3bm.length; i++) {
177 messages.add("Pass 3b, method " + meth + " ('"
178 + org.apache.bcel.Repository.lookupClass(classname).getMethods()[meth]
179 + "'): " + p3bm[i]);
180 }
181 }
182 String[] ret = new String[messages.size()];
183 for (int i = 0; i < messages.size(); i++) {
184 ret[i] = (String) messages.get(i);
185 }
186 return ret;
187 }
188
189
190 /***
191 * Verifies class files.
192 * This is a simple demonstration of how the API of BCEL's
193 * class file verifier "JustIce" may be used.
194 * You should supply command-line arguments which are
195 * fully qualified namea of the classes to verify. These class files
196 * must be somewhere in your CLASSPATH (refer to Sun's
197 * documentation for questions about this) or you must have put the classes
198 * into the BCEL Repository yourself (via 'addClass(JavaClass)').
199 */
200 public static void main( String[] args ) {
201 System.out
202 .println("JustIce by Enver Haase, (C) 2001-2002.\n<http://bcel.sourceforge.net>\n<http://jakarta.apache.org/bcel>\n");
203 for (int k = 0; k < args.length; k++) {
204 try {
205 if (args[k].endsWith(".class")) {
206 int dotclasspos = args[k].lastIndexOf(".class");
207 if (dotclasspos != -1) {
208 args[k] = args[k].substring(0, dotclasspos);
209 }
210 }
211 args[k] = args[k].replace('/', '.');
212 System.out.println("Now verifying: " + args[k] + "\n");
213 Verifier v = VerifierFactory.getVerifier(args[k]);
214 VerificationResult vr;
215 vr = v.doPass1();
216 System.out.println("Pass 1:\n" + vr);
217 vr = v.doPass2();
218 System.out.println("Pass 2:\n" + vr);
219 if (vr == VerificationResult.VR_OK) {
220 JavaClass jc = org.apache.bcel.Repository.lookupClass(args[k]);
221 for (int i = 0; i < jc.getMethods().length; i++) {
222 vr = v.doPass3a(i);
223 System.out.println("Pass 3a, method number " + i + " ['"
224 + jc.getMethods()[i] + "']:\n" + vr);
225 vr = v.doPass3b(i);
226 System.out.println("Pass 3b, method number " + i + " ['"
227 + jc.getMethods()[i] + "']:\n" + vr);
228 }
229 }
230 System.out.println("Warnings:");
231 String[] warnings = v.getMessages();
232 if (warnings.length == 0) {
233 System.out.println("<none>");
234 }
235 for (int j = 0; j < warnings.length; j++) {
236 System.out.println(warnings[j]);
237 }
238 System.out.println("\n");
239
240 v.flush();
241 org.apache.bcel.Repository.clearCache();
242 System.gc();
243 } catch (ClassNotFoundException e) {
244 e.printStackTrace();
245 }
246 }
247 }
248 }