KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > libraries > asm > util > TraceClassVisitor


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000,2002,2003 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
31 package oracle.toplink.libraries.asm.util;
32
33 import java.io.FileInputStream JavaDoc;
34 import java.io.PrintWriter JavaDoc;
35
36 import oracle.toplink.libraries.asm.Attribute;
37 import oracle.toplink.libraries.asm.ClassReader;
38 import oracle.toplink.libraries.asm.ClassVisitor;
39 import oracle.toplink.libraries.asm.CodeVisitor;
40 import oracle.toplink.libraries.asm.Constants;
41
42 /**
43  * A {@link PrintClassVisitor PrintClassVisitor} that prints a disassembled
44  * view of the classes it visits. This class visitor can be used alone (see the
45  * {@link #main main} method) to disassemble a class. It can also be used in
46  * the middle of class visitor chain to trace the class that is visited at a
47  * given point in this chain. This may be uselful for debugging purposes.
48  * <p>
49  * The trace printed when visiting the <tt>Hello</tt> class is the following:
50  * <p>
51  * <blockquote>
52  * <pre>
53  * // compiled from Hello.java
54  * public class Hello {
55  *
56  * public static main ([Ljava/lang/String;)V
57  * GETSTATIC java/lang/System out Ljava/io/PrintStream;
58  * LDC "hello"
59  * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
60  * RETURN
61  * MAXSTACK = 2
62  * MAXLOCALS = 1
63  *
64  * public &lt;init&gt; ()V
65  * ALOAD 0
66  * INVOKESPECIAL java/lang/Object &lt;init&gt; ()V
67  * RETURN
68  * MAXSTACK = 1
69  * MAXLOCALS = 1
70  *
71  * }
72  * </pre>
73  * </blockquote>
74  * where <tt>Hello</tt> is defined by:
75  * <p>
76  * <blockquote>
77  * <pre>
78  * public class Hello {
79  *
80  * public static void main (String[] args) {
81  * System.out.println("hello");
82  * }
83  * }
84  * </pre>
85  * </blockquote>
86  *
87  * @author Eric Bruneton, Eugene Kuleshov
88  */

