1*f1fbf3c2SXin Li package sample.vector; 2*f1fbf3c2SXin Li 3*f1fbf3c2SXin Li import java.io.IOException; 4*f1fbf3c2SXin Li import javassist.*; 5*f1fbf3c2SXin Li import sample.preproc.Assistant; 6*f1fbf3c2SXin Li 7*f1fbf3c2SXin Li /** 8*f1fbf3c2SXin Li * This is a Javassist program which produce a new class representing 9*f1fbf3c2SXin Li * vectors of a given type. For example, 10*f1fbf3c2SXin Li * 11*f1fbf3c2SXin Li * <ul>import java.util.Vector by sample.vector.VectorAssistant(int)</ul> 12*f1fbf3c2SXin Li * 13*f1fbf3c2SXin Li * <p>requests the Javassist preprocessor to substitute the following 14*f1fbf3c2SXin Li * lines for the original import declaration: 15*f1fbf3c2SXin Li * 16*f1fbf3c2SXin Li * <ul><pre> 17*f1fbf3c2SXin Li * import java.util.Vector; 18*f1fbf3c2SXin Li * import sample.vector.intVector; 19*f1fbf3c2SXin Li * </pre></ul> 20*f1fbf3c2SXin Li * 21*f1fbf3c2SXin Li * <p>The Javassist preprocessor calls <code>VectorAssistant.assist()</code> 22*f1fbf3c2SXin Li * and produces class <code>intVector</code> equivalent to: 23*f1fbf3c2SXin Li * 24*f1fbf3c2SXin Li * <ul><pre> 25*f1fbf3c2SXin Li * package sample.vector; 26*f1fbf3c2SXin Li * 27*f1fbf3c2SXin Li * public class intVector extends Vector { 28*f1fbf3c2SXin Li * pubilc void add(int value) { 29*f1fbf3c2SXin Li * addElement(new Integer(value)); 30*f1fbf3c2SXin Li * } 31*f1fbf3c2SXin Li * 32*f1fbf3c2SXin Li * public int at(int index) { 33*f1fbf3c2SXin Li * return elementAt(index).intValue(); 34*f1fbf3c2SXin Li * } 35*f1fbf3c2SXin Li * } 36*f1fbf3c2SXin Li * </pre></ul> 37*f1fbf3c2SXin Li * 38*f1fbf3c2SXin Li * <p><code>VectorAssistant.assist()</code> uses 39*f1fbf3c2SXin Li * <code>sample.vector.Sample</code> and <code>sample.vector.Sample2</code> 40*f1fbf3c2SXin Li * as a template to produce the methods <code>add()</code> and 41*f1fbf3c2SXin Li * <code>at()</code>. 42*f1fbf3c2SXin Li */ 43*f1fbf3c2SXin Li public class VectorAssistant implements Assistant { 44*f1fbf3c2SXin Li public final String packageName = "sample.vector."; 45*f1fbf3c2SXin Li 46*f1fbf3c2SXin Li /** 47*f1fbf3c2SXin Li * Calls <code>makeSubclass()</code> and produces a new vector class. 48*f1fbf3c2SXin Li * This method is called by a <code>sample.preproc.Compiler</code>. 49*f1fbf3c2SXin Li * 50*f1fbf3c2SXin Li * @see sample.preproc.Compiler 51*f1fbf3c2SXin Li */ assist(ClassPool pool, String vec, String[] args)52*f1fbf3c2SXin Li public CtClass[] assist(ClassPool pool, String vec, String[] args) 53*f1fbf3c2SXin Li throws CannotCompileException 54*f1fbf3c2SXin Li { 55*f1fbf3c2SXin Li if (args.length != 1) 56*f1fbf3c2SXin Li throw new CannotCompileException( 57*f1fbf3c2SXin Li "VectorAssistant receives a single argument."); 58*f1fbf3c2SXin Li 59*f1fbf3c2SXin Li try { 60*f1fbf3c2SXin Li CtClass subclass; 61*f1fbf3c2SXin Li CtClass elementType = pool.get(args[0]); 62*f1fbf3c2SXin Li if (elementType.isPrimitive()) 63*f1fbf3c2SXin Li subclass = makeSubclass2(pool, elementType); 64*f1fbf3c2SXin Li else 65*f1fbf3c2SXin Li subclass = makeSubclass(pool, elementType); 66*f1fbf3c2SXin Li 67*f1fbf3c2SXin Li CtClass[] results = { subclass, pool.get(vec) }; 68*f1fbf3c2SXin Li return results; 69*f1fbf3c2SXin Li } 70*f1fbf3c2SXin Li catch (NotFoundException e) { 71*f1fbf3c2SXin Li throw new CannotCompileException(e); 72*f1fbf3c2SXin Li } 73*f1fbf3c2SXin Li catch (IOException e) { 74*f1fbf3c2SXin Li throw new CannotCompileException(e); 75*f1fbf3c2SXin Li } 76*f1fbf3c2SXin Li } 77*f1fbf3c2SXin Li 78*f1fbf3c2SXin Li /** 79*f1fbf3c2SXin Li * Produces a new vector class. This method does not work if 80*f1fbf3c2SXin Li * the element type is a primitive type. 81*f1fbf3c2SXin Li * 82*f1fbf3c2SXin Li * @param type the type of elements 83*f1fbf3c2SXin Li */ makeSubclass(ClassPool pool, CtClass type)84*f1fbf3c2SXin Li public CtClass makeSubclass(ClassPool pool, CtClass type) 85*f1fbf3c2SXin Li throws CannotCompileException, NotFoundException, IOException 86*f1fbf3c2SXin Li { 87*f1fbf3c2SXin Li CtClass vec = pool.makeClass(makeClassName(type)); 88*f1fbf3c2SXin Li vec.setSuperclass(pool.get("java.util.Vector")); 89*f1fbf3c2SXin Li 90*f1fbf3c2SXin Li CtClass c = pool.get("sample.vector.Sample"); 91*f1fbf3c2SXin Li CtMethod addmethod = c.getDeclaredMethod("add"); 92*f1fbf3c2SXin Li CtMethod atmethod = c.getDeclaredMethod("at"); 93*f1fbf3c2SXin Li 94*f1fbf3c2SXin Li ClassMap map = new ClassMap(); 95*f1fbf3c2SXin Li map.put("sample.vector.X", type.getName()); 96*f1fbf3c2SXin Li 97*f1fbf3c2SXin Li vec.addMethod(CtNewMethod.copy(addmethod, "add", vec, map)); 98*f1fbf3c2SXin Li vec.addMethod(CtNewMethod.copy(atmethod, "at", vec, map)); 99*f1fbf3c2SXin Li vec.writeFile(); 100*f1fbf3c2SXin Li return vec; 101*f1fbf3c2SXin Li } 102*f1fbf3c2SXin Li 103*f1fbf3c2SXin Li /** 104*f1fbf3c2SXin Li * Produces a new vector class. This uses wrapped methods so that 105*f1fbf3c2SXin Li * the element type can be a primitive type. 106*f1fbf3c2SXin Li * 107*f1fbf3c2SXin Li * @param type the type of elements 108*f1fbf3c2SXin Li */ makeSubclass2(ClassPool pool, CtClass type)109*f1fbf3c2SXin Li public CtClass makeSubclass2(ClassPool pool, CtClass type) 110*f1fbf3c2SXin Li throws CannotCompileException, NotFoundException, IOException 111*f1fbf3c2SXin Li { 112*f1fbf3c2SXin Li CtClass vec = pool.makeClass(makeClassName(type)); 113*f1fbf3c2SXin Li vec.setSuperclass(pool.get("java.util.Vector")); 114*f1fbf3c2SXin Li 115*f1fbf3c2SXin Li CtClass c = pool.get("sample.vector.Sample2"); 116*f1fbf3c2SXin Li CtMethod addmethod = c.getDeclaredMethod("add"); 117*f1fbf3c2SXin Li CtMethod atmethod = c.getDeclaredMethod("at"); 118*f1fbf3c2SXin Li 119*f1fbf3c2SXin Li CtClass[] args1 = { type }; 120*f1fbf3c2SXin Li CtClass[] args2 = { CtClass.intType }; 121*f1fbf3c2SXin Li CtMethod m 122*f1fbf3c2SXin Li = CtNewMethod.wrapped(CtClass.voidType, "add", args1, 123*f1fbf3c2SXin Li null, addmethod, null, vec); 124*f1fbf3c2SXin Li vec.addMethod(m); 125*f1fbf3c2SXin Li m = CtNewMethod.wrapped(type, "at", args2, 126*f1fbf3c2SXin Li null, atmethod, null, vec); 127*f1fbf3c2SXin Li vec.addMethod(m); 128*f1fbf3c2SXin Li vec.writeFile(); 129*f1fbf3c2SXin Li return vec; 130*f1fbf3c2SXin Li } 131*f1fbf3c2SXin Li makeClassName(CtClass type)132*f1fbf3c2SXin Li private String makeClassName(CtClass type) { 133*f1fbf3c2SXin Li return packageName + type.getSimpleName() + "Vector"; 134*f1fbf3c2SXin Li } 135*f1fbf3c2SXin Li } 136