/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import org.apache.bcel.Constants; import org.apache.bcel.generic.ALOAD; import org.apache.bcel.generic.ASTORE; import org.apache.bcel.generic.ArrayType; import org.apache.bcel.generic.ClassGen; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.GOTO; import org.apache.bcel.generic.InstructionConstants; import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.LocalVariableGen; import org.apache.bcel.generic.MethodGen; import org.apache.bcel.generic.ObjectType; import org.apache.bcel.generic.PUSH; import org.apache.bcel.generic.Type; /** * Create HelloWorld class: *
 * import java.io.*;
 *
 * public class HelloWorld {
 *   public static void main(String[] argv) {
 *     BufferedReader in   = new BufferedReader(new InputStreamReader(System.in));
 *     String name = null;
 * 
 *     try {
 *       System.out.print("Please enter your name> ");
 *       name = in.readLine();
 *     } catch(IOException e) { 
 *       System.out.println(e);
 *     return; 
 *     }
 * 
 *     System.out.println("Hello, " + name);
 *   }
 * }
 * 
* * @version $Id$ * @author M. Dahm */ public class HelloWorldBuilder { public static void main(String[] argv) { ClassGen cg = new ClassGen("HelloWorld", "java.lang.Object", "", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null); ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool InstructionList il = new InstructionList(); MethodGen mg = new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC,// access flags Type.VOID, // return type new Type[] { // argument types new ArrayType(Type.STRING, 1) }, new String[] { "argv" }, // arg names "main", "HelloWorld", // method, class il, cp); InstructionFactory factory = new InstructionFactory(cg); ObjectType i_stream = new ObjectType("java.io.InputStream"); ObjectType p_stream = new ObjectType("java.io.PrintStream"); /* Create BufferedReader object and store it in local variable `in'. */ il.append(factory.createNew("java.io.BufferedReader")); il.append(InstructionConstants.DUP); // Use predefined constant, i.e. flyweight il.append(factory.createNew("java.io.InputStreamReader")); il.append(InstructionConstants.DUP); il.append(factory.createFieldAccess("java.lang.System", "in", i_stream, Constants.GETSTATIC)); /* Call constructors, i.e. BufferedReader(InputStreamReader()) */ il.append(factory.createInvoke("java.io.InputStreamReader", "", Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL)); il.append(factory.createInvoke("java.io.BufferedReader", "", Type.VOID, new Type[] { new ObjectType("java.io.Reader") }, Constants.INVOKESPECIAL)); /* Create local variable `in' */ LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType("java.io.BufferedReader"), null, null); int in = lg.getIndex(); lg.setStart(il.append(new ASTORE(in))); // `i' valid from here /* Create local variable `name' */ lg = mg.addLocalVariable("name", Type.STRING, null, null); int name = lg.getIndex(); il.append(InstructionConstants.ACONST_NULL); lg.setStart(il.append(new ASTORE(name))); // `name' valid from here /* try { ... */ InstructionHandle try_start = il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); il.append(new PUSH(cp, "Please enter your name> ")); il.append(factory.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); il.append(new ALOAD(in)); il.append(factory.createInvoke("java.io.BufferedReader", "readLine", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); il.append(new ASTORE(name)); /* Upon normal execution we jump behind exception handler, * the target address is not known yet. */ GOTO g = new GOTO(null); InstructionHandle try_end = il.append(g); /* } catch() { ... } * Add exception handler: print exception and return from method */ InstructionHandle handler = il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); // Little trick in order not to save exception object temporarily il.append(InstructionConstants.SWAP); il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.OBJECT }, Constants.INVOKEVIRTUAL)); il.append(InstructionConstants.RETURN); mg.addExceptionHandler(try_start, try_end, handler, new ObjectType("java.io.IOException")); /* Normal code continues, now we can set the branch target of the GOTO * that jumps over the handler code. */ InstructionHandle ih = il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); g.setTarget(ih); /* String concatenation compiles to StringBuffer operations. */ il.append(factory.createNew(Type.STRINGBUFFER)); il.append(InstructionConstants.DUP); il.append(new PUSH(cp, "Hello, ")); il.append(factory.createInvoke("java.lang.StringBuffer", "", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKESPECIAL)); il.append(new ALOAD(name)); /* Concatenate strings using a StringBuffer and print them. */ il.append(factory.createInvoke("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); il.append(factory.createInvoke("java.lang.StringBuffer", "toString", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); il.append(InstructionConstants.RETURN); mg.setMaxStack(5); // Needed stack size cg.addMethod(mg.getMethod()); il.dispose(); // Reuse instruction handles /* Add public method, i.e. empty constructor */ cg.addEmptyConstructor(Constants.ACC_PUBLIC); /* Get JavaClass object and dump it to file. */ try { cg.getJavaClass().dump("HelloWorld.class"); } catch(java.io.IOException e) { System.err.println(e); } } }