    View Javadoc
    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);
    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