89
90 public class TraceClassVisitor extends PrintClassVisitor {
91
92   /**
93    * The {@link ClassVisitor ClassVisitor} to which this visitor delegates
94    * calls. May be <tt>null</tt>.
95    */

96
97   protected final ClassVisitor cv;
98
99   /**
100    * Prints a disassembled view of the given class to the standard output.
101    * <p>
102    * Usage: TraceClassVisitor [-debug]
103    * &lt;fully qualified class name or class file name &gt;
104    *
105    * @param args the command line arguments.
106    *
107    * @throws Exception if the class cannot be found, or if an IO exception
108    * occurs.
109    */

110
111   public static void main (final String JavaDoc[] args) throws Exception JavaDoc {
112     if (args.length < 1 || args.length > 2) {
113       printUsage();
114     }
115     int i = 0;
116     boolean skipDebug = true;
117     if (args[0].equals("-debug")) {
118       i = 1;
119       skipDebug = false;
120       if (args.length != 2) {
121         printUsage();
122       }
123     }
124     ClassReader cr;
125     if (args[i].endsWith(".class")) {
126       cr = new ClassReader(new FileInputStream JavaDoc(args[i]));
127     } else {
128       cr = new ClassReader(args[i]);
129     }
130     cr.accept(new TraceClassVisitor(
131       null, new PrintWriter JavaDoc(System.out)), getDefaultAttributes(), skipDebug);
132   }
133   
134   private static void printUsage () {
135     System.err.println("Prints a disassembled view of the given class.");
136     System.err.println("Usage: TraceClassVisitor [-debug] " +
137                        "<fully qualified class name or class file name>");
138     System.exit(-1);
139   }
140   
141   /**
142    * Constructs a new {@link TraceClassVisitor TraceClassVisitor} object.
143    *
144    * @param cv the class visitor to which this adapter must delegate calls. May
145    * be <tt>null</tt>.
146    * @param pw the print writer to be used to print the class.
147    */

148
149   public TraceClassVisitor (final ClassVisitor cv, final PrintWriter JavaDoc pw) {
150     super(pw);
151     this.cv = cv;
152   }
153
154   public void visit (
155     final int version,
156     final int access,
157     final String JavaDoc name,
158     final String JavaDoc superName,
159     final String JavaDoc[] interfaces,
160     final String JavaDoc sourceFile)
161   {
162     int major = version & 0xFFFF;
163     int minor = version >>> 16;
164     buf.setLength(0);
165     buf.append("// class version " + major + "." + minor + " (" + version + ")\n");
166     if ((access & Constants.ACC_DEPRECATED) != 0) {
167       buf.append("// DEPRECATED\n");
168     }
169     if (sourceFile != null) {
170       buf.append("// compiled from ").append(sourceFile).append("\n");
171     }
172     buf.append("// access flags ").append(access).append("\n");
173     appendAccess(access & ~Constants.ACC_SUPER);
174     if ((access & Constants.ACC_ANNOTATION) != 0) {
175       buf.append("@interface ");
176     } else if ((access & Constants.ACC_INTERFACE) != 0) {
177         buf.append("interface ");
178     } else if ((access & Constants.ACC_ENUM) != 0) {
179       buf.append("enum ");
180     } else {
181       buf.append("class ");
182     }
183     buf.append(name).append(" ");
184     if (superName != null && !superName.equals("java/lang/Object")) {
185       buf.append("extends ").append(superName).append(" ");
186     }
187     if (interfaces != null && interfaces.length > 0) {
188       buf.append("implements ");
189       for (int i = 0; i < interfaces.length; ++i) {
190         buf.append(interfaces[i]).append(" ");
191       }
192     }
193     buf.append("{\n\n");
194     text.add(buf.toString());
195
196     if (cv != null) {
197       cv.visit(version, access, name, superName, interfaces, sourceFile);
198     }
199   }
200
201   public void visitInnerClass (
202     final String JavaDoc name,
203     final String JavaDoc outerName,
204     final String JavaDoc innerName,
205     final int access)
206   {
207     buf.setLength(0);
208     buf.append(" INNERCLASS ")
209       .append(name)
210       .append(" ")
211       .append(outerName)
212       .append(" ")
213       .append(innerName)
214       .append(" ");
215     appendAccess(access & ~Constants.ACC_SUPER);
216     if ((access & Constants.ACC_ENUM) != 0) {
217       buf.append("enum ");
218     }
219     buf.append("\n");
220     text.add(buf.toString());
221
222     if (cv != null) {
223       cv.visitInnerClass(name, outerName, innerName, access);
224     }
225   }
226
227   public void visitField (
228     final int access,
229     final String JavaDoc name,
230     final String JavaDoc desc,
231     final Object JavaDoc value,
232     final Attribute attrs)
233   {
234     buf.setLength(0);
235     if ((access & Constants.ACC_DEPRECATED) != 0) {
236       buf.append(" // DEPRECATED\n");
237     }
238     buf.append(" // access flags ").append(access).append("\n");
239     buf.append(" ");
240     appendAccess(access);
241     if ((access & Constants.ACC_ENUM) != 0) {
242       buf.append("enum ");
243     }
244     buf.append(desc)
245       .append(" ")
246       .append(name);
247     if (value != null) {
248       buf.append(" = ");
249       if (value instanceof String JavaDoc) {
250         buf.append("\"").append(value).append("\"");
251       } else {
252         buf.append(value);
253       }
254     }
255     Attribute attr = attrs;
256     while (attr != null) {
257       buf.append(" FIELD ATTRIBUTE ").append(attr.type).append(" : ")
258         .append(attr.toString()).append("\n");
259       attr = attr.next;
260     }
261     buf.append("\n");
262     text.add(buf.toString());
263
264     if (cv != null) {
265       cv.visitField(access, name, desc, value, attrs);
266     }
267   }
268
269   public CodeVisitor visitMethod (
270     final int access,
271     final String JavaDoc name,
272     final String JavaDoc desc,
273     final String JavaDoc[] exceptions,
274     final Attribute attrs)
275   {
276     buf.setLength(0);
277     if ((access & Constants.ACC_DEPRECATED) != 0) {
278       buf.append(" // DEPRECATED\n");
279     }
280     buf.append(" // access flags ").append(access).append("\n");
281     buf.append(" ");
282     appendAccess(access);
283     if ((access & Constants.ACC_NATIVE) != 0) {
284       buf.append("native ");
285     }
286     if ((access & Constants.ACC_VARARGS) != 0) {
287       buf.append("varargs ");
288     }
289     if ((access & Constants.ACC_BRIDGE) != 0) {
290       buf.append("bridge ");
291     }
292     buf.append(name).
293       append(" ").
294       append(desc);
295     if (exceptions != null && exceptions.length > 0) {
296       buf.append(" throws ");
297       for (int i = 0; i < exceptions.length; ++i) {
298         buf.append(exceptions[i]).append(" ");
299       }
300     }
301     buf.append("\n");
302     text.add(buf.toString());
303     Attribute attr = attrs;
304     while (attr != null) {
305       buf.setLength(0);
306       buf.append(" METHOD ATTRIBUTE ").append(attr.type).append(" : ")
307         .append(attr.toString()).append("\n");
308       text.add(buf.toString());
309       attr = attr.next;
310     }
311
312     CodeVisitor cv;
313     if (this.cv != null) {
314       cv = this.cv.visitMethod(access, name, desc, exceptions, attrs);
315     } else {
316       cv = null;
317     }
318     PrintCodeVisitor pcv = new TraceCodeVisitor(cv);
319     text.add(pcv.getText());
320     return pcv;
321   }
322
323   public void visitAttribute (final Attribute attr) {
324     buf.setLength(0);
325     buf.append(" CLASS ATTRIBUTE ").append(attr.type).append(" : ")
326       .append(attr.toString()).append("\n");
327     text.add(buf.toString());
328
329     if (cv != null) {
330       cv.visitAttribute(attr);
331     }
332   }
333
334   public void visitEnd () {
335     text.add("}\n");
336
337     if (cv != null) {
338       cv.visitEnd();
339     }
340
341     super.visitEnd();
342   }
343
344   /**
345    * Appends a string representation of the given access modifiers to {@link
346    * #buf buf}.
347    *
348    * @param access some access modifiers.
349    */

350
351   private void appendAccess (final int access) {
352     if ((access & Constants.ACC_PUBLIC) != 0) {
353       buf.append("public ");
354     }
355     if ((access & Constants.ACC_PRIVATE) != 0) {
356       buf.append("private ");
357     }
358     if ((access & Constants.ACC_PROTECTED) != 0) {
359       buf.append("protected ");
360     }
361     if ((access & Constants.ACC_FINAL) != 0) {
362       buf.append("final ");
363     }
364     if ((access & Constants.ACC_STATIC) != 0) {
365       buf.append("static ");
366     }
367     if ((access & Constants.ACC_SYNCHRONIZED) != 0) {
368       buf.append("synchronized ");
369     }
370     if ((access & Constants.ACC_VOLATILE) != 0) {
371       buf.append("volatile ");
372     }
373     if ((access & Constants.ACC_TRANSIENT) != 0) {
374       buf.append("transient ");
375     }
376     // if ((access & Constants.ACC_NATIVE) != 0) {
377
// buf.append("native ");
378
// }
379
if ((access & Constants.ACC_ABSTRACT) != 0) {
380       buf.append("abstract ");
381     }
382     if ((access & Constants.ACC_STRICT) != 0) {
383       buf.append("strictfp ");
384     }
385   }
386 }
387
Popular Tags