KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > asm > util > DumpClassVisitor


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  * Contact: Eric.Bruneton@rd.francetelecom.com
31  *
32  * Author: Eric Bruneton
33  */

34
35 package org.logicalcobwebs.asm.util;
36
37 import org.logicalcobwebs.asm.Constants;
38 import org.logicalcobwebs.asm.ClassReader;
39 import org.logicalcobwebs.asm.CodeVisitor;
40 import org.logicalcobwebs.asm.Attribute;
41
42 import java.io.PrintWriter JavaDoc;
43
44 /**
45  * A {@link PrintClassVisitor PrintClassVisitor} that prints the ASM code that
46  * generates the classes it visits. This class visitor can be used to quickly
47  * write ASM code to generate some given bytecode:
48  * <ul>
49  * <li>write the Java source code equivalent to the bytecode you want to
50  * generate;</li>
51  * <li>compile it with <tt>javac</tt>;</li>
52  * <li>make a {@link DumpClassVisitor DumpClassVisitor} visit this compiled
53  * class (see the {@link #main main} method);</li>
54  * <li>edit the generated source code, if necessary.</li>
55  * </ul>
56  * The source code printed when visiting the <tt>Hello</tt> class is the
57  * following:
58  * <p>
59  * <blockquote>
60  * <pre>
61  * import org.logicalcobwebs.asm.*;
62  * import java.io.FileOutputStream;
63  *
64  * public class Dump implements Constants {
65  *
66  * public static void main (String[] args) throws Exception {
67  *
68  * ClassWriter cw = new ClassWriter(false);
69  * CodeVisitor cv;
70  *
71  * cw.visit(ACC_PUBLIC + ACC_SUPER, "Hello", "java/lang/Object", null, "Hello.java");
72  *
73  * {
74  * cv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null);
75  * cv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
76  * cv.visitLdcInsn("hello");
77  * cv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
78  * cv.visitInsn(RETURN);
79  * cv.visitMaxs(2, 1);
80  * }
81  * {
82  * cv = cw.visitMethod(ACC_PUBLIC, "&lt;init&gt;", "()V", null);
83  * cv.visitVarInsn(ALOAD, 0);
84  * cv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "&lt;init&gt;", "()V");
85  * cv.visitInsn(RETURN);
86  * cv.visitMaxs(1, 1);
87  * }
88  * cw.visitEnd();
89  *
90  * FileOutputStream os = new FileOutputStream("Dumped.class");
91  * os.write(cw.toByteArray());
92  * os.close();
93  * }
94  * }
95  * </pre>
96  * </blockquote>
97  * where <tt>Hello</tt> is defined by:
98  * <p>
99  * <blockquote>
100  * <pre>
101  * public class Hello {
102  *
103  * public static void main (String[] args) {
104  * System.out.println("hello");
105  * }
106  * }
107  * </pre>
108  * </blockquote>
109  */

