KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > asm > util > TraceClassVisitor


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

94 public class TraceClassVisitor extends TraceAbstractVisitor implements
95         ClassVisitor
96 {
97
98     /**
99      * The {@link ClassVisitor} to which this visitor delegates calls. May be
100      * <tt>null</tt>.
101      */

102     protected final ClassVisitor cv;
103
104     /**
105      * The print writer to be used to print the class.
106      */

107     protected final PrintWriter JavaDoc pw;
108
109     /**
110      * Prints a disassembled view of the given class to the standard output. <p>
111      * Usage: TraceClassVisitor [-debug] &lt;fully qualified class name or class
112      * file name &gt;
113      *
114      * @param args the command line arguments.
115      *
116      * @throws Exception if the class cannot be found, or if an IO exception
117      * occurs.
118      */

119     public static void main(final String JavaDoc[] args) throws Exception JavaDoc {
120         int i = 0;
121         boolean skipDebug = true;
122
123         boolean ok = true;
124         if (args.length < 1 || args.length > 2) {
125             ok = false;
126         }
127         if (ok && args[0].equals("-debug")) {
128             i = 1;
129             skipDebug = false;
130             if (args.length != 2) {
131                 ok = false;
132             }
133         }
134         if (!ok) {
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         ClassReader cr;
141         if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
142                 || args[i].indexOf('/') > -1)
143         {
144             cr = new ClassReader(new FileInputStream JavaDoc(args[i]));
145         } else {
146             cr = new ClassReader(args[i]);
147         }
148         cr.accept(new TraceClassVisitor(new PrintWriter JavaDoc(System.out)),
149                 getDefaultAttributes(),
150                 skipDebug);
151     }
152
153     /**
154      * Constructs a new {@link TraceClassVisitor}.
155      *
156      * @param pw the print writer to be used to print the class.
157      */

158     public TraceClassVisitor(final PrintWriter JavaDoc pw) {
159         this(null, pw);
160     }
161
162     /**
163      * Constructs a new {@link TraceClassVisitor}.
164      *
165      * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
166      * May be <tt>null</tt>.
167      * @param pw the print writer to be used to print the class.
168      */

169     public TraceClassVisitor(final ClassVisitor cv, final PrintWriter JavaDoc pw) {
170         this.cv = cv;
171         this.pw = pw;
172     }
173
174     // ------------------------------------------------------------------------
175
// Implementation of the ClassVisitor interface
176
// ------------------------------------------------------------------------
177

178     public void visit(
179         final int version,
180         final int access,
181         final String JavaDoc name,
182         final String JavaDoc signature,
183         final String JavaDoc superName,
184         final String JavaDoc[] interfaces)
185     {
186         int major = version & 0xFFFF;
187         int minor = version >>> 16;
188         buf.setLength(0);
189         buf.append("// class version ")
190                 .append(major)
191                 .append('.')
192                 .append(minor)
193                 .append(" (")
194                 .append(version)
195                 .append(")\n");
196         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
197             buf.append("// DEPRECATED\n");
198         }
199         buf.append("// access flags ").append(access).append('\n');
200
201         appendDescriptor(CLASS_SIGNATURE, signature);
202         if (signature != null) {
203             TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
204             SignatureReader r = new SignatureReader(signature);
205             r.accept(sv);
206             buf.append("// declaration: ")
207                     .append(name)
208                     .append(sv.getDeclaration())
209                     .append('\n');
210         }
211
212         appendAccess(access & ~Opcodes.ACC_SUPER);
213         if ((access & Opcodes.ACC_ANNOTATION) != 0) {
214             buf.append("@interface ");
215         } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
216             buf.append("interface ");
217         } else if ((access & Opcodes.ACC_ENUM) != 0) {
218             buf.append("enum ");
219         } else {
220             buf.append("class ");
221         }
222         appendDescriptor(INTERNAL_NAME, name);
223
224         if (superName != null && !superName.equals("java/lang/Object")) {
225             buf.append(" extends ");
226             appendDescriptor(INTERNAL_NAME, superName);
227             buf.append(' ');
228         }
229         if (interfaces != null && interfaces.length > 0) {
230             buf.append(" implements ");
231             for (int i = 0; i < interfaces.length; ++i) {
232                 appendDescriptor(INTERNAL_NAME, interfaces[i]);
233                 buf.append(' ');
234             }
235         }
236         buf.append(" {\n\n");
237
238         text.add(buf.toString());
239
240         if (cv != null) {
241             cv.visit(version, access, name, signature, superName, interfaces);
242         }
243     }
244
245     public void visitSource(final String JavaDoc file, final String JavaDoc debug) {
246         buf.setLength(0);
247         if (file != null) {
248             buf.append(tab)
249                     .append("// compiled from: ")
250                     .append(file)
251                     .append('\n');
252         }
253         if (debug != null) {
254             buf.append(tab)
255                     .append("// debug info: ")
256                     .append(debug)
257                     .append('\n');
258         }
259         if (buf.length() > 0) {
260             text.add(buf.toString());
261         }
262
263         if (cv != null) {
264             cv.visitSource(file, debug);
265         }
266     }
267
268     public void visitOuterClass(
269         final String JavaDoc owner,
270         final String JavaDoc name,
271         final String JavaDoc desc)
272     {
273         buf.setLength(0);
274         buf.append(tab).append("OUTERCLASS ");
275         appendDescriptor(INTERNAL_NAME, owner);
276         buf.append(' ').append(name).append(' ');
277         appendDescriptor(METHOD_DESCRIPTOR, desc);
278         buf.append('\n');
279         text.add(buf.toString());
280
281         if (cv != null) {
282             cv.visitOuterClass(owner, name, desc);
283         }
284     }
285
286     public AnnotationVisitor visitAnnotation(
287         final String JavaDoc desc,
288         final boolean visible)
289     {
290         text.add("\n");
291         AnnotationVisitor tav = super.visitAnnotation(desc, visible);
292         if (cv != null) {
293             ((TraceAnnotationVisitor) tav).av = cv.visitAnnotation(desc,
294                     visible);
295         }
296         return tav;
297     }
298
299     public void visitAttribute(final Attribute attr) {
300         text.add("\n");
301         super.visitAttribute(attr);
302
303         if (cv != null) {
304             cv.visitAttribute(attr);
305         }
306     }
307
308     public void visitInnerClass(
309         final String JavaDoc name,
310         final String JavaDoc outerName,
311         final String JavaDoc innerName,
312         final int access)
313     {
314         buf.setLength(0);
315         buf.append(tab).append("INNERCLASS ");
316         appendDescriptor(INTERNAL_NAME, name);
317         buf.append(' ');
318         appendDescriptor(INTERNAL_NAME, outerName);
319         buf.append(' ');
320         appendDescriptor(INTERNAL_NAME, innerName);
321         buf.append(' ').append(access & ~Opcodes.ACC_SUPER);
322         if ((access & Opcodes.ACC_ENUM) != 0) {
323             buf.append("enum ");
324         }
325         buf.append('\n');
326         text.add(buf.toString());
327
328         if (cv != null) {
329             cv.visitInnerClass(name, outerName, innerName, access);
330         }
331     }
332
333     public FieldVisitor visitField(
334         final int access,
335         final String JavaDoc name,
336         final String JavaDoc desc,
337         final String JavaDoc signature,
338         final Object JavaDoc value)
339     {
340         buf.setLength(0);
341         buf.append('\n');
342         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
343             buf.append(tab).append("// DEPRECATED\n");
344         }
345         buf.append(tab).append("// access flags ").append(access).append('\n');
346         if (signature != null) {
347             buf.append(tab);
348             appendDescriptor(FIELD_SIGNATURE, signature);
349
350             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
351             SignatureReader r = new SignatureReader(signature);
352             r.acceptType(sv);
353             buf.append(tab)
354                     .append("// declaration: ")
355                     .append(sv.getDeclaration())
356                     .append('\n');
357         }
358
359         buf.append(tab);
360         appendAccess(access);
361         if ((access & Opcodes.ACC_ENUM) != 0) {
362             buf.append("enum ");
363         }
364
365         appendDescriptor(FIELD_DESCRIPTOR, desc);
366         buf.append(' ').append(name);
367         if (value != null) {
368             buf.append(" = ");
369             if (value instanceof String JavaDoc) {
370                 buf.append("\"").append(value).append("\"");
371             } else {
372                 buf.append(value);
373             }
374         }
375
376         buf.append('\n');
377         text.add(buf.toString());
378
379         TraceFieldVisitor tav = createTraceFieldVisitor();
380         text.add(tav.getText());
381
382         if (cv != null) {
383             tav.fv = cv.visitField(access, name, desc, signature, value);
384         }
385
386         return tav;
387     }
388
389     public MethodVisitor visitMethod(
390         final int access,
391         final String JavaDoc name,
392         final String JavaDoc desc,
393         final String JavaDoc signature,
394         final String JavaDoc[] exceptions)
395     {
396         buf.setLength(0);
397         buf.append('\n');
398         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
399             buf.append(tab).append("// DEPRECATED\n");
400         }
401         buf.append(tab).append("// access flags ").append(access).append('\n');
402         buf.append(tab);
403         appendDescriptor(METHOD_SIGNATURE, signature);
404
405         if (signature != null) {
406             TraceSignatureVisitor v = new TraceSignatureVisitor(0);
407             SignatureReader r = new SignatureReader(signature);
408             r.accept(v);
409             String JavaDoc genericDecl = v.getDeclaration();
410             String JavaDoc genericReturn = v.getReturnType();
411             String JavaDoc genericExceptions = v.getExceptions();
412
413             buf.append(tab)
414                     .append("// declaration: ")
415                     .append(genericReturn)
416                     .append(' ')
417                     .append(name)
418                     .append(genericDecl);
419             if (genericExceptions != null) {
420                 buf.append(" throws ").append(genericExceptions);
421             }
422             buf.append('\n');
423         }
424
425         appendAccess(access);
426         if ((access & Opcodes.ACC_NATIVE) != 0) {
427             buf.append("native ");
428         }
429         if ((access & Opcodes.ACC_VARARGS) != 0) {
430             buf.append("varargs ");
431         }
432         if ((access & Opcodes.ACC_BRIDGE) != 0) {
433             buf.append("bridge ");
434         }
435
436         buf.append(name);
437         appendDescriptor(METHOD_DESCRIPTOR, desc);
438         if (exceptions != null && exceptions.length > 0) {
439             buf.append(" throws ");
440             for (int i = 0; i < exceptions.length; ++i) {
441                 appendDescriptor(INTERNAL_NAME, exceptions[i]);
442                 buf.append(' ');
443             }
444         }
445
446         buf.append('\n');
447         text.add(buf.toString());
448
449         TraceMethodVisitor tcv = createTraceMethodVisitor();
450         text.add(tcv.getText());
451
452         if (cv != null) {
453             tcv.mv = cv.visitMethod(access, name, desc, signature, exceptions);
454         }
455
456         return tcv;
457     }
458
459     public void visitEnd() {
460         text.add("}\n");
461
462         printList(pw, text);
463         pw.flush();
464
465         if (cv != null) {
466             cv.visitEnd();
467         }
468     }
469
470     // ------------------------------------------------------------------------
471
// Utility methods
472
// ------------------------------------------------------------------------
473

