KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > asm > util > TraceMethodVisitor


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 com.tc.asm.AnnotationVisitor;
33 import com.tc.asm.Attribute;
34 import com.tc.asm.MethodVisitor;
35 import com.tc.asm.Label;
36 import com.tc.asm.Opcodes;
37 import com.tc.asm.Type;
38 import com.tc.asm.signature.SignatureReader;
39 import com.tc.asm.util.attrs.Traceable;
40
41 import java.util.HashMap JavaDoc;
42
43 /**
44  * A {@link MethodVisitor} that prints a disassembled view of the methods it
45  * visits.
46  *
47  * @author Eric Bruneton
48  */

49 public class TraceMethodVisitor extends TraceAbstractVisitor implements
50         MethodVisitor
51 {
52
53     /**
54      * The {@link MethodVisitor} to which this visitor delegates calls. May be
55      * <tt>null</tt>.
56      */

57     protected MethodVisitor mv;
58
59     /**
60      * Tab for bytecode instructions.
61      */

62     protected String JavaDoc tab2 = " ";
63
64     /**
65      * Tab for table and lookup switch instructions.
66      */

67     protected String JavaDoc tab3 = " ";
68
69     /**
70      * Tab for labels.
71      */

72     protected String JavaDoc ltab = " ";
73
74     /**
75      * The label names. This map associate String values to Label keys.
76      */

77     protected final HashMap JavaDoc labelNames;
78
79     /**
80      * Constructs a new {@link TraceMethodVisitor}.
81      */

82     public TraceMethodVisitor() {
83         this(null);
84     }
85
86     /**
87      * Constructs a new {@link TraceMethodVisitor}.
88      *
89      * @param mv the {@link MethodVisitor} to which this visitor delegates
90      * calls. May be <tt>null</tt>.
91      */

92     public TraceMethodVisitor(final MethodVisitor mv) {
93         this.labelNames = new HashMap JavaDoc();
94         this.mv = mv;
95     }
96
97     // ------------------------------------------------------------------------
98
// Implementation of the MethodVisitor interface
99
// ------------------------------------------------------------------------
100

101     public AnnotationVisitor visitAnnotation(
102         final String JavaDoc desc,
103         final boolean visible)
104     {
105         AnnotationVisitor av = super.visitAnnotation(desc, visible);
106         if (mv != null) {
107             ((TraceAnnotationVisitor) av).av = mv.visitAnnotation(desc, visible);
108         }
109         return av;
110     }
111
112     public void visitAttribute(final Attribute attr) {
113         buf.setLength(0);
114         buf.append(tab).append("ATTRIBUTE ");
115         appendDescriptor(-1, attr.type);
116
117         if (attr instanceof Traceable) {
118             ((Traceable) attr).trace(buf, labelNames);
119         } else {
120             buf.append(" : ").append(attr.toString()).append("\n");
121         }
122
123         text.add(buf.toString());
124         if (mv != null) {
125             mv.visitAttribute(attr);
126         }
127     }
128
129     public AnnotationVisitor visitAnnotationDefault() {
130         text.add(tab2 + "default=");
131         TraceAnnotationVisitor tav = new TraceAnnotationVisitor();
132         text.add(tav.getText());
133         text.add("\n");
134         if (mv != null) {
135             tav.av = mv.visitAnnotationDefault();
136         }
137         return tav;
138     }
139
140     public AnnotationVisitor visitParameterAnnotation(
141         final int parameter,
142         final String JavaDoc desc,
143         final boolean visible)
144     {
145         buf.setLength(0);
146         buf.append(tab2).append('@');
147         appendDescriptor(FIELD_DESCRIPTOR, desc);
148         buf.append('(');
149         text.add(buf.toString());
150         TraceAnnotationVisitor tav = new TraceAnnotationVisitor();
151         text.add(tav.getText());
152         text.add(visible ? ") // parameter " : ") // invisible, parameter ");
153         text.add(new Integer JavaDoc(parameter));
154         text.add("\n");
155         if (mv != null) {
156             tav.av = mv.visitParameterAnnotation(parameter, desc, visible);
157         }
158         return tav;
159     }
160
161     public void visitCode() {
162         if (mv != null) {
163             mv.visitCode();
164         }
165     }
166
167     public void visitInsn(final int opcode) {
168         buf.setLength(0);
169         buf.append(tab2).append(OPCODES[opcode]).append('\n');
170         text.add(buf.toString());
171
172         if (mv != null) {
173             mv.visitInsn(opcode);
174         }
175     }
176
177     public void visitIntInsn(final int opcode, final int operand) {
178         buf.setLength(0);
179         buf.append(tab2)
180                 .append(OPCODES[opcode])
181                 .append(' ')
182                 .append(opcode == Opcodes.NEWARRAY
183                         ? TYPES[operand]
184                         : Integer.toString(operand))
185                 .append('\n');
186         text.add(buf.toString());
187
188         if (mv != null) {
189             mv.visitIntInsn(opcode, operand);
190         }
191     }
192
193     public void visitVarInsn(final int opcode, final int var) {
194         buf.setLength(0);
195         buf.append(tab2)
196                 .append(OPCODES[opcode])
197                 .append(' ')
198                 .append(var)
199                 .append('\n');
200         text.add(buf.toString());
201
202         if (mv != null) {
203             mv.visitVarInsn(opcode, var);
204         }
205     }
206
207     public void visitTypeInsn(final int opcode, final String JavaDoc desc) {
208         buf.setLength(0);
209         buf.append(tab2).append(OPCODES[opcode]).append(' ');
210         if (desc.startsWith("[")) {
211             appendDescriptor(FIELD_DESCRIPTOR, desc);
212         } else {
213             appendDescriptor(INTERNAL_NAME, desc);
214         }
215         buf.append('\n');
216         text.add(buf.toString());
217
218         if (mv != null) {
219             mv.visitTypeInsn(opcode, desc);
220         }
221     }
222
223     public void visitFieldInsn(
224         final int opcode,
225         final String JavaDoc owner,
226         final String JavaDoc name,
227         final String JavaDoc desc)
228     {
229         buf.setLength(0);
230         buf.append(tab2).append(OPCODES[opcode]).append(' ');
231         appendDescriptor(INTERNAL_NAME, owner);
232         buf.append('.').append(name).append(" : ");
233         appendDescriptor(FIELD_DESCRIPTOR, desc);
234         buf.append('\n');
235         text.add(buf.toString());
236
237         if (mv != null) {
238             mv.visitFieldInsn(opcode, owner, name, desc);
239         }
240     }
241
242     public void visitMethodInsn(
243         final int opcode,
244         final String JavaDoc owner,
245         final String JavaDoc name,
246         final String JavaDoc desc)
247     {
248         buf.setLength(0);
249         buf.append(tab2).append(OPCODES[opcode]).append(' ');
250         appendDescriptor(INTERNAL_NAME, owner);
251         buf.append('.').append(name).append(' ');
252         appendDescriptor(METHOD_DESCRIPTOR, desc);
253         buf.append('\n');
254         text.add(buf.toString());
255
256         if (mv != null) {
257             mv.visitMethodInsn(opcode, owner, name, desc);
258         }
259     }
260
261     public void visitJumpInsn(final int opcode, final Label label) {
262         buf.setLength(0);
263         buf.append(tab2).append(OPCODES[opcode]).append(' ');
264         appendLabel(label);
265         buf.append('\n');
266         text.add(buf.toString());
267
268         if (mv != null) {
269             mv.visitJumpInsn(opcode, label);
270         }
271     }
272
273     public void visitLabel(final Label label) {
274         buf.setLength(0);
275         buf.append(ltab);
276         appendLabel(label);
277         buf.append('\n');
278         text.add(buf.toString());
279
280         if (mv != null) {
281             mv.visitLabel(label);
282         }
283     }
284
285     public void visitLdcInsn(final Object JavaDoc cst) {
286         buf.setLength(0);
287         buf.append(tab2).append("LDC ");
288         if (cst instanceof String JavaDoc) {
289             AbstractVisitor.appendString(buf, (String JavaDoc) cst);
290         } else if (cst instanceof Type) {
291             buf.append(((Type) cst).getDescriptor() + ".class");
292         } else {
293             buf.append(cst);
294         }
295         buf.append('\n');
296         text.add(buf.toString());
297
298         if (mv != null) {
299             mv.visitLdcInsn(cst);
300         }
301     }
302
303     public void visitIincInsn(final int var, final int increment) {
304         buf.setLength(0);
305         buf.append(tab2)
306                 .append("IINC ")
307                 .append(var)
308                 .append(' ')
309                 .append(increment)
310                 .append('\n');
311         text.add(buf.toString());
312
313         if (mv != null) {
314             mv.visitIincInsn(var, increment);
315         }
316     }
317
318     public void visitTableSwitchInsn(
319         final int min,
320         final int max,
321         final Label dflt,
322         final Label labels[])
323     {
324         buf.setLength(0);
325         buf.append(tab2).append("TABLESWITCH\n");
326         for (int i = 0; i < labels.length; ++i) {
327             buf.append(tab3).append(min + i).append(": ");
328             appendLabel(labels[i]);
329             buf.append('\n');
330         }
331         buf.append(tab3).append("default: ");
332         appendLabel(dflt);
333         buf.append('\n');
334         text.add(buf.toString());
335
336         if (mv != null) {
337             mv.visitTableSwitchInsn(min, max, dflt, labels);
338         }
339     }
340
341     public void visitLookupSwitchInsn(
342         final Label dflt,
343         final int keys[],
344         final Label labels[])
345     {
346         buf.setLength(0);
347         buf.append(tab2).append("LOOKUPSWITCH\n");
348         for (int i = 0; i < labels.length; ++i) {
349             buf.append(tab3).append(keys[i]).append(": ");
350             appendLabel(labels[i]);
351             buf.append('\n');
352         }
353         buf.append(tab3).append("default: ");
354         appendLabel(dflt);
355         buf.append('\n');
356         text.add(buf.toString());
357
358         if (mv != null) {
359             mv.visitLookupSwitchInsn(dflt, keys, labels);
360         }
361     }
362
363     public void visitMultiANewArrayInsn(final String JavaDoc desc, final int dims) {
364         buf.setLength(0);
365         buf.append(tab2).append("MULTIANEWARRAY ");
366         appendDescriptor(FIELD_DESCRIPTOR, desc);
367         buf.append(' ').append(dims).append('\n');
368         text.add(buf.toString());
369
370         if (mv != null) {
371             mv.visitMultiANewArrayInsn(desc, dims);
372         }
373     }
374
375     public void visitTryCatchBlock(
376         final Label start,
377         final Label end,
378         final Label handler,
379         final String JavaDoc type)
380     {
381         buf.setLength(0);
382         buf.append(tab2).append("TRYCATCHBLOCK ");
383         appendLabel(start);
384         buf.append(' ');
385         appendLabel(end);
386         buf.append(' ');
387         appendLabel(handler);
388         buf.append(' ');
389         appendDescriptor(INTERNAL_NAME, type);
390         buf.append('\n');
391         text.add(buf.toString());
392
393         if (mv != null) {
394             mv.visitTryCatchBlock(start, end, handler, type);
395         }
396     }
397
398     public void visitLocalVariable(
399         final String JavaDoc name,
400         final String JavaDoc desc,
401         final String JavaDoc signature,
402         final Label start,
403         final Label end,
404         final int index)
405     {
406         buf.setLength(0);
407         buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
408         appendDescriptor(FIELD_DESCRIPTOR, desc);
409         buf.append(' ');
410         appendLabel(start);
411         buf.append(' ');
412         appendLabel(end);
413         buf.append(' ').append(index).append('\n');
414
415         if (signature != null) {
416             buf.append(tab2);
417             appendDescriptor(FIELD_SIGNATURE, signature);
418
419             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
420             SignatureReader r = new SignatureReader(signature);
421             r.acceptType(sv);
422             buf.append(tab2)
423                     .append("// declaration: ")
424                     .append(sv.getDeclaration())
425                     .append('\n');
426         }
427         text.add(buf.toString());
428
429         if (mv != null) {
430             mv.visitLocalVariable(name, desc, signature, start, end, index);
431         }
432     }
433
434     public void visitLineNumber(final int line, final Label start) {
435         buf.setLength(0);
436         buf.append(tab2).append("LINENUMBER ").append(line).append(' ');
437         appendLabel(start);
438         buf.append('\n');
439         text.add(buf.toString());
440
441         if (mv != null) {
442             mv.visitLineNumber(line, start);
443         }
444     }
445
446     public void visitMaxs(final int maxStack, final int maxLocals) {
447         buf.setLength(0);
448         buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n');
449         text.add(buf.toString());
450
451         buf.setLength(0);
452         buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n');
453         text.add(buf.toString());
454
455         if (mv != null) {
456             mv.visitMaxs(maxStack, maxLocals);
457         }
458     }
459
460     public void visitEnd() {
461         super.visitEnd();
462
463         if (mv != null) {
464             mv.visitEnd();
465         }
466     }
467
468     // ------------------------------------------------------------------------
469
// Utility methods
470
// ------------------------------------------------------------------------
471

472     /**
473      * Appends the name of the given label to {@link #buf buf}. Creates a new
474      * label name if the given label does not yet have one.
475      *
476      * @param l a label.
477      */

478     public void appendLabel(final Label l) {
479         String JavaDoc name = (String JavaDoc) labelNames.get(l);
480         if (name == null) {
481             name = "L" + labelNames.size();
482             labelNames.put(l, name);
483         }
484         buf.append(name);
485     }
486 }
487
Popular Tags