1   package org.apache.bcel.util;
2   
3   /* ====================================================================
4    * The Apache Software License, Version 1.1
5    *
6    * Copyright (c) 2002 The Apache Software Foundation.  All rights
7    * reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
16   * 2. Redistributions in binary form must reproduce the above copyright
17   *    notice, this list of conditions and the following disclaimer in
18   *    the documentation and/or other materials provided with the
19   *    distribution.
20   *
21   * 3. The end-user documentation included with the redistribution,
22   *    if any, must include the following acknowledgment:
23   *       "This product includes software developed by the
24   *        Apache Software Foundation (http://www.apache.org/)."
25   *    Alternately, this acknowledgment may appear in the software itself,
26   *    if and wherever such third-party acknowledgments normally appear.
27   *
28   * 4. The names "Apache" and "Apache Software Foundation" and
29   *    "Apache BCEL" must not be used to endorse or promote products
30   *    derived from this software without prior written permission. For
31   *    written permission, please contact apache@apache.org.
32   *
33   * 5. Products derived from this software may not be called "Apache",
34   *    "Apache BCEL", nor may "Apache" appear in their name, without
35   *    prior written permission of the Apache Software Foundation.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48   * SUCH DAMAGE.
49   * ====================================================================
50   *
51   * This software consists of voluntary contributions made by many
52   * individuals on behalf of the Apache Software Foundation.  For more
53   * information on the Apache Software Foundation, please see
54   * <http://www.apache.org/>.
55   */
56  import org.apache.bcel.classfile.*;
57  import org.apache.bcel.generic.*;
58  import org.apache.bcel.Repository;
59  import org.apache.bcel.Constants;
60  import java.io.*;
61  
62  /*** 
63   * This class takes a given JavaClass object and converts it to a
64   * Java program that creates that very class using BCEL. This
65   * gives new users of BCEL a useful example showing how things
66   * are done with BCEL. It does not cover all features of BCEL,
67   * but tries to mimic hand-written code as close as possible.
68   *
69   * @version $Id: BCELifier.java,v 1.4 2002/11/30 11:12:21 mdahm Exp $
70   * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 
71   */
72  public class BCELifier extends org.apache.bcel.classfile.EmptyVisitor {
73    private JavaClass         _clazz;
74    private PrintWriter       _out;
75    private ConstantPoolGen   _cp;
76  
77    /*** @param clazz Java class to "decompile"
78     * @param out where to output Java program
79     */
80    public BCELifier(JavaClass clazz, OutputStream out) {
81      _clazz = clazz;
82      _out = new PrintWriter(out);
83      _cp = new ConstantPoolGen(_clazz.getConstantPool());
84    }
85  
86    /*** Start Java code generation
87     */
88    public void start() {
89      visitJavaClass(_clazz);
90      _out.flush();
91    }
92  
93    public void visitJavaClass(JavaClass clazz) {
94      String class_name   = clazz.getClassName();
95      String super_name   = clazz.getSuperclassName();
96      String package_name = clazz.getPackageName();
97      String inter        = Utility.printArray(clazz.getInterfaceNames(),
98  					     false, true);
99      if(!"".equals(package_name)) {
100       class_name = class_name/substring(package_name/length() + 1)/package-summary.html">>_name = class_name.substring(package_name.length() + 1);
101       _out.println("package " + package_name + ";\n");
102      }
103 
104     _out.println("import org.apache.bcel.generic.*;");
105     _out.println("import org.apache.bcel.classfile.*;");
106     _out.println("import org.apache.bcel.*;");
107     _out.println("import java.io.*;\n");
108 
109     _out.println("public class " + class_name + "Creator implements Constants {");
110     _out.println("  private InstructionFactory _factory;");
111     _out.println("  private ConstantPoolGen    _cp;");
112     _out.println("  private ClassGen           _cg;\n");
113 
114     _out.println("  public " + class_name  + "Creator() {");
115     _out.println("    _cg = new ClassGen(\"" +
116 		 (("".equals(package_name))? class_name :
117 		  package_name + "." + class_name) +
118 		 "\", \"" + super_name + "\", " +
119 		 "\"" + clazz.getSourceFileName() + "\", " +
120 		 printFlags(clazz.getAccessFlags(), true) + ", " +
121 		 "new String[] { " + inter + " });\n");
122 
123     _out.println("    _cp = _cg.getConstantPool();");
124     _out.println("    _factory = new InstructionFactory(_cg, _cp);");
125     _out.println("  }\n");
126 
127     printCreate();
128 
129     Field[] fields = clazz.getFields();
130 
131     if(fields.length > 0) {
132       _out.println("  private void createFields() {");   
133       _out.println("    FieldGen field;");
134 
135       for(int i=0; i < fields.length; i++) {
136 	fields[i].accept(this);
137       }
138 
139       _out.println("  }\n");   
140     }
141 
142     Method[] methods = clazz.getMethods();
143 
144     for(int i=0; i < methods.length; i++) {
145       _out.println("  private void createMethod_" + i + "() {");   
146 
147       methods[i].accept(this);
148       _out.println("  }\n");   
149     }
150 
151     printMain();
152     _out.println("}");
153   }
154   
155   private void printCreate() {
156     _out.println("  public void create(OutputStream out) throws IOException {");
157 
158     Field[] fields = _clazz.getFields();
159     if(fields.length > 0) {
160       _out.println("    createFields();");   
161     }
162 
163     Method[] methods = _clazz.getMethods();
164     for(int i=0; i < methods.length; i++) {
165       _out.println("    createMethod_" + i + "();");   
166     }
167 
168     _out.println("    _cg.getJavaClass().dump(out);");   
169   
170     _out.println("  }\n");     
171   }
172 
173   private void printMain() {
174     String   class_name   = _clazz.getClassName();
175     
176     _out.println("  public static void main(String[] args) throws Exception {");
177     _out.println("    " + class_name + "Creator creator = new " +
178 		 class_name + "Creator();");
179     _out.println("    creator.create(new FileOutputStream(\"" + class_name +
180 		 ".class\"));");
181     _out.println("  }");     
182   }
183 
184   public void visitField(Field field) {
185     _out.println("\n    field = new FieldGen(" +
186 		 printFlags(field.getAccessFlags()) +
187 		 ", " + printType(field.getSignature()) + ", \"" +
188 		 field.getName() + "\", _cp);");
189 
190     ConstantValue cv = field.getConstantValue();
191 
192     if(cv != null) {
193       String value = cv.toString();
194       _out.println("    field.setInitValue(" + value + ")");
195     }
196 
197     _out.println("    _cg.addField(field.getField());");
198   }
199 
200   public void visitMethod(Method method) {
201     MethodGen mg = new MethodGen(method, _clazz.getClassName(), _cp);
202 
203     Type   result_type = mg.getReturnType();
204     Type[] arg_types   = mg.getArgumentTypes();
205 
206     _out.println("    InstructionList il = new InstructionList();");
207     _out.println("    MethodGen method = new MethodGen(" +
208 		 printFlags(method.getAccessFlags()) +
209 		 ", " + printType(result_type) +
210 		 ", " + printArgumentTypes(arg_types) + ", " +
211 		 "new String[] { " +
212 		 Utility.printArray(mg.getArgumentNames(), false, true) +
213 		 " }, \"" + method.getName() + "\", \"" +
214 		 _clazz.getClassName() + "\", il, _cp);\n");
215     
216     BCELFactory factory = new BCELFactory(mg, _out);
217     factory.start();
218 
219     _out.println("    method.setMaxStack();");
220     _out.println("    method.setMaxLocals();");
221     _out.println("    _cg.addMethod(method.getMethod());");
222     _out.println("    il.dispose();");
223   }
224 
225   static String printFlags(int flags) {
226     return printFlags(flags, false);
227   }
228 
229   static String printFlags(int flags, boolean for_class) {
230     if(flags == 0)
231       return "0";
232 
233     StringBuffer buf = new StringBuffer();
234     for(int i=0, pow=1; i <= Constants.MAX_ACC_FLAG; i++) {
235       if((flags & pow) != 0) {
236 	if((pow == Constants.ACC_SYNCHRONIZED) && for_class)
237 	  buf.append("ACC_SUPER | ");
238 	else
239 	  buf.append("ACC_" + Constants.ACCESS_NAMES[i].toUpperCase() + " | ");
240       }
241 
242       pow <<= 1;
243     }
244 
245     String str = buf.toString();
246     return str.substring(0, str.length() - 3);
247   }
248 
249   static String printArgumentTypes(Type[] arg_types) {
250     if(arg_types.length == 0)
251       return "Type.NO_ARGS";
252 
253     StringBuffer args = new StringBuffer();
254 
255     for(int i=0; i < arg_types.length; i++) {
256       args.append(printType(arg_types[i]));
257 
258       if(i < arg_types.length - 1)
259 	args.append(", ");
260     }
261 
262     return "new Type[] { " + args.toString() + " }";
263   }
264 
265   static String printType(Type type) {
266     return printType(type.getSignature());
267   }
268 
269   static String printType(String signature) {
270     Type type = Type.getType(signature);
271     byte t    = type.getType();
272 
273     if(t <= Constants.T_VOID) {
274       return "Type." + Constants.TYPE_NAMES[t].toUpperCase();
275     } else if(type.toString().equals("java.lang.String")) {
276       return "Type.STRING";
277     } else if(type.toString().equals("java.lang.Object")) {
278       return "Type.OBJECT";
279     } else if(type.toString().equals("java.lang.StringBuffer")) {
280       return "Type.STRINGBUFFER";
281     } else if(type instanceof ArrayType) {
282       ArrayType at = (ArrayType)type;
283 
284       return "new ArrayType(" + printType(at.getBasicType()) +
285 	", " + at.getDimensions() + ")";
286     } else {
287       return "new ObjectType(\"" + Utility.signatureToString(signature, false) +
288 	"\")";
289     }
290   }
291 
292   /*** Default main method
293    */
294   public static void main(String[] argv) throws Exception {
295     JavaClass java_class;
296     String    name = argv[0];
297 
298     if((java_class = Repository.lookupClass(name)) == null)
299       java_class = new ClassParser(name).parse(); // May throw IOException
300 
301     BCELifier bcelifier = new BCELifier(java_class, System.out);
302     bcelifier.start();
303   }
304 }
This page was automatically generated by Maven