1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 
19 import java.io.IOException;
20 
21 import org.apache.bcel.Constants;
22 import org.apache.bcel.generic.ALOAD;
23 import org.apache.bcel.generic.ASTORE;
24 import org.apache.bcel.generic.ArrayType;
25 import org.apache.bcel.generic.ClassGen;
26 import org.apache.bcel.generic.ConstantPoolGen;
27 import org.apache.bcel.generic.GOTO;
28 import org.apache.bcel.generic.InstructionConstants;
29 import org.apache.bcel.generic.InstructionFactory;
30 import org.apache.bcel.generic.InstructionHandle;
31 import org.apache.bcel.generic.InstructionList;
32 import org.apache.bcel.generic.LocalVariableGen;
33 import org.apache.bcel.generic.MethodGen;
34 import org.apache.bcel.generic.ObjectType;
35 import org.apache.bcel.generic.PUSH;
36 import org.apache.bcel.generic.Type;
37 
38 /**
39  * Create HelloWorld class:
40  * <PRE>
41  * import java.io.*;
42  *
43  * public class HelloWorld {
44  *     public static void main(String[] argv) {
45  *         BufferedReader in   = new BufferedReader(new InputStreamReader(System.in));
46  *         String name = null;
47  *
48  *         try {
49  *             System.out.print("Please enter your name> ");
50  *             name = in.readLine();
51  *         } catch(IOException e) {
52  *             System.out.println(e);
53  *             return;
54  *         }
55  *
56  *         System.out.println("Hello, " + name);
57  *     }
58  * }
59  * </PRE>
60  *
61  * @version $Id$
62  */
63 public class HelloWorldBuilder {
main(String[] argv)64     public static void main(String[] argv) {
65         ClassGen cg = new ClassGen("HelloWorld", "java.lang.Object",
66                 "<generated>", Constants.ACC_PUBLIC |
67                 Constants.ACC_SUPER,
68                 null);
69         ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool
70         InstructionList il = new InstructionList();
71         MethodGen mg = new MethodGen(Constants.ACC_STATIC |
72                 Constants.ACC_PUBLIC,// access flags
73                 Type.VOID,              // return type
74                 new Type[]{            // argument types
75                         new ArrayType(Type.STRING, 1)
76                 },
77                 new String[]{"argv"}, // arg names
78                 "main", "HelloWorld",    // method, class
79                 il, cp);
80         InstructionFactory factory = new InstructionFactory(cg);
81 
82         ObjectType i_stream = new ObjectType("java.io.InputStream");
83         ObjectType p_stream = new ObjectType("java.io.PrintStream");
84 
85         // Create BufferedReader object and store it in local variable `in'.
86         il.append(factory.createNew("java.io.BufferedReader"));
87         il.append(InstructionConstants.DUP); // Use predefined constant, i.e. flyweight
88         il.append(factory.createNew("java.io.InputStreamReader"));
89         il.append(InstructionConstants.DUP);
90         il.append(factory.createFieldAccess("java.lang.System", "in", i_stream, Constants.GETSTATIC));
91 
92         // Call constructors, i.e. BufferedReader(InputStreamReader())
93         il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
94                 Type.VOID, new Type[]{i_stream},
95                 Constants.INVOKESPECIAL));
96         il.append(factory.createInvoke("java.io.BufferedReader", "<init>", Type.VOID,
97                 new Type[]{new ObjectType("java.io.Reader")},
98                 Constants.INVOKESPECIAL));
99 
100         // Create local variable `in'
101         LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType("java.io.BufferedReader"), null, null);
102         int in = lg.getIndex();
103         lg.setStart(il.append(new ASTORE(in))); // `i' valid from here
104 
105         // Create local variable `name'
106         lg = mg.addLocalVariable("name", Type.STRING, null, null);
107         int name = lg.getIndex();
108         il.append(InstructionConstants.ACONST_NULL);
109         lg.setStart(il.append(new ASTORE(name))); // `name' valid from here
110 
111         // try { ...
112         InstructionHandle try_start =
113                 il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC));
114 
115         il.append(new PUSH(cp, "Please enter your name> "));
116         il.append(factory.createInvoke("java.io.PrintStream", "print", Type.VOID,
117                 new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL));
118         il.append(new ALOAD(in));
119         il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
120                 Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
121         il.append(new ASTORE(name));
122 
123         // Upon normal execution we jump behind exception handler, the target address is not known yet.
124         GOTO g = new GOTO(null);
125         InstructionHandle try_end = il.append(g);
126 
127         /* } catch() { ... }
128          * Add exception handler: print exception and return from method
129          */
130         InstructionHandle handler =
131                 il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC));
132         // Little trick in order not to save exception object temporarily
133         il.append(InstructionConstants.SWAP);
134 
135         il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[]{Type.OBJECT}, Constants.INVOKEVIRTUAL));
136         il.append(InstructionConstants.RETURN);
137         mg.addExceptionHandler(try_start, try_end, handler, new ObjectType("java.io.IOException"));
138 
139         // Normal code continues, now we can set the branch target of the GOTO that jumps over the handler code.
140         InstructionHandle ih =
141                 il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC));
142         g.setTarget(ih);
143 
144         // String concatenation compiles to StringBuffer operations.
145         il.append(factory.createNew(Type.STRINGBUFFER));
146         il.append(InstructionConstants.DUP);
147         il.append(new PUSH(cp, "Hello, "));
148         il.append(factory.createInvoke("java.lang.StringBuffer", "<init>",
149                 Type.VOID, new Type[]{Type.STRING},
150                 Constants.INVOKESPECIAL));
151         il.append(new ALOAD(name));
152 
153         // Concatenate strings using a StringBuffer and print them.
154         il.append(factory.createInvoke("java.lang.StringBuffer", "append",
155                 Type.STRINGBUFFER, new Type[]{Type.STRING},
156                 Constants.INVOKEVIRTUAL));
157         il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
158                 Type.STRING, Type.NO_ARGS,
159                 Constants.INVOKEVIRTUAL));
160 
161         il.append(factory.createInvoke("java.io.PrintStream", "println",
162                 Type.VOID, new Type[]{Type.STRING},
163                 Constants.INVOKEVIRTUAL));
164 
165         il.append(InstructionConstants.RETURN);
166 
167         mg.setMaxStack(5); // Needed stack size
168         cg.addMethod(mg.getMethod());
169 
170         il.dispose(); // Reuse instruction handles
171 
172         // Add public <init> method, i.e. empty constructor
173         cg.addEmptyConstructor(Constants.ACC_PUBLIC);
174 
175         // Get JavaClass object and dump it to file.
176         try {
177             cg.getJavaClass().dump("HelloWorld.class");
178         } catch (IOException e) {
179             System.err.println(e);
180         }
181     }
182 }
183