KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > 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 com.tc.asm.util;
31
32 import java.io.FileInputStream JavaDoc;
33 import java.io.PrintWriter JavaDoc;
34
35 import com.tc.asm.AnnotationVisitor;
36 import com.tc.asm.Attribute;
37 import com.tc.asm.ClassReader;
38 import com.tc.asm.ClassVisitor;
39 import com.tc.asm.MethodVisitor;
40 import com.tc.asm.Opcodes;
41 import com.tc.asm.FieldVisitor;
42 import com.tc.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             return;
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         // if enclosing name is null, so why should we show this info?
277
if (name != null) {
278             buf.append(' ').append(name).append(' ');
279         } else {
280             buf.append(' ');
281         }
282         appendDescriptor(METHOD_DESCRIPTOR, desc);
283         buf.append('\n');
284         text.add(buf.toString());
285
286         if (cv != null) {
287             cv.visitOuterClass(owner, name, desc);
288         }
289     }
290
291     public AnnotationVisitor visitAnnotation(
292         final String JavaDoc desc,
293         final boolean visible)
294     {
295         text.add("\n");
296         AnnotationVisitor tav = super.visitAnnotation(desc, visible);
297         if (cv != null) {
298             ((TraceAnnotationVisitor) tav).av = cv.visitAnnotation(desc,
299                     visible);
300         }
301         return tav;
302     }
303
304     public void visitAttribute(final Attribute attr) {
305         text.add("\n");
306         super.visitAttribute(attr);
307
308         if (cv != null) {
309             cv.visitAttribute(attr);
310         }
311     }
312
313     public void visitInnerClass(
314         final String JavaDoc name,
315         final String JavaDoc outerName,
316         final String JavaDoc innerName,
317         final int access)
318     {
319         buf.setLength(0);
320         buf.append(tab).append("// access flags ").append(access
321                 & ~Opcodes.ACC_SUPER).append('\n');
322         buf.append(tab);
323         appendAccess(access);
324         buf.append("INNERCLASS ");
325         if ((access & Opcodes.ACC_ENUM) != 0) {
326             buf.append("enum ");
327         }
328         appendDescriptor(INTERNAL_NAME, name);
329         buf.append(' ');
330         appendDescriptor(INTERNAL_NAME, outerName);
331         buf.append(' ');
332         appendDescriptor(INTERNAL_NAME, innerName);
333         buf.append('\n');
334         text.add(buf.toString());
335
336         if (cv != null) {
337             cv.visitInnerClass(name, outerName, innerName, access);
338         }
339     }
340
341     public FieldVisitor visitField(
342         final int access,
343         final String JavaDoc name,
344         final String JavaDoc desc,
345         final String JavaDoc signature,
346         final Object JavaDoc value)
347     {
348         buf.setLength(0);
349         buf.append('\n');
350         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
351             buf.append(tab).append("// DEPRECATED\n");
352         }
353         buf.append(tab).append("// access flags ").append(access).append('\n');
354         if (signature != null) {
355             buf.append(tab);
356             appendDescriptor(FIELD_SIGNATURE, signature);
357
358             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
359             SignatureReader r = new SignatureReader(signature);
360             r.acceptType(sv);
361             buf.append(tab)
362                     .append("// declaration: ")
363                     .append(sv.getDeclaration())
364                     .append('\n');
365         }
366
367         buf.append(tab);
368         appendAccess(access);
369         if ((access & Opcodes.ACC_ENUM) != 0) {
370             buf.append("enum ");
371         }
372
373         appendDescriptor(FIELD_DESCRIPTOR, desc);
374         buf.append(' ').append(name);
375         if (value != null) {
376             buf.append(" = ");
377             if (value instanceof String JavaDoc) {
378                 buf.append("\"").append(value).append("\"");
379             } else {
380                 buf.append(value);
381             }
382         }
383
384         buf.append('\n');
385         text.add(buf.toString());
386
387         TraceFieldVisitor tav = createTraceFieldVisitor();
388         text.add(tav.getText());
389
390         if (cv != null) {
391             tav.fv = cv.visitField(access, name, desc, signature, value);
392         }
393
394         return tav;
395     }
396
397     public MethodVisitor visitMethod(
398         final int access,
399         final String JavaDoc name,
400         final String JavaDoc desc,
401         final String JavaDoc signature,
402         final String JavaDoc[] exceptions)
403     {
404         buf.setLength(0);
405         buf.append('\n');
406         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
407             buf.append(tab).append("// DEPRECATED\n");
408         }
409         buf.append(tab).append("// access flags ").append(access).append('\n');
410         buf.append(tab);
411         appendDescriptor(METHOD_SIGNATURE, signature);
412
413         if (signature != null) {
414             TraceSignatureVisitor v = new TraceSignatureVisitor(0);
415             SignatureReader r = new SignatureReader(signature);
416             r.accept(v);
417             String JavaDoc genericDecl = v.getDeclaration();
418             String JavaDoc genericReturn = v.getReturnType();
419             String JavaDoc genericExceptions = v.getExceptions();
420
421             buf.append(tab)
422                     .append("// declaration: ")
423                     .append(genericReturn)
424                     .append(' ')
425                     .append(name)
426                     .append(genericDecl);
427             if (genericExceptions != null) {
428                 buf.append(" throws ").append(genericExceptions);
429             }
430             buf.append('\n');
431         }
432
433         appendAccess(access);
434         if ((access & Opcodes.ACC_NATIVE) != 0) {
435             buf.append("native ");
436         }
437         if ((access & Opcodes.ACC_VARARGS) != 0) {
438             buf.append("varargs ");
439         }
440         if ((access & Opcodes.ACC_BRIDGE) != 0) {
441             buf.append("bridge ");
442         }
443
444         buf.append(name);
445         appendDescriptor(METHOD_DESCRIPTOR, desc);
446         if (exceptions != null && exceptions.length > 0) {
447             buf.append(" throws ");
448             for (int i = 0; i < exceptions.length; ++i) {
449                 appendDescriptor(INTERNAL_NAME, exceptions[i]);
450                 buf.append(' ');
451             }
452         }
453
454         buf.append('\n');
455         text.add(buf.toString());
456
457         TraceMethodVisitor tcv = createTraceMethodVisitor();
458         text.add(tcv.getText());
459
460         if (cv != null) {
461             tcv.mv = cv.visitMethod(access, name, desc, signature, exceptions);
462         }
463
464         return tcv;
465     }
466
467     public void visitEnd() {
468         text.add("}\n");
469
470         printList(pw, text);
471         pw.flush();
472
473         if (cv != null) {
474             cv.visitEnd();
475         }
476     }
477
478     // ------------------------------------------------------------------------
479
// Utility methods
480
// ------------------------------------------------------------------------
481

