KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > event > MethodEventInstrumentor


1 package alt.jiapi.event;
2
3 import java.lang.reflect.Modifier JavaDoc;
4
5 import alt.jiapi.Instrumentor;
6 import alt.jiapi.reflect.Instruction;
7 import alt.jiapi.reflect.InstructionFactory;
8 import alt.jiapi.reflect.InstructionList;
9 import alt.jiapi.reflect.JiapiClass;
10 import alt.jiapi.reflect.JiapiField;
11 import alt.jiapi.reflect.JiapiMethod;
12 import alt.jiapi.reflect.MethodExistsException;
13 import alt.jiapi.reflect.Signature;
14
15 import alt.jiapi.reflect.instruction.OpcodeGroups;
16 import alt.jiapi.reflect.instruction.Opcodes;
17 import alt.jiapi.reflect.instruction.FieldAccess;
18
19 /**
20  * MethodEventInstrumentor. This class instruments
21  * target classes so, that method entries and exits are trapped
22  * to MethodEventProducer.
23  *
24  * @author Mika Riekkinen
25  */

26 class MethodEventInstrumentor extends EventInstrumentor {
27     MethodEventInstrumentor(MethodEventProducer mep) {
28         super(mep);
29     }
30
31     public void instrument(JiapiMethod jm) {
32         InstructionList il = jm.getInstructionList();
33         InstructionFactory factory = il.getInstructionFactory();
34         JiapiClass mep = getEventProducer();
35         JiapiMethod methodEntered = null;
36         JiapiMethod methodExited = null;
37         JiapiField jiapiField = getEventProducerField();
38
39         // a flag, that tells whether or not InstructionList being
40
// processed is in a static method.
41
boolean isStatic = Modifier.isStatic(il.getDeclaringMethod().getModifiers());
42
43         try {
44             methodEntered =
45                 mep.getDeclaredMethod("methodEntered",
46                                       new String JavaDoc[] { "java.lang.Object",
47                                                      "java.lang.String" });
48             methodExited =
49                 mep.getDeclaredMethod("methodExited",
50                                       new String JavaDoc[] { "java.lang.Object",
51                                                      "java.lang.String" });
52         }
53         catch(Exception JavaDoc e) {
54             System.out.println("ERROR: " + e);
55         }
56
57         // Create instructions for method entrance
58
InstructionList entryList = il.createEmptyList();
59         entryList.add(factory.getField(jiapiField));
60         if (isStatic) {
61             entryList.add(factory.pushConstant(il.getDeclaringMethod().getDeclaringClass().getName())); // BUG: we should pass a Class
62
}
63         else {
64             entryList.add(factory.pushThis());
65         }
66         entryList.add(factory.pushConstant(il.getDeclaringMethod().getName()));
67         entryList.add(factory.invoke(methodEntered));
68
69         // Skip super(....) call, if in <init> method
70
int superIdx = il.indexOf(Opcodes.INVOKESPECIAL);
71
72         // BUG: we should insert entrylist on <clinit> pass the
73
// __jiapi_field initialization
74
if (!"<clinit>".equals(il.getDeclaringMethod().getName())) {
75             // FIXME: See bug above
76
il.insert(superIdx+1, entryList);
77         }
78         else {
79             int idx = findFieldInitIndex(il, jiapiField);
80             if (idx != -1) {
81                 il.insert(idx + 1, entryList);
82             }
83         }
84
85         // Create instructions for method exits
86
InstructionList exitList = il.createEmptyList();
87         exitList.add(factory.getField(jiapiField));
88         if (isStatic) {
89             exitList.add(factory.pushConstant(il.getDeclaringMethod().getDeclaringClass().getName())); // BUG: we should pass a Class
90
}
91         else {
92             exitList.add(factory.pushThis());
93         }
94
95         exitList.add(factory.pushConstant(il.getDeclaringMethod().getName()));
96         exitList.add(factory.invoke(methodExited));
97
98         // Find all method exits
99
int idx = il.indexOf(OpcodeGroups.RETURN_INSTRUCTIONS, 0);
100         while (idx != -1) {
101             Instruction ins = il.get(idx);
102             il.insert(idx, exitList);
103
104             // Next index. Skip Instructions created above.
105
idx = il.indexOf(OpcodeGroups.RETURN_INSTRUCTIONS,
106                              idx + exitList.size() + 1);
107         }
108     }
109
110
111     // Find event producer initialization on <clinit>
112
private int findFieldInitIndex(InstructionList il, JiapiField jiapiField) {
113         int idx = -1;
114         
115         while ((idx = il.indexOf(Opcodes.PUTSTATIC, idx+1)) != -1) {
116             FieldAccess fa = (FieldAccess)il.get(idx);
117             if (fa.getFieldName().equals(jiapiField.getName())) {
118                 break;
119             }
120         }
121
122         return idx;
123     }
124 }
125
Popular Tags