474     protected TraceFieldVisitor createTraceFieldVisitor() {
475         return new TraceFieldVisitor();
476     }
477
478     protected TraceMethodVisitor createTraceMethodVisitor() {
479         return new TraceMethodVisitor();
480     }
481
482     /**
483      * Appends a string representation of the given access modifiers to {@link
484      * #buf buf}.
485      *
486      * @param access some access modifiers.
487      */

488     private void appendAccess(final int access) {
489         if ((access & Opcodes.ACC_PUBLIC) != 0) {
490             buf.append("public ");
491         }
492         if ((access & Opcodes.ACC_PRIVATE) != 0) {
493             buf.append("private ");
494         }
495         if ((access & Opcodes.ACC_PROTECTED) != 0) {
496             buf.append("protected ");
497         }
498         if ((access & Opcodes.ACC_FINAL) != 0) {
499             buf.append("final ");
500         }
501         if ((access & Opcodes.ACC_STATIC) != 0) {
502             buf.append("static ");
503         }
504         if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
505             buf.append("synchronized ");
506         }
507         if ((access & Opcodes.ACC_VOLATILE) != 0) {
508             buf.append("volatile ");
509         }
510         if ((access & Opcodes.ACC_TRANSIENT) != 0) {
511             buf.append("transient ");
512         }
513         // if ((access & Constants.ACC_NATIVE) != 0) {
514
// buf.append("native ");
515
// }
516
if ((access & Opcodes.ACC_ABSTRACT) != 0) {
517             buf.append("abstract ");
518         }
519         if ((access & Opcodes.ACC_STRICT) != 0) {
520             buf.append("strictfp ");
521         }
522     }
523 }
524
Popular Tags