/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