KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > interceptor > FieldAdvisorInstrumentor


1 package alt.jiapi.interceptor;
2
3 import java.util.List JavaDoc;
4
5 import java.lang.reflect.Field JavaDoc;
6 import java.lang.reflect.Modifier JavaDoc;
7
8 import alt.jiapi.InstrumentationException;
9
10 import alt.jiapi.event.EventInstrumentor;
11 import alt.jiapi.event.EventRuntime;
12
13 import alt.jiapi.reflect.Instruction;
14 import alt.jiapi.reflect.InstructionFactory;
15 import alt.jiapi.reflect.InstructionList;
16 import alt.jiapi.reflect.JiapiClass;
17 import alt.jiapi.reflect.JiapiField;
18 import alt.jiapi.reflect.JiapiMethod;
19 import alt.jiapi.reflect.Loader;
20 import alt.jiapi.reflect.Signature;
21 import alt.jiapi.reflect.SignatureUtil;
22
23 import alt.jiapi.reflect.FieldExistsException;
24 import alt.jiapi.reflect.MethodExistsException;
25
26 import alt.jiapi.reflect.instruction.FieldAccess;
27 import alt.jiapi.reflect.instruction.Invocation;
28 import alt.jiapi.reflect.instruction.OpcodeGroups;
29 import alt.jiapi.reflect.instruction.Opcodes;
30
31 import alt.jiapi.util.HotSpot;
32 import alt.jiapi.util.HotSpotLocator;
33
34
35 /**
36  * Class FieldInstrumentor.
37  *
38  * @author Mika Riekkinen
39  */