110
111 public class DumpClassVisitor extends PrintClassVisitor {
112
113   /**
114    * Prints the ASM source code to generate the given class to the standard
115    * output.
116    * <p>
117    * Usage: DumpClassVisitor &lt;fully qualified class name&gt;
118    *
119    * @param args the command line arguments.
120    *
121    * @throws Exception if the class cannot be found, or if an IO exception
122    * occurs.
123    */

124
125   public static void main (final String JavaDoc[] args) throws Exception JavaDoc {
126     if (args.length == 0) {
127       System.err.println("Prints the ASM code to generate the given class.");
128       System.err.println("Usage: DumpClassVisitor <fully qualified class name>");
129       System.exit(-1);
130     }
131     ClassReader cr = new ClassReader(args[0]);
132     cr.accept(new DumpClassVisitor(new PrintWriter JavaDoc(System.out)), true);
133   }
134
135   /**
136    * Constructs a new {@link DumpClassVisitor DumpClassVisitor} object.
137    *
138    * @param pw the print writer to be used to print the class.
139    */

140
141   public DumpClassVisitor (final PrintWriter JavaDoc pw) {
142     super(pw);
143   }
144
145   public void visit (
146     final int access,
147     final String JavaDoc name,
148     final String JavaDoc superName,
149     final String JavaDoc[] interfaces,
150     final String JavaDoc sourceFile)
151   {
152     text.add("import org.logicalcobwebs.asm.*;\n");
153     text.add("import java.io.FileOutputStream;\n\n");
154     text.add("public class Dump implements Constants {\n\n");
155     text.add("public static void main (String[] args) throws Exception {\n\n");
156     text.add("ClassWriter cw = new ClassWriter(false);\n");
157     text.add("CodeVisitor cv;\n\n");
158
159     buf.setLength(0);
160     buf.append("cw.visit(");
161     appendAccess(access | 262144);
162     buf.append(", ");
163     appendConstant(buf, name);
164     buf.append(", ");
165     appendConstant(buf, superName);
166     buf.append(", ");
167     if (interfaces != null && interfaces.length > 0) {
168       buf.append("new String[] {");
169       for (int i = 0; i < interfaces.length; ++i) {
170         buf.append(i == 0 ? " " : ", ");
171         appendConstant(buf, interfaces[i]);
172       }
173       buf.append(" }");
174     } else {
175       buf.append("null");
176     }
177     buf.append(", ");
178     appendConstant(buf, sourceFile);
179     buf.append(");\n\n");
180     text.add(buf.toString());
181   }
182
183   public void visitInnerClass (
184     final String JavaDoc name,
185     final String JavaDoc outerName,
186     final String JavaDoc innerName,
187     final int access)
188   {
189     buf.setLength(0);
190     buf.append("cw.visitInnerClass(");
191     appendConstant(buf, name);
192     buf.append(", ");
193     appendConstant(buf, outerName);
194     buf.append(", ");
195     appendConstant(buf, innerName);
196     buf.append(", ");
197     appendAccess(access);
198     buf.append(");\n\n");
199     text.add(buf.toString());
200   }
201
202   public void visitField (
203     final int access,
204     final String JavaDoc name,
205     final String JavaDoc desc,
206     final Object JavaDoc value,
207     final Attribute attrs)
208   {
209     buf.setLength(0);
210     buf.append("cw.visitField(");
211     appendAccess(access);
212     buf.append(", ");
213     appendConstant(buf, name);
214     buf.append(", ");
215     appendConstant(buf, desc);
216     buf.append(", ");
217     appendConstant(buf, value);
218     buf.append(", null);\n\n");
219     if (attrs != null) {
220       buf.append("// WARNING! skipped some non standard field attributes\n");
221     }
222     text.add(buf.toString());
223   }
224
225   public CodeVisitor visitMethod (
226     final int access,
227     final String JavaDoc name,
228     final String JavaDoc desc,
229     final String JavaDoc[] exceptions,
230     final Attribute attrs)
231   {
232     buf.setLength(0);
233     buf.append("{\n").append("cv = cw.visitMethod(");
234     appendAccess(access);
235     buf.append(", ");
236     appendConstant(buf, name);
237     buf.append(", ");
238     appendConstant(buf, desc);
239     buf.append(", ");
240     if (exceptions != null && exceptions.length > 0) {
241       buf.append("new String[] {");
242       for (int i = 0; i < exceptions.length; ++i) {
243         buf.append(i == 0 ? " " : ", ");
244         appendConstant(buf, exceptions[i]);
245       }
246       buf.append(" }");
247     } else {
248       buf.append("null");
249     }
250     buf.append(", null);\n");
251     if (attrs != null) {
252       buf.append("// WARNING! skipped some non standard method attributes\n");
253     }
254     text.add(buf.toString());
255     PrintCodeVisitor pcv = new DumpCodeVisitor();
256     text.add(pcv.getText());
257     text.add("}\n");
258     return pcv;
259   }
260
261   public void visitAttribute (final Attribute attr) {
262     buf.setLength(0);
263     buf.append("// WARNING! skipped a non standard class attribute of type \"");
264     buf.append(attr.type);
265     buf.append("\"\n");
266     text.add(buf.toString());
267   }
268
269   public void visitEnd () {
270     text.add("cw.visitEnd();\n\n");
271     text.add("FileOutputStream os = new FileOutputStream(\"Dumped.class\");\n");
272     text.add("os.write(cw.toByteArray());\n");
273     text.add("os.close();\n");
274     text.add("}\n");
275     text.add("}\n");
276     super.visitEnd();
277   }
278
279   /**
280    * Appends a string representation of the given access modifiers to {@link
281    * #buf buf}.
282    *
283    * @param access some access modifiers.
284    */

285
286   void appendAccess (final int access) {
287     boolean first = true;
288     if ((access & Constants.ACC_PUBLIC) != 0) {
289       buf.append("ACC_PUBLIC");
290       first = false;
291     }
292     if ((access & Constants.ACC_PRIVATE) != 0) {
293       if (!first) {
294         buf.append(" + ");
295       }
296       buf.append("ACC_PRIVATE");
297       first = false;
298     }
299     if ((access & Constants.ACC_PROTECTED) != 0) {
300       if (!first) {
301         buf.append(" + ");
302       }
303       buf.append("ACC_PROTECTED");
304       first = false;
305     }
306     if ((access & Constants.ACC_FINAL) != 0) {
307       if (!first) {
308         buf.append(" + ");
309       }
310       buf.append("ACC_FINAL");
311       first = false;
312     }
313     if ((access & Constants.ACC_STATIC) != 0) {
314       if (!first) {
315         buf.append(" + ");
316       }
317       buf.append("ACC_STATIC");
318       first = false;
319     }
320     if ((access & Constants.ACC_SYNCHRONIZED) != 0) {
321       if (!first) {
322         buf.append(" + ");
323       }
324       if ((access & 262144) != 0) {
325         buf.append("ACC_SUPER");
326       } else {
327         buf.append("ACC_SYNCHRONIZED");
328       }
329       first = false;
330     }
331     if ((access & Constants.ACC_VOLATILE) != 0) {
332       if (!first) {
333         buf.append(" + ");
334       }
335       buf.append("ACC_VOLATILE");
336       first = false;
337     }
338     if ((access & Constants.ACC_TRANSIENT) != 0) {
339       if (!first) {
340         buf.append(" + ");
341       }
342       buf.append("ACC_TRANSIENT");
343       first = false;
344     }
345     if ((access & Constants.ACC_NATIVE) != 0) {
346       if (!first) {
347         buf.append(" + ");
348       }
349       buf.append("ACC_NATIVE");
350       first = false;
351     }
352     if ((access & Constants.ACC_ABSTRACT) != 0) {
353       if (!first) {
354         buf.append(" + ");
355       }
356       buf.append("ACC_ABSTRACT");
357       first = false;
358     }
359     if ((access & Constants.ACC_INTERFACE) != 0) {
360       if (!first) {
361         buf.append(" + ");
362       }
363       buf.append("ACC_INTERFACE");
364       first = false;
365     }
366     if ((access & Constants.ACC_STRICT) != 0) {
367       if (!first) {
368         buf.append(" + ");
369       }
370       buf.append("ACC_STRICT");
371       first = false;
372     }
373     if ((access & Constants.ACC_SYNTHETIC) != 0) {
374       if (!first) {
375         buf.append(" + ");
376       }
377       buf.append("ACC_SYNTHETIC");
378       first = false;
379     }
380     if ((access & Constants.ACC_DEPRECATED) != 0) {
381       if (!first) {
382         buf.append(" + ");
383       }
384       buf.append("ACC_DEPRECATED");
385       first = false;
386     }
387     if (first) {
388       buf.append("0");
389     }
390   }
391
392   /**
393    * Appends a string representation of the given constant to the given buffer.
394    *
395    * @param buf a string buffer.
396    * @param cst an {@link java.lang.Integer Integer}, {@link java.lang.Float
397    * Float}, {@link java.lang.Long Long}, {@link java.lang.Double Double}
398    * or {@link String String} object. May be <tt>null</tt>.
399    */

400
401   static void appendConstant (final StringBuffer JavaDoc buf, final Object JavaDoc cst) {
402     if (cst == null) {
403       buf.append("null");
404     } else if (cst instanceof String JavaDoc) {
405       String JavaDoc s = (String JavaDoc)cst;
406       buf.append("\"");
407       for (int i = 0; i < s.length(); ++i) {
408         char c = s.charAt(i);
409         if (c == '\n') {
410           buf.append("\\n");
411         } else if (c == '\\') {
412           buf.append("\\\\");
413         } else if (c == '"') {
414           buf.append("\\\"");
415         } else {
416           buf.append(c);
417         }
418       }
419       buf.append("\"");
420     } else if (cst instanceof Integer JavaDoc) {
421       buf.append("new Integer(")
422         .append(cst)
423         .append(")");
424     } else if (cst instanceof Float JavaDoc) {
425       buf.append("new Float(")
426         .append(cst)
427         .append("F)");
428     } else if (cst instanceof Long JavaDoc) {
429       buf.append("new Long(")
430         .append(cst)
431         .append("L)");
432     } else if (cst instanceof Double JavaDoc) {
433       buf.append("new Double(")
434         .append(cst)
435         .append(")");
436     }
437   }
438 }
439
Popular Tags