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