KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ch > ethz > prose > jvmai > jikesrvm > advice_weaver > AdviceJVMAI


1 package ch.ethz.prose.jvmai.jikesrvm.advice_weaver;
2
3 import java.lang.reflect.*;
4 import java.util.*;
5
6 import ch.ethz.jvmai.*;
7
8 import com.ibm.JikesRVM.VM_Callbacks;
9 import com.ibm.JikesRVM.VM_Thread;
10 import com.ibm.JikesRVM.classloader.*;
11
12 /**
13  * A JVMAspectInterface implementation that is based on advice weaving at
14  * bytecode level.
15  *
16  * @author Johann Gyger
17  */

18 public class AdviceJVMAI
19   implements VM_Callbacks.ClassLoadedMonitor, VM_Callbacks.ExceptionThrownMonitor, VM_Callbacks.ExceptionCaughtMonitor, JVMAspectInterface {
20
21   /**
22    * Sole instance of this class.
23    */

24   protected static AdviceJVMAI instance;
25
26   /**
27    * Threads for which the aspect interface is suspended;
28    */

29   protected static BitSet suspendedThreads;
30
31   /**
32    * Is this aspect interface up and running?
33    */

34   protected static boolean initialized;
35
36   /**
37    * Currently registered join point hook.
38    */

39   protected static JoinPointHook hook;
40
41   /**
42    * Storage for aopTags registered with join points. An ID of a method or a
43    * field is used as index into these arrays.
44    */

45   protected static Object JavaDoc[] fieldAccessTags;
46   protected static Object JavaDoc[] fieldModificationTags;
47   protected static Object JavaDoc[] methodEntryTags;
48   protected static Object JavaDoc[] methodExitTags;
49   protected static Object JavaDoc[] exceptionThrowTags;
50   protected static Object JavaDoc[] exceptionCatchTags;
51
52   /**
53    * Dummy-tag used to mark join points registered with aopTag 'null' in the
54    * tag arrays.
55    */

56   protected static Object JavaDoc aopNullTag = new Object JavaDoc();
57
58   protected static MethodEntryJoinPointImpl methodEntryJoinPoint = new MethodEntryJoinPointImpl();
59   protected static MethodExitJoinPointImpl methodExitJoinPoint = new MethodExitJoinPointImpl();
60   protected static FieldAccessJoinPointImpl fieldAccessJoinPoint = new FieldAccessJoinPointImpl();
61   protected static FieldModificationJoinPointImpl fieldModificationJoinPoint = new FieldModificationJoinPointImpl();
62   protected static ExceptionThrowJoinPointImpl exceptionThrowJoinPoint = new ExceptionThrowJoinPointImpl();
63   protected static ExceptionCatchJoinPointImpl exceptionCatchJoinPoint = new ExceptionCatchJoinPointImpl();
64
65   /**
66    * Get sole instance (singleton) of this class.
67    *
68    * @return Sole instance of this class
69    */

70   public static AdviceJVMAI getInstance() {
71     if (instance == null) {
72       instance = new AdviceJVMAI();
73       VM_Callbacks.addClassLoadedMonitor(instance);
74       VM_Callbacks.addExceptionThrownMonitor(instance);
75       VM_Callbacks.addExceptionCaughtMonitor(instance);
76     }
77     return instance;
78   }
79
80   /**
81    * This callback will be invoked at method entry join points. Invocation only
82    * takes place if the callback is woven in to the corresponding method.
83    *
84    * @param methodId method identifier
85    * @param this0 object on which the method is executed
86    * @param args actual arguments of method being intercepted
87    */

88   public static final void onMethodEntry(int methodId, Object JavaDoc this0, Object JavaDoc[] args) {
89     if (hook == null || suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
90       return;
91
92     //System.out.println("AdviceJVMAI.onMethodEntry(): " + methodId + " / " + this0 + " / " + Arrays.asList(args));
93
methodEntryJoinPoint.init(methodId, methodEntryTags[methodId], this0, args);
94     hook.onMethodEntry(methodEntryJoinPoint);
95   }
96
97   /**
98    * This callback will be invoked at method exit join points. Invocation only
99    * takes place if the callback is woven in to the corresponding method.
100    *
101    * @param methodId method identifier
102    * @param this0 object on which the method is executed
103    * @param args actual arguments of method being intercepted
104    */

105   public static final void onMethodExit(int methodId, Object JavaDoc this0, Object JavaDoc[] args) {
106     if (hook == null || suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
107       return;
108
109     //System.out.println("AdviceJVMAI.onMethodExit(): " + methodId + " / " + this0 + " / " + Arrays.asList(args));
110
methodExitJoinPoint.init(methodId, methodExitTags[methodId], this0, args);
111     hook.onMethodExit(methodExitJoinPoint);
112   }
113
114   /**
115    * This callback will be invoked at field access join points. Invocation only
116    * takes place if the callback is woven in to the corresponding method.
117    *
118    * @param owner object that contains the field
119    * @param fieldId field identifier
120    * @param methodId method identifier
121    * @param this0 object on which the method containing the field access is
122    * executed
123    * @param args actual arguments of method being intercepted
124    */

125   public static final void onFieldAccess(Object JavaDoc owner, int fieldId, int methodId, Object JavaDoc this0, Object JavaDoc[] args) {
126     if (hook == null || suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
127       return;
128
129     fieldAccessJoinPoint.init(methodId, fieldAccessTags[fieldId], this0, args, fieldId, owner);
130     //System.out.println("AdviceJVMAI.onFieldAccess(): " + fieldAccessJoinPoint.getAopTag());
131
//System.out.println("AdviceJVMAI.onFieldAccess(): " + fieldAccessJoinPoint.getField() + " / " + this0);
132
hook.onFieldAccess(fieldAccessJoinPoint);
133   }
134
135   /**
136    * This callback will be invoked at field modification join points.
137    * Invocation only takes place if the callback is woven in to the
138    * corresponding method.
139    *
140    * @param owner object that contains the field
141    * @param fieldId field identifier
142    * @param methodId method identifier
143    * @param this0 object on which the method containing the field access is
144    * executed
145    * @param args actual arguments of method being intercepted
146    */

147   public static final void onFieldModification(Object JavaDoc owner, int fieldId, int methodId, Object JavaDoc this0, Object JavaDoc[] args) {
148     if (hook == null || suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
149       return;
150
151     //System.out.println("AdviceJVMAI.onMethodExit(): " + owner + " / " + fieldId + " / " + methodId + " / " + this0 + " / " + Arrays.asList(args));
152
fieldModificationJoinPoint.init(methodId, fieldModificationTags[fieldId], this0, args, fieldId, owner);
153     //System.out.println("AdviceJVMAI.onFieldModification(): " + fieldModificationJoinPoint.getField());
154
hook.onFieldModification(fieldModificationJoinPoint);
155   }
156
157   /**
158    * Create new instance. Used by singleton pattern.
159    */

160   protected AdviceJVMAI() {}
161
162   public void notifyClassLoaded(VM_Class klass) {
163     if (!initialized || hook == null || suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
164       return;
165
166     //System.out.println("AdviceJVMAI.notifyClassLoaded(): " + klass);
167
hook.onClassLoad(klass.getClassForType());
168   }
169
170   public final void notifyExceptionThrown(Throwable JavaDoc exception, VM_Method thrower) {
171     if (hook == null)
172       return;
173
174     int id = java.lang.JikesRVMSupport.getTypeForClass(exception.getClass()).getId();
175     if (id >= exceptionThrowTags.length)
176       return;
177
178     Object JavaDoc tag = exceptionThrowTags[id];
179     if (tag == null)
180       return;
181
182     if (suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
183       return;
184
185     // Ignore exceptions thrown in the VM
186
if (thrower.getDeclaringClass().toString().startsWith("com.ibm.JikesRVM."))
187       return;
188
189     exceptionThrowJoinPoint.init(thrower.getId(), tag, null, null, exception);
190     //System.out.println("AdviceJVMAI.notifyExceptionThrown(): " + exception + " / " + thrower);
191
hook.onExceptionThrow(exceptionThrowJoinPoint);
192   }
193
194   public final void notifyExceptionCaught(Throwable JavaDoc exception, VM_Method catcher) {
195     if (hook == null)
196       return;
197
198     int id = java.lang.JikesRVMSupport.getTypeForClass(exception.getClass()).getId();
199     if (id >= exceptionCatchTags.length)
200       return;
201
202     Object JavaDoc tag = exceptionCatchTags[id];
203     if (tag == null)
204       return;
205
206     if (suspendedThreads.get(VM_Thread.getCurrentThread().getIndex()))
207       return;
208
209     // Ignore exceptions caught in the VM
210
if (catcher.getDeclaringClass().toString().startsWith("com.ibm.JikesRVM."))
211       return;
212
213     exceptionCatchJoinPoint.init(catcher.getId(), tag, null, null, exception);
214     //System.out.println("AdviceJVMAI.notifyExceptionCaught(): " + exception + " / " + catcher);
215
hook.onExceptionCatch(exceptionCatchJoinPoint);
216   }
217
218   public void startup(String JavaDoc[] packagePrefixes, boolean openWorldAssumption) {
219     fieldAccessTags = new Object JavaDoc[1024];
220     fieldModificationTags = new Object JavaDoc[1024];
221     methodEntryTags = new Object JavaDoc[1024];
222     methodExitTags = new Object JavaDoc[1024];
223     exceptionThrowTags = new Object JavaDoc[1024];
224     exceptionCatchTags = new Object JavaDoc[1024];
225     suspendedThreads = new BitSet(1024);
226
227     initialized = true;
228   }
229
230   public void teardown() {
231     //System.out.println("AdviceJVMAI.teardown()");
232
hook = null;
233     initialized = false;
234
235     fieldAccessTags = null;
236     fieldModificationTags = null;
237     methodEntryTags = null;
238     methodExitTags = null;
239     exceptionThrowTags = null;
240     exceptionCatchTags = null;
241     suspendedThreads.clear();
242
243     FieldWeaver.resetAll();
244     MethodWeaver.resetAll();
245   }
246
247   public void setJoinPointHook(JoinPointHook h) {
248     if (!initialized)
249       throw new NotInitializedException();
250
251     hook = h;
252   }
253
254   public void setFieldAccessWatch(Field f, Object JavaDoc aopTag) {
255     if (!initialized)
256       throw new NotInitializedException();
257     if (f == null)
258       throw new NullPointerException JavaDoc("Parameter `f' must not be null.");
259     if (aopTag == null)
260       throw new NullPointerException JavaDoc("Parameter `aopTag' must not be null.");
261
262     //System.out.println("AdviceJVMAI.setFieldAccessWatch(): " + f);
263
int id = java.lang.reflect.JikesRVMSupport.getFieldOf(f).getId();
264     fieldAccessTags = setWatch(fieldAccessTags, aopTag, id);
265     FieldWeaver.getWeaver(f).setFieldAccessEnabled(true);
266   }
267
268   public void clearFieldAccessWatch(Field f) {
269     if (!initialized)
270       throw new NotInitializedException();
271     if (f == null)
272       throw new NullPointerException JavaDoc("Parameter `f' must not be null.");
273
274     int id = java.lang.reflect.JikesRVMSupport.getFieldOf(f).getId();
275     clearWatch(fieldAccessTags, id);
276     FieldWeaver.getWeaver(f).setFieldAccessEnabled(false);
277   }
278
279   public void setFieldModificationWatch(Field f, Object JavaDoc aopTag) {
280     if (!initialized)
281       throw new NotInitializedException();
282     if (f == null)
283       throw new NullPointerException JavaDoc("Parameter `f' must not be null.");
284     if (aopTag == null)
285       throw new NullPointerException JavaDoc("Parameter `aopTag' must not be null.");
286
287     //System.out.println("AdviceJVMAI.setFieldModificationWatch(): " + f);
288
int id = java.lang.reflect.JikesRVMSupport.getFieldOf(f).getId();
289     fieldModificationTags = setWatch(fieldModificationTags, aopTag, id);
290     FieldWeaver.getWeaver(f).setFieldModificationEnabled(true);
291   }
292
293   public void clearFieldModificationWatch(Field f) {
294     if (!initialized)
295       throw new NotInitializedException();
296     if (f == null)
297       throw new NullPointerException JavaDoc("Parameter `f' must not be null.");
298
299     int id = java.lang.reflect.JikesRVMSupport.getFieldOf(f).getId();
300     clearWatch(fieldModificationTags, id);
301     FieldWeaver.getWeaver(f).setFieldModificationEnabled(false);
302   }
303
304   public void setMethodEntryWatch(Method m, Object JavaDoc aopTag) {
305     if (!initialized)
306       throw new NotInitializedException();
307     if (m == null)
308       throw new NullPointerException JavaDoc("Parameter `m' must not be null.");
309     if (aopTag == null)
310       throw new NullPointerException JavaDoc("Parameter `aopTag' must not be null.");
311     if (Modifier.isAbstract(m.getModifiers()))
312       throw new CannotSetWatchException("Method is abstract: " + m);
313
314     //System.out.println("AdviceJVMAI.setMethodEntryWatch(): " + m);
315
int id = java.lang.reflect.JikesRVMSupport.getMethodOf(m).getId();
316     methodEntryTags = setWatch(methodEntryTags, aopTag, id);
317     MethodWeaver.getWeaver(m).setMethodEntryEnabled(true);
318   }
319
320   public void clearMethodEntryWatch(Method m) {
321     if (!initialized)
322       throw new NotInitializedException();
323     if (m == null)
324       throw new NullPointerException JavaDoc("Parameter `m' must not be null.");
325
326     //System.out.println("AdviceJVMAI.clearMethodEntryWatch(): " + m);
327
int id = java.lang.reflect.JikesRVMSupport.getMethodOf(m).getId();
328     clearWatch(methodEntryTags, id);
329     MethodWeaver.getWeaver(m).setMethodEntryEnabled(false);
330   }
331
332   public void setMethodExitWatch(Method m, Object JavaDoc aopTag) {
333     if (!initialized)
334       throw new NotInitializedException();
335     if (m == null)
336       throw new NullPointerException JavaDoc("Parameter `m' must not be null.");
337     if (aopTag == null)
338       throw new NullPointerException JavaDoc("Parameter `aopTag' must not be null.");
339     if (Modifier.isAbstract(m.getModifiers()))
340       throw new CannotSetWatchException("Method is abstract: " + m);
341
342     //System.out.println("AdviceJVMAI.setMethodExitWatch(): " + m);
343
int id = java.lang.reflect.JikesRVMSupport.getMethodOf(m).getId();
344     methodExitTags = setWatch(methodExitTags, aopTag, id);
345     MethodWeaver.getWeaver(m).setMethodExitEnabled(true);
346   }
347
348   public void clearMethodExitWatch(Method m) {
349     if (!initialized)
350       throw new NotInitializedException();
351     if (m == null)
352       throw new NullPointerException JavaDoc("Parameter `m' must not be null.");
353
354     //System.out.println("AdviceJVMAI.clearMethodEntryWatch(): " + m);
355
int id = java.lang.reflect.JikesRVMSupport.getMethodOf(m).getId();
356     clearWatch(methodExitTags, id);
357     MethodWeaver.getWeaver(m).setMethodExitEnabled(false);
358   }
359
360   public void setExceptionThrowWatch(Class JavaDoc c, Object JavaDoc aopTag) {
361     if (!initialized)
362       throw new NotInitializedException();
363     if (c == null)
364       throw new NullPointerException JavaDoc("Parameter `c' must not be null.");
365     if (aopTag == null)
366       throw new NullPointerException JavaDoc("Parameter `aopTag' must not be null.");
367
368     //System.out.println("AdviceJVMAI.setExceptionThrowWatch(): " + c);
369
int id = java.lang.JikesRVMSupport.getTypeForClass(c).getId();
370     exceptionThrowTags = setWatch(exceptionThrowTags, aopTag, id);
371   }
372
373   public void clearExceptionThrowWatch(Class JavaDoc c) {
374     if (!initialized)
375       throw new NotInitializedException();
376     if (c == null)
377       throw new NullPointerException JavaDoc("Parameter `c' must not be null.");
378
379     int id = java.lang.JikesRVMSupport.getTypeForClass(c).getId();
380     clearWatch(exceptionThrowTags, id);
381   }
382
383   public void setExceptionCatchWatch(Class JavaDoc c, Object JavaDoc aopTag) {
384     if (!initialized)
385       throw new NotInitializedException();
386     if (c == null)
387       throw new NullPointerException JavaDoc("Parameter `c' must not be null.");
388     if (aopTag == null)
389       throw new NullPointerException JavaDoc("Parameter `aopTag' must not be null.");
390
391     //System.out.println("AdviceJVMAI.setExceptionCatchWatch(): " + c);
392
int id = java.lang.JikesRVMSupport.getTypeForClass(c).getId();
393     exceptionCatchTags = setWatch(exceptionCatchTags, aopTag, id);
394   }
395
396   public void clearExceptionCatchWatch(Class JavaDoc c) {
397     if (!initialized)
398       throw new NotInitializedException();
399     if (c == null)
400       throw new NullPointerException JavaDoc("Parameter `c' must not be null.");
401
402     int id = java.lang.JikesRVMSupport.getTypeForClass(c).getId();
403     clearWatch(exceptionCatchTags, id);
404   }
405
406   public void suspendNotification(Thread JavaDoc thread) {
407     if (!initialized)
408       throw new NotInitializedException();
409     if (thread == null)
410       throw new NullPointerException JavaDoc("Parameter `thread' must not be null");
411
412     suspendedThreads.set(thread.getIndex());
413   }
414
415   public void resumeNotification(Thread JavaDoc thread) {
416     if (!initialized)
417       throw new NotInitializedException();
418     if (thread == null)
419       throw new NullPointerException JavaDoc("Parameter `thread' must not be null");
420
421     FieldWeaver.commit();
422     MethodWeaver.commit();
423     suspendedThreads.set(thread.getIndex(), false);
424   }
425
426   public List getLoadedClasses() {
427     if (!initialized)
428       throw new NotInitializedException();
429
430     VM_Type[] types = VM_Type.getTypes();
431     Vector classes = new Vector();
432
433     for (int t = 0; t < types.length; t++) {
434       if ((types[t] == null) || !types[t].isClassType())
435         continue;
436
437       VM_Class klass = types[t].asClass();
438       if (!klass.isResolved() || klass.toString().startsWith("com.ibm.JikesRVM."))
439         continue;
440
441       classes.add(klass.getClassForType());
442     }
443
444     return classes;
445   }
446
447   /**
448    * Set `tags[id]' to `tag'. If `tags' is too small then resize it
449    * appriopriately.
450    */

451   protected Object JavaDoc[] setWatch(Object JavaDoc[] tags, Object JavaDoc tag, int id) {
452     synchronized (tags) {
453       try {
454         if (tags[id] != null)
455           throw new WatchAlreadySetException("<" + id + ">");
456       } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
457         Object JavaDoc tmp[] = new Object JavaDoc[2 * id];
458         System.arraycopy(tags, 0, tmp, 0, tags.length);
459         tags = tmp;
460       }
461       tags[id] = (tag == null) ? aopNullTag : tag;
462     }
463     return tags;
464   }
465
466   /**
467    * Set `tags[id] = null'. If `id' is out of bounds or the watch already
468    * cleared a WatchNotSetException is thrown.
469    *
470    * @param tags AOP tag array
471    * @param id Index into `tags'
472    */

473   protected void clearWatch(Object JavaDoc[] tags, int id) {
474     synchronized (tags) {
475       try {
476         if (tags[id] == null)
477           throw new WatchNotSetException("<" + id + ">");
478         tags[id] = null;
479       } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
480         throw new WatchNotSetException("<" + id + ">");
481       }
482     }
483   }
484
485 }
486
Popular Tags