| import java.io.*; |
| import org.apache.bcel.classfile.*; |
| import org.apache.bcel.generic.*; |
| import org.apache.bcel.util.ByteSequence; |
| import org.apache.bcel.*; |
| import java.awt.event.*; |
| import java.util.Vector; |
| import java.util.zip.*; |
| |
| /** |
| * Dynamically creates and uses a proxy for <tt>java.awt.event.ActionListener</tt> |
| * via the classloader mechanism if called with |
| * <pre>java org.apache.bcel.util.JavaWrapper ProxyCreator</pre> |
| * |
| * The trick is to encode the byte code we need into the class name |
| * using the Utility.encode() method. This will result however in big |
| * ugly class name, so for many cases it will be more sufficient to |
| * put some clever creation code into the class loader.<br> This is |
| * comparable to the mechanism provided via |
| * <tt>java.lang.reflect.Proxy</tt>, but much more flexible. |
| * |
| * @version $Id$ |
| * @author <A HREF="http://www.berlin.de/~markus.dahm/">M. Dahm</A> |
| * @see org.apache.bcel.util.JavaWrapper |
| * @see org.apache.bcel.util.ClassLoader |
| * @see Utility |
| */ |
| public class ProxyCreator { |
| /** Load class and create instance |
| */ |
| public static Object createProxy(String pack, String class_name) { |
| try { |
| Class cl = Class.forName(pack + "$$BCEL$$" + class_name); |
| return cl.newInstance(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| |
| return null; |
| } |
| |
| /** Create JavaClass object for a simple proxy for an java.awt.event.ActionListener |
| * that just prints the passed arguments, load and use it via the class loader |
| * mechanism. |
| */ |
| public static void main(String[] argv) throws Exception { |
| ClassLoader loader = ProxyCreator.class.getClassLoader(); |
| |
| // instanceof won't work here ... |
| if(loader.getClass().toString().equals("class org.apache.bcel.util.ClassLoader")) { |
| // Real class name will be set by the class loader |
| ClassGen cg = new ClassGen("foo", "java.lang.Object", "", Constants.ACC_PUBLIC, |
| new String[] {"java.awt.event.ActionListener"}); |
| |
| // That's important, otherwise newInstance() won't work |
| cg.addEmptyConstructor(Constants.ACC_PUBLIC); |
| |
| InstructionList il = new InstructionList(); |
| ConstantPoolGen cp = cg.getConstantPool(); |
| InstructionFactory factory = new InstructionFactory(cg); |
| |
| int out = cp.addFieldref("java.lang.System", "out", |
| "Ljava/io/PrintStream;"); |
| int println = cp.addMethodref("java.io.PrintStream", "println", |
| "(Ljava/lang/Object;)V"); |
| MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, |
| new Type[] { |
| new ObjectType("java.awt.event.ActionEvent") |
| }, null, "actionPerformed", "foo", il, cp); |
| |
| // System.out.println("actionPerformed:" + event); |
| il.append(new GETSTATIC(out)); |
| il.append(factory.createNew("java.lang.StringBuffer")); |
| il.append(InstructionConstants.DUP); |
| il.append(new PUSH(cp, "actionPerformed:")); |
| il.append(factory.createInvoke("java.lang.StringBuffer", "<init>", Type.VOID, |
| new Type[] {Type.STRING}, Constants.INVOKESPECIAL)); |
| |
| il.append(new ALOAD(1)); |
| il.append(factory.createAppend(Type.OBJECT)); |
| il.append(new INVOKEVIRTUAL(println)); |
| il.append(InstructionConstants.RETURN); |
| |
| mg.stripAttributes(true); |
| mg.setMaxStack(); |
| mg.setMaxLocals(); |
| cg.addMethod(mg.getMethod()); |
| |
| byte[] bytes = cg.getJavaClass().getBytes(); |
| |
| System.out.println("Uncompressed class: " + bytes.length); |
| |
| String s = Utility.encode(bytes, true); |
| System.out.println("Encoded class: " + s.length()); |
| |
| System.out.print("Creating proxy ... "); |
| ActionListener a = (ActionListener)createProxy("foo.bar.", s); |
| System.out.println("Done. Now calling actionPerformed()"); |
| |
| a.actionPerformed(new ActionEvent(a, ActionEvent.ACTION_PERFORMED, "hello")); |
| } else |
| System.err.println("Call me with java org.apache.bcel.util.JavaWrapper ProxyCreator"); |
| } |
| |
| } |