VectorAssistant.java revision 69e17611504376e4d4603925f8528dfc890fd2c6
169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage sample.vector; 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException; 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*; 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport sample.preproc.Assistant; 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This is a Javassist program which produce a new class representing 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * vectors of a given type. For example, 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul>import java.util.Vector by sample.vector.VectorAssistant(int)</ul> 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>requests the Javassist preprocessor to substitute the following 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * lines for the original import declaration: 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre> 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * import java.util.Vector; 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * import sample.vector.intVector; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>The Javassist preprocessor calls <code>VectorAssistant.assist()</code> 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and produces class <code>intVector</code> equivalent to: 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre> 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * package sample.vector; 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public class intVector extends Vector { 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * pubilc void add(int value) { 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * addElement(new Integer(value)); 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * } 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int at(int index) { 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * return elementAt(index).intValue(); 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * } 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * } 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>VectorAssistant.assist()</code> uses 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>sample.vector.Sample</code> and <code>sample.vector.Sample2</code> 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * as a template to produce the methods <code>add()</code> and 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>at()</code>. 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class VectorAssistant implements Assistant { 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final String packageName = "sample.vector."; 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Calls <code>makeSubclass()</code> and produces a new vector class. 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method is called by a <code>sample.preproc.Compiler</code>. 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see sample.preproc.Compiler 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass[] assist(ClassPool pool, String vec, String[] args) 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (args.length != 1) 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException( 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "VectorAssistant receives a single argument."); 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass subclass; 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass elementType = pool.get(args[0]); 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (elementType.isPrimitive()) 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal subclass = makeSubclass2(pool, elementType); 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal subclass = makeSubclass(pool, elementType); 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] results = { subclass, pool.get(vec) }; 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return results; 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IOException e) { 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e); 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Produces a new vector class. This method does not work if 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the element type is a primitive type. 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param type the type of elements 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass makeSubclass(ClassPool pool, CtClass type) 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException, IOException 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass vec = pool.makeClass(makeClassName(type)); 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.setSuperclass(pool.get("java.util.Vector")); 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass c = pool.get("sample.vector.Sample"); 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod addmethod = c.getDeclaredMethod("add"); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod atmethod = c.getDeclaredMethod("at"); 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassMap map = new ClassMap(); 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal map.put("sample.vector.X", type.getName()); 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.addMethod(CtNewMethod.copy(addmethod, "add", vec, map)); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.addMethod(CtNewMethod.copy(atmethod, "at", vec, map)); 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.writeFile(); 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return vec; 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Produces a new vector class. This uses wrapped methods so that 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the element type can be a primitive type. 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param type the type of elements 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass makeSubclass2(ClassPool pool, CtClass type) 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException, IOException 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass vec = pool.makeClass(makeClassName(type)); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.setSuperclass(pool.get("java.util.Vector")); 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass c = pool.get("sample.vector.Sample2"); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod addmethod = c.getDeclaredMethod("add"); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod atmethod = c.getDeclaredMethod("at"); 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] args1 = { type }; 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] args2 = { CtClass.intType }; 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod m 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = CtNewMethod.wrapped(CtClass.voidType, "add", args1, 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal null, addmethod, null, vec); 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.addMethod(m); 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m = CtNewMethod.wrapped(type, "at", args2, 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal null, atmethod, null, vec); 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.addMethod(m); 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal vec.writeFile(); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return vec; 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String makeClassName(CtClass type) { 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return packageName + type.getSimpleName() + "Vector"; 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 136