xref: /aosp_15_r20/external/apache-commons-bcel/src/examples/ProxyCreator.java (revision 0c56280ab0842982c46a149f7b9eaa497e31e292)
1*0c56280aSSorin Basca /*
2*0c56280aSSorin Basca  * Licensed to the Apache Software Foundation (ASF) under one or more
3*0c56280aSSorin Basca  * contributor license agreements.  See the NOTICE file distributed with
4*0c56280aSSorin Basca  * this work for additional information regarding copyright ownership.
5*0c56280aSSorin Basca  * The ASF licenses this file to You under the Apache License, Version 2.0
6*0c56280aSSorin Basca  * (the "License"); you may not use this file except in compliance with
7*0c56280aSSorin Basca  * the License.  You may obtain a copy of the License at
8*0c56280aSSorin Basca  *
9*0c56280aSSorin Basca  *      http://www.apache.org/licenses/LICENSE-2.0
10*0c56280aSSorin Basca  *
11*0c56280aSSorin Basca  *  Unless required by applicable law or agreed to in writing, software
12*0c56280aSSorin Basca  *  distributed under the License is distributed on an "AS IS" BASIS,
13*0c56280aSSorin Basca  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*0c56280aSSorin Basca  *  See the License for the specific language governing permissions and
15*0c56280aSSorin Basca  *  limitations under the License.
16*0c56280aSSorin Basca  *
17*0c56280aSSorin Basca  */
18*0c56280aSSorin Basca 
19*0c56280aSSorin Basca import java.awt.event.ActionEvent;
20*0c56280aSSorin Basca import java.awt.event.ActionListener;
21*0c56280aSSorin Basca 
22*0c56280aSSorin Basca import org.apache.bcel.Constants;
23*0c56280aSSorin Basca import org.apache.bcel.classfile.Utility;
24*0c56280aSSorin Basca import org.apache.bcel.generic.ALOAD;
25*0c56280aSSorin Basca import org.apache.bcel.generic.ClassGen;
26*0c56280aSSorin Basca import org.apache.bcel.generic.ConstantPoolGen;
27*0c56280aSSorin Basca import org.apache.bcel.generic.GETSTATIC;
28*0c56280aSSorin Basca import org.apache.bcel.generic.INVOKEVIRTUAL;
29*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionConstants;
30*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionFactory;
31*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionList;
32*0c56280aSSorin Basca import org.apache.bcel.generic.MethodGen;
33*0c56280aSSorin Basca import org.apache.bcel.generic.ObjectType;
34*0c56280aSSorin Basca import org.apache.bcel.generic.PUSH;
35*0c56280aSSorin Basca import org.apache.bcel.generic.Type;
36*0c56280aSSorin Basca 
37*0c56280aSSorin Basca /**
38*0c56280aSSorin Basca  * Dynamically creates and uses a proxy for {@code java.awt.event.ActionListener}
39*0c56280aSSorin Basca  * via the classloader mechanism if called with
40*0c56280aSSorin Basca  * <pre>java org.apache.bcel.util.JavaWrapper ProxyCreator</pre>
41*0c56280aSSorin Basca  *
42*0c56280aSSorin Basca  * The trick is to encode the byte code we need into the class name
43*0c56280aSSorin Basca  * using the Utility.encode() method. This will result however in big
44*0c56280aSSorin Basca  * ugly class name, so for many cases it will be more sufficient to
45*0c56280aSSorin Basca  * put some clever creation code into the class loader.<br> This is
46*0c56280aSSorin Basca  * comparable to the mechanism provided via
47*0c56280aSSorin Basca  * {@code java.lang.reflect.Proxy}, but much more flexible.
48*0c56280aSSorin Basca  *
49*0c56280aSSorin Basca  * @version $Id$
50*0c56280aSSorin Basca  * @see org.apache.bcel.util.JavaWrapper
51*0c56280aSSorin Basca  * @see Utility
52*0c56280aSSorin Basca  */
53*0c56280aSSorin Basca public class ProxyCreator {
54*0c56280aSSorin Basca 
55*0c56280aSSorin Basca     /**
56*0c56280aSSorin Basca      * Load class and create instance
57*0c56280aSSorin Basca      */
createProxy(String pack, String class_name)58*0c56280aSSorin Basca     public static Object createProxy(String pack, String class_name) {
59*0c56280aSSorin Basca         try {
60*0c56280aSSorin Basca             Class<?> cl = Class.forName(pack + "$$BCEL$$" + class_name);
61*0c56280aSSorin Basca             return cl.newInstance();
62*0c56280aSSorin Basca         } catch (Exception e) {
63*0c56280aSSorin Basca             e.printStackTrace();
64*0c56280aSSorin Basca         }
65*0c56280aSSorin Basca 
66*0c56280aSSorin Basca         return null;
67*0c56280aSSorin Basca     }
68*0c56280aSSorin Basca 
69*0c56280aSSorin Basca     /**
70*0c56280aSSorin Basca      * Create JavaClass object for a simple proxy for an java.awt.event.ActionListener
71*0c56280aSSorin Basca      * that just prints the passed arguments, load and use it via the class loader
72*0c56280aSSorin Basca      * mechanism.
73*0c56280aSSorin Basca      */
main(String[] argv)74*0c56280aSSorin Basca     public static void main(String[] argv) throws Exception {
75*0c56280aSSorin Basca         ClassLoader loader = ProxyCreator.class.getClassLoader();
76*0c56280aSSorin Basca 
77*0c56280aSSorin Basca         // instanceof won't work here ...
78*0c56280aSSorin Basca         // TODO this is broken; cannot ever be true now that ClassLoader has been dropped
79*0c56280aSSorin Basca         if (loader.getClass().toString().equals("class org.apache.bcel.util.ClassLoader")) {
80*0c56280aSSorin Basca             // Real class name will be set by the class loader
81*0c56280aSSorin Basca             ClassGen cg = new ClassGen("foo", "java.lang.Object", "", Constants.ACC_PUBLIC,
82*0c56280aSSorin Basca                     new String[]{"java.awt.event.ActionListener"});
83*0c56280aSSorin Basca 
84*0c56280aSSorin Basca             // That's important, otherwise newInstance() won't work
85*0c56280aSSorin Basca             cg.addEmptyConstructor(Constants.ACC_PUBLIC);
86*0c56280aSSorin Basca 
87*0c56280aSSorin Basca             InstructionList il = new InstructionList();
88*0c56280aSSorin Basca             ConstantPoolGen cp = cg.getConstantPool();
89*0c56280aSSorin Basca             InstructionFactory factory = new InstructionFactory(cg);
90*0c56280aSSorin Basca 
91*0c56280aSSorin Basca             int out = cp.addFieldref("java.lang.System", "out",
92*0c56280aSSorin Basca                     "Ljava/io/PrintStream;");
93*0c56280aSSorin Basca             int println = cp.addMethodref("java.io.PrintStream", "println",
94*0c56280aSSorin Basca                     "(Ljava/lang/Object;)V");
95*0c56280aSSorin Basca             MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
96*0c56280aSSorin Basca                     new Type[]{
97*0c56280aSSorin Basca                             new ObjectType("java.awt.event.ActionEvent")
98*0c56280aSSorin Basca                     }, null, "actionPerformed", "foo", il, cp);
99*0c56280aSSorin Basca 
100*0c56280aSSorin Basca             // System.out.println("actionPerformed:" + event);
101*0c56280aSSorin Basca             il.append(new GETSTATIC(out));
102*0c56280aSSorin Basca             il.append(factory.createNew("java.lang.StringBuffer"));
103*0c56280aSSorin Basca             il.append(InstructionConstants.DUP);
104*0c56280aSSorin Basca             il.append(new PUSH(cp, "actionPerformed:"));
105*0c56280aSSorin Basca             il.append(factory.createInvoke("java.lang.StringBuffer", "<init>", Type.VOID,
106*0c56280aSSorin Basca                     new Type[]{Type.STRING}, Constants.INVOKESPECIAL));
107*0c56280aSSorin Basca 
108*0c56280aSSorin Basca             il.append(new ALOAD(1));
109*0c56280aSSorin Basca             il.append(factory.createAppend(Type.OBJECT));
110*0c56280aSSorin Basca             il.append(new INVOKEVIRTUAL(println));
111*0c56280aSSorin Basca             il.append(InstructionConstants.RETURN);
112*0c56280aSSorin Basca 
113*0c56280aSSorin Basca             mg.stripAttributes(true);
114*0c56280aSSorin Basca             mg.setMaxStack();
115*0c56280aSSorin Basca             mg.setMaxLocals();
116*0c56280aSSorin Basca             cg.addMethod(mg.getMethod());
117*0c56280aSSorin Basca 
118*0c56280aSSorin Basca             byte[] bytes = cg.getJavaClass().getBytes();
119*0c56280aSSorin Basca 
120*0c56280aSSorin Basca             System.out.println("Uncompressed class: " + bytes.length);
121*0c56280aSSorin Basca 
122*0c56280aSSorin Basca             String s = Utility.encode(bytes, true);
123*0c56280aSSorin Basca             System.out.println("Encoded class: " + s.length());
124*0c56280aSSorin Basca 
125*0c56280aSSorin Basca             System.out.print("Creating proxy ... ");
126*0c56280aSSorin Basca             ActionListener a = (ActionListener) createProxy("foo.bar.", s);
127*0c56280aSSorin Basca             System.out.println("Done. Now calling actionPerformed()");
128*0c56280aSSorin Basca 
129*0c56280aSSorin Basca             a.actionPerformed(new ActionEvent(a, ActionEvent.ACTION_PERFORMED, "hello"));
130*0c56280aSSorin Basca         } else {
131*0c56280aSSorin Basca             System.err.println("Call me with java org.apache.bcel.util.JavaWrapper ProxyCreator");
132*0c56280aSSorin Basca         }
133*0c56280aSSorin Basca     }
134*0c56280aSSorin Basca 
135*0c56280aSSorin Basca }
136