/Users/lyon/j4p/src/javassist/sample/vector/VectorAssistant.java

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