import java.io.*; import de.fub.bytecode.classfile.*; import de.fub.bytecode.generic.*; import de.fub.bytecode.util.ByteSequence; import de.fub.bytecode.*; import java.awt.event.*; import java.util.Vector; import java.util.zip.*; /** * Dynamically creates and uses a proxy for java.awt.event.ActionListener * via the classloader mechanism if called with *
java de.fub.bytecode.util.JavaWrapper ProxyCreator
* * 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.
This is * comparable to the mechanism provided via * java.lang.reflect.Proxy but more flexible. * * @version $Id: ProxyCreator.java,v 1.5 2001/08/27 11:25:38 dahm Exp $ * @author M. Dahm * @see de.fub.bytecode.util.JavaWrapper * @see de.fub.bytecode.util.ClassLoader * @see Utility */ public class ProxyCreator { /** Load class and create instance */ public static Object createProxy(String class_name) { try { Class cl = Class.forName("$$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 de.fub.bytecode.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", "", 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(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 de.fub.bytecode.util.JavaWrapper ProxyCreator"); } }