1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.bcel.internal.util; 23 24 import com.sun.org.apache.bcel.internal.classfile.*; 25 import com.sun.org.apache.bcel.internal.generic.*; 26 import com.sun.org.apache.bcel.internal.Repository; 27 import com.sun.org.apache.bcel.internal.Constants; 28 import java.io.*; 29 30 /** 31 * This class takes a given JavaClass object and converts it to a 32 * Java program that creates that very class using BCEL. This 33 * gives new users of BCEL a useful example showing how things 34 * are done with BCEL. It does not cover all features of BCEL, 35 * but tries to mimic hand-written code as close as possible. 36 * 37 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 38 */ 39 public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyVisitor { 40 private JavaClass _clazz; 41 private PrintWriter _out; 42 private ConstantPoolGen _cp; 43 44 /** @param clazz Java class to "decompile" 45 * @param out where to output Java program 46 */ 47 public BCELifier(JavaClass clazz, OutputStream out) { 48 _clazz = clazz; 49 _out = new PrintWriter(out); 50 _cp = new ConstantPoolGen(_clazz.getConstantPool()); 51 } 52 53 /** Start Java code generation 54 */ 55 public void start() { 56 visitJavaClass(_clazz); 57 _out.flush(); 58 } 59 60 public void visitJavaClass(JavaClass clazz) { 61 String class_name = clazz.getClassName(); 62 String super_name = clazz.getSuperclassName(); 63 String package_name = clazz.getPackageName(); 64 String inter = Utility.printArray(clazz.getInterfaceNames(), 65 false, true); 66 if(!"".equals(package_name)) { 67 class_name = class_name.substring(package_name.length() + 1); 68 _out.println("package " + package_name + ";\n"); 69 } 70 71 _out.println("import com.sun.org.apache.bcel.internal.generic.*;"); 72 _out.println("import com.sun.org.apache.bcel.internal.classfile.*;"); 73 _out.println("import com.sun.org.apache.bcel.internal.*;"); 74 _out.println("import java.io.*;\n"); 75 76 _out.println("public class " + class_name + "Creator implements Constants {"); 77 _out.println(" private InstructionFactory _factory;"); 78 _out.println(" private ConstantPoolGen _cp;"); 79 _out.println(" private ClassGen _cg;\n"); 80 81 _out.println(" public " + class_name + "Creator() {"); 82 _out.println(" _cg = new ClassGen(\"" + 83 (("".equals(package_name))? class_name : 84 package_name + "." + class_name) + 85 "\", \"" + super_name + "\", " + 86 "\"" + clazz.getSourceFileName() + "\", " + 87 printFlags(clazz.getAccessFlags(), true) + ", " + 88 "new String[] { " + inter + " });\n"); 89 90 _out.println(" _cp = _cg.getConstantPool();"); 91 _out.println(" _factory = new InstructionFactory(_cg, _cp);"); 92 _out.println(" }\n"); 93 94 printCreate(); 95 96 Field[] fields = clazz.getFields(); 97 98 if(fields.length > 0) { 99 _out.println(" private void createFields() {"); 100 _out.println(" FieldGen field;"); 101 102 for(int i=0; i < fields.length; i++) { 103 fields[i].accept(this); 104 } 105 106 _out.println(" }\n"); 107 } 108 109 Method[] methods = clazz.getMethods(); 110 111 for(int i=0; i < methods.length; i++) { 112 _out.println(" private void createMethod_" + i + "() {"); 113 114 methods[i].accept(this); 115 _out.println(" }\n"); 116 } 117 118 printMain(); 119 _out.println("}"); 120 } 121 122 private void printCreate() { 123 _out.println(" public void create(OutputStream out) throws IOException {"); 124 125 Field[] fields = _clazz.getFields(); 126 if(fields.length > 0) { 127 _out.println(" createFields();"); 128 } 129 130 Method[] methods = _clazz.getMethods(); 131 for(int i=0; i < methods.length; i++) { 132 _out.println(" createMethod_" + i + "();"); 133 } 134 135 _out.println(" _cg.getJavaClass().dump(out);"); 136 137 _out.println(" }\n"); 138 } 139 140 private void printMain() { 141 String class_name = _clazz.getClassName(); 142 143 _out.println(" public static void _main(String[] args) throws Exception {"); 144 _out.println(" " + class_name + "Creator creator = new " + 145 class_name + "Creator();"); 146 _out.println(" creator.create(new FileOutputStream(\"" + class_name + 147 ".class\"));"); 148 _out.println(" }"); 149 } 150 151 public void visitField(Field field) { 152 _out.println("\n field = new FieldGen(" + 153 printFlags(field.getAccessFlags()) + 154 ", " + printType(field.getSignature()) + ", \"" + 155 field.getName() + "\", _cp);"); 156 157 ConstantValue cv = field.getConstantValue(); 158 159 if(cv != null) { 160 String value = cv.toString(); 161 _out.println(" field.setInitValue(" + value + ")"); 162 } 163 164 _out.println(" _cg.addField(field.getField());"); 165 } 166 167 public void visitMethod(Method method) { 168 MethodGen mg = new MethodGen(method, _clazz.getClassName(), _cp); 169 170 Type result_type = mg.getReturnType(); 171 Type[] arg_types = mg.getArgumentTypes(); 172 173 _out.println(" InstructionList il = new InstructionList();"); 174 _out.println(" MethodGen method = new MethodGen(" + 175 printFlags(method.getAccessFlags()) + 176 ", " + printType(result_type) + 177 ", " + printArgumentTypes(arg_types) + ", " + 178 "new String[] { " + 179 Utility.printArray(mg.getArgumentNames(), false, true) + 180 " }, \"" + method.getName() + "\", \"" + 181 _clazz.getClassName() + "\", il, _cp);\n"); 182 183 BCELFactory factory = new BCELFactory(mg, _out); 184 factory.start(); 185 186 _out.println(" method.setMaxStack();"); 187 _out.println(" method.setMaxLocals();"); 188 _out.println(" _cg.addMethod(method.getMethod());"); 189 _out.println(" il.dispose();"); 190 } 191 192 static String printFlags(int flags) { 193 return printFlags(flags, false); 194 } 195 196 static String printFlags(int flags, boolean for_class) { 197 if(flags == 0) 198 return "0"; 199 200 StringBuffer buf = new StringBuffer(); 201 for(int i=0, pow=1; i <= Constants.MAX_ACC_FLAG; i++) { 202 if((flags & pow) != 0) { 203 if((pow == Constants.ACC_SYNCHRONIZED) && for_class) 204 buf.append("ACC_SUPER | "); 205 else 206 buf.append("ACC_" + Constants.ACCESS_NAMES[i].toUpperCase() + " | "); 207 } 208 209 pow <<= 1; 210 } 211 212 String str = buf.toString(); 213 return str.substring(0, str.length() - 3); 214 } 215 216 static String printArgumentTypes(Type[] arg_types) { 217 if(arg_types.length == 0) 218 return "Type.NO_ARGS"; 219 220 StringBuffer args = new StringBuffer(); 221 222 for(int i=0; i < arg_types.length; i++) { 223 args.append(printType(arg_types[i])); 224 225 if(i < arg_types.length - 1) 226 args.append(", "); 227 } 228 229 return "new Type[] { " + args.toString() + " }"; 230 } 231 232 static String printType(Type type) { 233 return printType(type.getSignature()); 234 } 235 236 static String printType(String signature) { 237 Type type = Type.getType(signature); 238 byte t = type.getType(); 239 240 if(t <= Constants.T_VOID) { 241 return "Type." + Constants.TYPE_NAMES[t].toUpperCase(); 242 } else if(type.toString().equals("java.lang.String")) { 243 return "Type.STRING"; 244 } else if(type.toString().equals("java.lang.Object")) { 245 return "Type.OBJECT"; 246 } else if(type.toString().equals("java.lang.StringBuffer")) { 247 return "Type.STRINGBUFFER"; 248 } else if(type instanceof ArrayType) { 249 ArrayType at = (ArrayType)type; 250 251 return "new ArrayType(" + printType(at.getBasicType()) + 252 ", " + at.getDimensions() + ")"; 253 } else { 254 return "new ObjectType(\"" + Utility.signatureToString(signature, false) + 255 "\")"; 256 } 257 } 258 259 /** Default _main method 260 */ 261 public static void _main(String[] argv) throws Exception { 262 JavaClass java_class; 263 String name = argv[0]; 264 265 if((java_class = Repository.lookupClass(name)) == null) 266 java_class = new ClassParser(name).parse(); // May throw IOException 267 268 BCELifier bcelifier = new BCELifier(java_class, System.out); 269 bcelifier.start(); 270 } 271 }