KickJava   Java API By Example, From Geeks To Geeks.

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


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
22 import alt.jiapi.reflect.FieldExistsException;
23 import alt.jiapi.reflect.MethodExistsException;
24
25 import alt.jiapi.reflect.instruction.FieldAccess;
26 import alt.jiapi.reflect.instruction.OpcodeGroups;
27 import alt.jiapi.reflect.instruction.Opcodes;
28
29 import alt.jiapi.util.HotSpot;
30 import alt.jiapi.util.HotSpotLocator;
31
32
33 /**
34  * Class FieldInstrumentor.
35  *
36  * @author Mika Riekkinen
37  */

38 class FieldInstrumentor extends EventInstrumentor {
39     private FieldHandler handler;
40     private JiapiMethod getMethod;
41     private JiapiMethod setMethod;
42
43     FieldInstrumentor(FieldInterceptor2 ii, FieldHandler handler) {
44         super(ii);
45         this.handler = handler;
46
47         JiapiClass jc = getEventProducer();
48         try {
49             this.getMethod =
50                 jc.getDeclaredMethod("getField",
51                                      new String JavaDoc[] { "java.lang.Object",
52                                                     "java.lang.String"});
53
54             this.setMethod =
55                 jc.getDeclaredMethod("setField",
56                                      new String JavaDoc[] { "java.lang.Object",
57                                                     "java.lang.String",
58                                                     "java.lang.Object"});
59         }
60         catch(Exception JavaDoc e) {
61             e.printStackTrace();
62         }
63     }
64
65     public void instrument(JiapiMethod jm) {
66         JiapiField interceptor = getEventProducerField();
67         InstructionList il = jm.getInstructionList();
68         InstructionFactory factory = il.getInstructionFactory();
69
70         HotSpotLocator hsl =
71             new HotSpotLocator(il,
72                                new byte[]{Opcodes.GETSTATIC/*,Opcodes.PUTSTATIC*/});
73         HotSpot[] hotSpots = hsl.getHotSpots();
74
75         for (int i = 0; i < hotSpots.length; i++) {
76             FieldAccess fa = (FieldAccess)hotSpots[i].getHotSpotInstruction();
77             
78             if (fa.getName().startsWith("__jiapi")) {
79                 continue;
80             }
81
82             if (!match(fa.getClassName() + "." + fa.getFieldName())) {
83                 continue;
84             }
85
86             // BUG: We cannot use reflection in this interceptor, since it
87
// is allowed only for public fields.
88
if (!isPublicField(fa)) {
89                 continue;
90             }
91
92             InstructionList hsList = hotSpots[i].getInstructionList();
93             InstructionList nList = il.createEmptyList();
94
95             nList.add(factory.getField(interceptor)); // Interceptor
96

97             // Class or objref; 1st parameter to interceptor
98
if ((fa.getOpcode() == Opcodes.GETSTATIC) ||
99                 (fa.getOpcode() == Opcodes.PUTSTATIC)) {
100                 addClassForNameInstructions(fa.getClassName(), nList);
101             }
102             else {
103                 nList.add(il.get(0)); // objref
104
}
105
106             // Name of the field; 2nd parameter to interceptor
107
nList.add(factory.pushConstant(fa.getClassName() + "." +
108                                            fa.getFieldName()));
109
110             // call Interceptor
111
if ((fa.getOpcode() == Opcodes.GETSTATIC) ||
112                 (fa.getOpcode() == Opcodes.GETFIELD)) {
113                 nList.add(factory.invoke(getMethod));
114             }
115             else {
116                 nList.add(il.get(1)); // value ???
117
nList.add(factory.invoke(setMethod));
118             }
119             
120             handleReturnValue(nList, fa.getTypeName());
121
122             //nList.add(factory.cast(fa.getTypeName()));
123

124             hsList.replace(nList);
125         }
126     }
127
128
129     private void addClassForNameInstructions(String JavaDoc name, InstructionList il) {
130         InstructionFactory f = il.getInstructionFactory();
131
132         InstructionList nl = il.createEmptyList();
133         
134         // NOTE: We do not create exception handlers for
135
// Class.forName(...) invocation.
136
// However, we use this to get Class of the running object,
137
// so its Class is allways found.
138
try {
139             nl.add(f.pushConstant(name));
140             nl.add(f.invoke(Modifier.STATIC, "java.lang.Class",
141                             "forName", new Signature("java.lang.Class",
142                                                      new String JavaDoc[] {"java.lang.String"})));
143         }
144         catch(Exception JavaDoc e) {
145             e.printStackTrace();
146             il.add(f.pushNull());
147         }
148
149         il.add(nl);
150     }
151
152
153     private boolean isPublicField(FieldAccess fa) {
154         try {
155             JiapiClass jc = new Loader().loadClass(fa.getClassName());
156             JiapiField jf = jc.getField(fa.getName());
157
158             return Modifier.isPublic(jf.getModifiers());
159         }
160         catch(Exception JavaDoc e) {
161             e.printStackTrace();
162         }
163
164         return false;
165     }
166
167
168     private void handleReturnValue(InstructionList il, String JavaDoc rType) {
169         // Convert return value if needed.
170
InstructionFactory factory = il.getInstructionFactory();
171
172         if ("int".equals(rType)) {
173             try {
174                 JiapiClass jc = new Loader().loadClass("java.lang.Integer");
175                 JiapiMethod jm =
176                     jc.getDeclaredMethod("intValue", new String JavaDoc[0]);
177
178                 il.add(factory.cast("java.lang.Integer"));
179                 il.add(factory.invoke(jm));
180             }
181             catch(Exception JavaDoc e) {
182                 e.printStackTrace();
183             }
184         }
185         else if ("long".equals(rType)) {
186             try {
187                 JiapiClass jc = new Loader().loadClass("java.lang.Long");
188                 JiapiMethod jm =
189                     jc.getDeclaredMethod("longValue", new String JavaDoc[0]);
190
191                 il.add(factory.cast("java.lang.Long"));
192                 il.add(factory.invoke(jm));
193             }
194             catch(Exception JavaDoc e) {
195                 e.printStackTrace();
196             }
197         }
198         else if ("char".equals(rType)) {
199             try {
200                 JiapiClass jc = new Loader().loadClass("java.lang.Character");
201                 JiapiMethod jm =
202                     jc.getDeclaredMethod("charValue", new String JavaDoc[0]);
203
204                 il.add(factory.cast("java.lang.Character"));
205                 il.add(factory.invoke(jm));
206             }
207             catch(Exception JavaDoc e) {
208                 e.printStackTrace();
209             }
210         }
211         else if ("boolean".equals(rType)) {
212             try {
213                 JiapiClass jc = new Loader().loadClass("java.lang.Boolean");
214                 JiapiMethod jm =
215                     jc.getDeclaredMethod("booleanValue", new String JavaDoc[0]);
216
217                 il.add(factory.cast("java.lang.Boolean"));
218                 il.add(factory.invoke(jm));
219             }
220             catch(Exception JavaDoc e) {
221                 e.printStackTrace();
222             }
223         }
224         else if ("byte".equals(rType)) {
225             try {
226                 JiapiClass jc = new Loader().loadClass("java.lang.Byte");
227                 JiapiMethod jm =
228                     jc.getDeclaredMethod("byteValue", new String JavaDoc[0]);
229
230                 il.add(factory.cast("java.lang.Byte"));
231                 il.add(factory.invoke(jm));
232             }
233             catch(Exception JavaDoc e) {
234                 e.printStackTrace();
235             }
236         }
237         else if ("float".equals(rType)) {
238             try {
239                 JiapiClass jc = new Loader().loadClass("java.lang.Float");
240                 JiapiMethod jm =
241                     jc.getDeclaredMethod("floatValue", new String JavaDoc[0]);
242
243                 il.add(factory.cast("java.lang.Float"));
244                 il.add(factory.invoke(jm));
245             }
246             catch(Exception JavaDoc e) {
247                 e.printStackTrace();
248             }
249         }
250         else if ("double".equals(rType)) {
251             try {
252                 JiapiClass jc = new Loader().loadClass("java.lang.Double");
253                 JiapiMethod jm =
254                     jc.getDeclaredMethod("doubleValue", new String JavaDoc[0]);
255
256                 il.add(factory.cast("java.lang.Double"));
257                 il.add(factory.invoke(jm));
258             }
259             catch(Exception JavaDoc e) {
260                 e.printStackTrace();
261             }
262         }
263         else if ("void".equals(rType)){
264             // Pop out the return value(probably null) of
265
// the invocation handler if it was a 'void' method
266
il.add(new Instruction(new byte[]{Opcodes.POP}));
267         }
268         else { // Cast to correct Object
269
il.add(factory.cast(rType));
270         }
271     }
272 }
273
Popular Tags