40 class FieldAdvisorInstrumentor extends EventInstrumentor {
41     private AccessAdvisor advisor;
42     private JiapiMethod getMethod;
43     private JiapiMethod setMethod;
44
45     FieldAdvisorInstrumentor(FieldInterceptor fi, AccessAdvisor advisor) {
46         super(fi);
47         this.advisor = advisor;
48
49         JiapiClass jc = getEventProducer();
50         try {
51             this.getMethod =
52                 jc.getDeclaredMethod("getField",
53                                      new String JavaDoc[] { "java.lang.Object",
54                                                     "java.lang.String",
55                                                     "java.lang.Object"});
56
57             this.setMethod =
58                 jc.getDeclaredMethod("setField",
59                                      new String JavaDoc[] { "java.lang.Object",
60                                                     "java.lang.String",
61                                                     "java.lang.Object"});
62         }
63         catch(Exception JavaDoc e) {
64             e.printStackTrace();
65         }
66     }
67
68     public void instrument(JiapiMethod jm) {
69         JiapiClass clazz = jm.getDeclaringClass();
70         JiapiField interceptor = getEventProducerField();
71         InstructionList il = jm.getInstructionList();
72         InstructionFactory factory = il.getInstructionFactory();
73
74         HotSpotLocator hsl =
75             new HotSpotLocator(il, new byte[]{Opcodes.GETSTATIC,
76                                               Opcodes.GETFIELD});
77         HotSpot[] hotSpots = hsl.getHotSpots();
78
79         for (int i = 0; i < hotSpots.length; i++) {
80             FieldAccess fa = (FieldAccess)hotSpots[i].getHotSpotInstruction();
81             short opCode = fa.getOpcode();
82
83             if (!match(fa.getClassName() + "." + fa.getFieldName())) {
84                 continue;
85             }
86
87             InstructionList hsList = hotSpots[i].getInstructionList();
88             InstructionList nList = il.createEmptyList();
89
90             boolean primitive = SignatureUtil.isPrimitive(fa.getTypeName());
91
92
93             if (opCode == Opcodes.GETSTATIC ||
94                 opCode == Opcodes.GETFIELD) {
95                 nList.add(factory.getField(interceptor)); // Interceptor
96

97                 // NOTE: We could store Class into variable,
98
// and use getField() instead of Class.forName() call
99
// Class or objref; 1st parameter to interceptor
100
if (opCode == Opcodes.GETSTATIC) {
101                     short lvIdx =
102                         addClassForNameInstructions(fa.getClassName(), jm);
103                     nList.add(factory.aload(lvIdx));
104 // addClassForNameInstructions(fa.getClassName(), nList);
105
// nList.add(factory.pushNull());
106
}
107                 else {
108                     //addClassForNameInstructions(fa.getClassName(), nList);
109
nList.add(hsList.get(0)); // objref
110
}
111
112                 // Name of the field; 2nd parameter to interceptor
113
nList.add(factory.pushConstant(fa.getFieldName()));
114
115                 // 3rd parameter; field value
116
Instruction pIns = null;
117                 if (primitive) {
118                     // Provide wrapper for primitive types
119
pIns = handlePrimitiveType(fa.getTypeName(), nList);
120                 }
121                 //nList.add(fa);
122
//nList.add(hsList);
123
nList.add(hotSpots[i].getInstructionList());
124
125                 if (pIns != null) {
126                     nList.add(pIns);
127                 }
128
129                 // call Interceptor
130
nList.add(factory.invoke(getMethod));
131
132                 handleReturnValue(nList, fa.getTypeName());
133                 //nList.add(factory.cast(fa.getTypeName()));
134

135                 hotSpots[i].getInstructionList()/* hsList*/.replace(nList);
136             }
137         }
138     }
139
140
141     /**
142      * Add Class.forName(name) instructions in fhe beginning of method.
143      * Class is stored in next available local-variable
144      * We could also store this into class-variable, and initialize
145      * values in <clinit>
146      *
147      * @return index of the local variable, where Class is stored
148      */

149     private short addClassForNameInstructions(String JavaDoc name, JiapiMethod jm) {
150         InstructionList il = jm.getInstructionList();
151         InstructionFactory f = il.getInstructionFactory();
152
153         InstructionList nl = il.createEmptyList();
154         short maxLocals = (short)jm.getMaxLocals();
155         
156         // NOTE: We do not create exception handlers for
157
// Class.forName(...) invocation.
158
// However, we use this to get Class of the running object,
159
// so its Class is allways found.
160
try {
161             nl.add(f.pushConstant(name));
162             nl.add(f.invoke(Modifier.STATIC, "java.lang.Class",
163                             "forName", new Signature("java.lang.Class",
164                                                      new String JavaDoc[] {"java.lang.String"})));
165             nl.add(f.astore(maxLocals));
166         }
167         catch(Exception JavaDoc e) {
168             e.printStackTrace();
169             il.add(f.pushNull());
170         }
171
172 // il.add(nl);
173
il.insert(0, nl);
174
175         return maxLocals;
176     }
177
178
179     private boolean isPublicField(FieldAccess fa) {
180         try {
181             JiapiClass jc = new Loader().loadClass(fa.getClassName());
182             JiapiField jf = jc.getField(fa.getName());
183
184             return Modifier.isPublic(jf.getModifiers());
185         }
186         catch(Exception JavaDoc e) {
187             e.printStackTrace();
188         }
189
190         return false;
191     }
192
193
194
195     private void handleReturnValue(InstructionList il, String JavaDoc rType) {
196         // Convert return value if needed.
197
InstructionFactory factory = il.getInstructionFactory();
198
199         if ("int".equals(rType)) {
200             try {
201                 JiapiClass jc = new Loader().loadClass("java.lang.Integer");
202                 JiapiMethod jm =
203                     jc.getDeclaredMethod("intValue", new String JavaDoc[0]);
204
205                 il.add(factory.cast("java.lang.Integer"));
206                 il.add(factory.invoke(jm));
207             }
208             catch(Exception JavaDoc e) {
209                 e.printStackTrace();
210             }
211         }
212         else if ("long".equals(rType)) {
213             try {
214                 JiapiClass jc = new Loader().loadClass("java.lang.Long");
215                 JiapiMethod jm =
216                     jc.getDeclaredMethod("longValue", new String JavaDoc[0]);
217
218                 il.add(factory.cast("java.lang.Long"));
219                 il.add(factory.invoke(jm));
220             }
221             catch(Exception JavaDoc e) {
222                 e.printStackTrace();
223             }
224         }
225         else if ("char".equals(rType)) {
226             try {
227                 JiapiClass jc = new Loader().loadClass("java.lang.Character");
228                 JiapiMethod jm =
229                     jc.getDeclaredMethod("charValue", new String JavaDoc[0]);
230
231                 il.add(factory.cast("java.lang.Character"));
232                 il.add(factory.invoke(jm));
233             }
234             catch(Exception JavaDoc e) {
235                 e.printStackTrace();
236             }
237         }
238         else if ("boolean".equals(rType)) {
239             try {
240                 JiapiClass jc = new Loader().loadClass("java.lang.Boolean");
241                 JiapiMethod jm =
242                     jc.getDeclaredMethod("booleanValue", new String JavaDoc[0]);
243
244                 il.add(factory.cast("java.lang.Boolean"));
245                 il.add(factory.invoke(jm));
246             }
247             catch(Exception JavaDoc e) {
248                 e.printStackTrace();
249             }
250         }
251         else if ("byte".equals(rType)) {
252             try {
253                 JiapiClass jc = new Loader().loadClass("java.lang.Byte");
254                 JiapiMethod jm =
255                     jc.getDeclaredMethod("byteValue", new String JavaDoc[0]);
256
257                 il.add(factory.cast("java.lang.Byte"));
258                 il.add(factory.invoke(jm));
259             }
260             catch(Exception JavaDoc e) {
261                 e.printStackTrace();
262             }
263         }
264         else if ("float".equals(rType)) {
265             try {
266                 JiapiClass jc = new Loader().loadClass("java.lang.Float");
267                 JiapiMethod jm =
268                     jc.getDeclaredMethod("floatValue", new String JavaDoc[0]);
269
270                 il.add(factory.cast("java.lang.Float"));
271                 il.add(factory.invoke(jm));
272             }
273             catch(Exception JavaDoc e) {
274                 e.printStackTrace();
275             }
276         }
277         else if ("double".equals(rType)) {
278             try {
279                 JiapiClass jc = new Loader().loadClass("java.lang.Double");
280                 JiapiMethod jm =
281                     jc.getDeclaredMethod("doubleValue", new String JavaDoc[0]);
282
283                 il.add(factory.cast("java.lang.Double"));
284                 il.add(factory.invoke(jm));
285             }
286             catch(Exception JavaDoc e) {
287                 e.printStackTrace();
288             }
289         }
290         else if ("void".equals(rType)){
291             // Pop out the return value(probably null) of
292
// the invocation handler if it was a 'void' method
293
il.add(new Instruction(new byte[]{Opcodes.POP}));
294         }
295         else { // Cast to correct Object
296
il.add(factory.cast(rType));
297         }
298     }
299
300
301
302     /**
303      * @return an Invocation to constructor of primitive wrapper
304      */

305     private Instruction handlePrimitiveType(String JavaDoc type, InstructionList il) {
306         InstructionFactory f = il.getInstructionFactory();
307         String JavaDoc cName = null;
308         Signature s = new Signature("void", new String JavaDoc[]{ type });
309
310         if ("int".equals(type)) {
311             cName = "java.lang.Integer";
312         }
313         else if ("long".equals(type)) {
314             cName = "java.lang.Long";
315         }
316         else if ("char".equals(type)) {
317             cName = "java.lang.Character";
318         }
319         else if ("boolean".equals(type)) {
320             cName = "java.lang.Boolean";
321         }
322         else if ("byte".equals(type)) {
323             cName = "java.lang.Byte";
324         }
325         else if ("float".equals(type)) {
326             cName = "java.lang.Float";
327         }
328         else if ("double".equals(type)) {
329             cName = "java.lang.Double";
330         }
331
332          il.add(f.newClass(cName));
333          il.add(f.dup());
334          Instruction ins = f.invoke(Modifier.PUBLIC, cName, "<init>", s);
335          return ins;
336     }
337 }
338
Popular Tags