482     protected TraceFieldVisitor createTraceFieldVisitor() {
483         return new TraceFieldVisitor();
484     }
485
486     protected TraceMethodVisitor createTraceMethodVisitor() {
487         return new TraceMethodVisitor();
488     }
489
490     /**
491      * Appends a string representation of the given access modifiers to {@link
492      * #buf buf}.
493      *
494      * @param access some access modifiers.
495      */

496     private void appendAccess(final int access) {
497         if ((access & Opcodes.ACC_PUBLIC) != 0) {
498             buf.append("public ");
499         }
500         if ((access & Opcodes.ACC_PRIVATE) != 0) {
501             buf.append("private ");
502         }
503         if ((access & Opcodes.ACC_PROTECTED) != 0) {
504             buf.append("protected ");
505         }
506         if ((access & Opcodes.ACC_FINAL) != 0) {
507             buf.append("final ");
508         }
509         if ((access & Opcodes.ACC_STATIC) != 0) {
510             buf.append("static ");
511         }
512         if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
513             buf.append("synchronized ");
514         }
515         if ((access & Opcodes.ACC_VOLATILE) != 0) {
516             buf.append("volatile ");
517         }
518         if ((access & Opcodes.ACC_TRANSIENT) != 0) {
519             buf.append("transient ");
520         }
521         // if ((access & Constants.ACC_NATIVE) != 0) {
522
// buf.append("native ");
523
// }
524
if ((access & Opcodes.ACC_ABSTRACT) != 0) {
525             buf.append("abstract ");
526         }
527         if ((access & Opcodes.ACC_STRICT) != 0) {
528             buf.append("strictfp ");
529         }
530         if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
531             buf.append("synthetic ");
532         }
533     }
534 }
535
Popular Tags