KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > emn > info > eaop > instrumentation > InsertEvents


1 /* ----------------------------------------------------------------------------
2  * EAOP 1.0, 2002-12-19
3  * (c) 2002 Remi Douence, Mario Sudholt; OBASCO group; EMN/INRIA; France
4  * THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY WARRANTY
5   -------------------------------------------------------------------------- */

6
7 package fr.emn.info.eaop.instrumentation;
8
9 import fr.emn.info.eaop.*;
10 import fr.emn.info.eaop.recoderaux.*;
11
12 import recoder.*;
13 import recoder.abstraction.*;
14 import recoder.list.*;
15 import recoder.kit.*;
16 import recoder.java.*;
17 import recoder.java.declaration.*;
18 import recoder.java.statement.*;
19 import recoder.java.reference.*;
20
21
22 /**
23  * Class performing instrumentation of source programs with event generation
24  * and calls to the monitor.
25  *
26  * @author MS
27  * @version 1.0
28  */

29 public class InsertEvents extends Instrumentation {
30
31     public InsertEvents(CrossReferenceServiceConfiguration sc,
32             TypeDeclaration td) {
33     super(sc, null, td);
34     }
35
36     /**
37      * Method executing the instrumentation transformation. As a
38      * result the monitor is called with suitable events at
39      * constructor/method call and return points.
40      */

41     public ProblemReport execute() {
42     SelectiveInstrumentation instrument = IO.getInstrumentationContext();
43     boolean isFunction = false;
44     String JavaDoc type = "";
45
46     if (instrument.checkClass(td)) {
47         MemberDeclarationArrayList ml =
48         (MemberDeclarationArrayList) td.getMembers();
49         for (int i = 0, s = ml.size(); i < s; i += 1) {
50         MemberDeclaration m = ml.getMemberDeclaration(i);
51         if (m instanceof MethodDeclaration) {
52             MethodDeclaration md = (MethodDeclaration) m;
53
54             if (!instrument.checkMethodOrConstructor(md)) continue;
55             
56             if (isDelegateeOrDummyConstructor(md)) continue;
57             
58             // distinguish constructors and methods
59
if (md instanceof Constructor)
60             type = "Constructor";
61             else type = "Method";
62             
63             // distinguish function and procedure methods
64
isFunction =
65             Main.getSourceInfo().getReturnType(md) != null;
66
67             // wrap body statements in monitor calls with events
68
StatementMutableList sl =
69             getInitialThisOrSuperStatement(md.getBody());
70             StatementMutableList tl = null;
71             try {
72             boolean instrumentAspect = instrument.checkAspect(td);
73             
74             String JavaDoc str = genCallEvent(md, type, instrumentAspect);
75             sl.add(pf.parseStatements(str));
76             
77             str = genSkipReturnEvent(md, type, isFunction,
78                          instrumentAspect);
79             sl.add(pf.parseStatements(str));
80             
81             sl = genTryCatch(sl, md, isFunction);
82             } catch (ParserException e) {
83             e.printStackTrace();
84             IO.fail("event parsing: "
85                 + e.toString());
86             }
87             //md.setBody(new StatementBlock(sl));
88
md.replaceChild(md.getBody(), new StatementBlock(sl));
89         }
90         }
91     }
92     return Transformation.NO_PROBLEM;
93     }
94
95     boolean isDelegateeOrDummyConstructor(MethodDeclaration md) {
96     boolean ret;
97
98     ret = md.getName().indexOf(origStr) > -1;
99     
100     if (md.getParameterDeclarationCount() == 1) {
101         String JavaDoc pd = md.getParameterDeclarationAt(0).toSource();
102         ret = ret || (pd.indexOf(constructorDummyTypeStr) > -1);
103     }
104
105     return ret;
106     }
107
108     /**
109      * Return a statement calling the monitor with a call event
110      */

111     String JavaDoc genCallEvent(MethodDeclaration md, String JavaDoc type,
112             boolean instrumentAspect) {
113     String JavaDoc traceMethodStr = "";
114     if (!instrumentAspect) traceMethodStr = "trace";
115     else traceMethodStr = "traceRecursive";
116
117     return type + "Call e1 =\n"
118         + "(" + type + "Call) Monitor.monitor." + traceMethodStr + "(\n"
119         + "new " + type + "Call(\n"
120         + "Thread.currentThread(),\n"
121         + "this,\n"
122         + genMethodOrConstructorObject(md, type)
123         + AuxListKit.params2argsObj(md.getParameters()) + "));";
124
125     }
126
127     /**
128      * Return a conditional statement calling a method if necessary and
129      * generates a statement calling the monitor with a suitable
130      * return statement.
131      */

132     String JavaDoc genSkipReturnEvent(MethodDeclaration md,
133                   String JavaDoc type,
134                   boolean isFunction,
135                   boolean instrumentAspect) {
136     String JavaDoc skipStr = "";
137
138     if (!(md instanceof ConstructorDeclaration)) {
139         skipStr = "if (e1.skip) {\n";
140
141         if (isFunction) {
142         String JavaDoc str = "((" +
143             type + "Call) e1).returnValue";
144         Type t = Main.getSourceInfo().getReturnType(md);
145         if (AuxTypeKit.isPrimitive(t))
146             str = "((" + AuxTypeKit.primitiveT2objectT(t.getName())
147             + ")" + str + ")." + t.getName() + "Value()";
148         skipStr += "return (" + t.getName() +")" + str + ";";
149         } else skipStr += "; // skip\n";
150         
151         skipStr += "} else {\n"
152         + genReturnEvent(md, type, isFunction, instrumentAspect) + "}";
153     }
154     else skipStr = genReturnEvent(md, type, isFunction, instrumentAspect);
155
156     return skipStr;
157     }
158
159     /**
160      * Return a statement calling the monitor with a return statement.
161      */

162     String JavaDoc genReturnEvent(MethodDeclaration md,
163               String JavaDoc type,
164               boolean isFunction,
165               boolean instrumentAspect) {
166     String JavaDoc returnStr = "";
167     String JavaDoc str = "";
168     String JavaDoc tName = "";
169
170     if (!isFunction)
171         returnStr =
172         "this." + md.getName() + origStr
173         + "(" + AuxListKit.paramsObj2args(md.getParameters())
174         + ");";
175
176     String JavaDoc traceMethodStr = "";
177     if (!instrumentAspect) traceMethodStr = "trace";
178     else traceMethodStr = "traceRecursive";
179
180     String JavaDoc eventStr = type + "Return e2 =\n"
181         + "(" + type + "Return) Monitor.monitor." + traceMethodStr + "(\n"
182         + "new " + type + "Return(" + "Thread.currentThread(),\n";
183
184     if (isFunction) {
185         str =
186         "this." + md.getName() + origStr
187         + "(" + AuxListKit.paramsObj2args(md.getParameters())
188         + ")";
189         tName = md.getReturnType().getName();
190         if (AuxTypeKit.isPrimitive(md.getReturnType()))
191         str = "new " + AuxTypeKit.primitiveT2objectT(tName)
192               + "(" + str + ")";
193     } else str += "null";
194     eventStr += str + ",\n";
195
196     eventStr += "this,\n " + genMethodOrConstructorObject(md, type)
197                 + "e1.args));";
198
199     if (isFunction) {
200         str = "((" + type + "Return) e2).returnValue";
201         tName = md.getReturnType().getName();
202         if (AuxTypeKit.isPrimitive(md.getReturnType()))
203         str = "((" + AuxTypeKit.primitiveT2objectT(tName) + ")"
204               + str + ")" + "." + tName + "Value()";
205         eventStr +=
206         "return (" + md.getReturnType().getName() +")" + str + ";";
207     }
208     returnStr += eventStr + "}";
209
210     return returnStr;
211     }
212
213     /**
214      * Generate code yielding current method/constructor object.
215      */

216     String JavaDoc genMethodOrConstructorObject(MethodDeclaration md, String JavaDoc type) {
217     String JavaDoc str = "";
218
219     // str = md.getContainingClassType().getName()
220
str = md.getMemberParent().getName()
221         + ".class.getDeclared" + type + "(";
222     if (type == "Method") str += "\"" + md.getName() + "\", ";
223         str += AuxListKit.paramTs2argTs(md.getParameters(), si) + "),\n";
224
225     return str;
226     }
227
228     /**
229      * Encapsulates a statement list in a try statement catching
230      * arbitrary exceptions.
231      */

232     StatementMutableList genTryCatch(StatementMutableList sl,
233                      MethodDeclaration md,
234                      boolean isFunction) {
235     String JavaDoc str;
236     StatementMutableList tryL = null;
237
238     str = "try { ; } catch (Exception e) {\n";
239     str += "System.out.println(\"Exception: \" + e.toString());\n";
240     str += "e.printStackTrace();\n";
241     str += "System.exit(0);\n";
242     if (isFunction)
243         str += "return "
244            + AuxTypeKit.elementOfType(md.getReturnType().getName())
245            + ";";
246     str += "}";
247     
248     try { tryL = pf.parseStatements(str); }
249     catch (ParserException e) {
250         e.printStackTrace();
251         IO.fail("event parsing: " + e.toString());
252     }
253
254     Try t = (Try) tryL.getStatement(0);
255     StatementBlock sb = new StatementBlock(sl);
256     tryL.insert(0, getInitialThisOrSuperStatement(sb));
257     t.replaceChild(t.getBody(), removeInitialThisOrSuperStatement(sb));
258
259     return tryL;
260     }
261
262     /**
263      * Compute a possibly empty sequence of an initial call to
264      * <code>this</code> or <code>super</code> of the argument block.
265      */

266     StatementMutableList getInitialThisOrSuperStatement(StatementBlock b) {
267     StatementArrayList res = new StatementArrayList();
268
269     if (b.getStatementCount() > 0) {
270         Statement s = b.getStatementAt(0);
271         if ((s instanceof ThisConstructorReference) ||
272         (s instanceof SuperConstructorReference) ) res.add(s);
273     }
274
275     return res;
276     }
277
278     /**
279      * Compute a possibly empty statement block which excludes an initial
280      * call to <code>this</code> or <code>super</code> of the argument block.
281      */

282     StatementBlock removeInitialThisOrSuperStatement(StatementBlock b) {
283     StatementMutableList sl = b.getBody();
284     StatementBlock res = null;
285
286     if (sl.size() > 0) {
287         Statement s = sl.getStatement(0);
288         if ((s instanceof ThisConstructorReference) ||
289         (s instanceof SuperConstructorReference)) {
290         sl.remove(0);
291         res = new StatementBlock(sl);
292         } else res = b;
293     }
294
295     return res;
296     }
297 }
298
299
Popular Tags