001: //
002: // This file is part of the prose package.
003: //
004: // The contents of this file are subject to the Mozilla Public License
005: // Version 1.1 (the "License"); you may not use this file except in
006: // compliance with the License. You may obtain a copy of the License at
007: // http://www.mozilla.org/MPL/
008: //
009: // Software distributed under the License is distributed on an "AS IS" basis,
010: // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: // for the specific language governing rights and limitations under the
012: // License.
013: //
014: // The Original Code is prose.
015: //
016: // The Initial Developer of the Original Code is Andrei Popovici. Portions
017: // created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
018: // All Rights Reserved.
019: //
020: // Contributor(s):
021: // $Id: JoinPointManager.java,v 1.4 2005/06/25 16:56:13 anicoara Exp $
022: // =====================================================================
023: //
024: // (history at end)
025: //
026:
027: package ch.ethz.prose.engine;
028:
029: // used packages
030: import java.lang.reflect.InvocationTargetException;
031: import java.lang.reflect.Method;
032: import java.lang.reflect.Field;
033: import java.lang.reflect.Constructor;
034:
035: import java.util.Collection;
036: import java.util.HashMap;
037: import java.util.HashSet;
038: import java.util.Iterator;
039: import java.util.List;
040: import java.util.Map;
041: import java.util.Set;
042: import java.util.Vector;
043:
044: import ch.ethz.jvmai.ExceptionJoinPoint;
045: import ch.ethz.jvmai.ExceptionCatchJoinPoint;
046: import ch.ethz.jvmai.FieldAccessJoinPoint;
047: import ch.ethz.jvmai.FieldModificationJoinPoint;
048: import ch.ethz.jvmai.JVMAspectInterface;
049: import ch.ethz.jvmai.JoinPoint;
050: import ch.ethz.jvmai.JoinPointHook;
051: import ch.ethz.jvmai.MethodEntryJoinPoint;
052: import ch.ethz.jvmai.MethodExitJoinPoint;
053: import ch.ethz.jvmai.MethodRedefineJoinPoint;
054: import ch.ethz.jvmai.ConstructorJoinPoint;
055: import ch.ethz.prose.Insertable;
056: import ch.ethz.prose.ProsePermission;
057: import ch.ethz.prose.crosscut.Crosscut;
058: import ch.ethz.inf.util.Logger;
059: import ch.ethz.jvmai.SunBCELRepositoryInterface;
060:
061: /**
062: * Class JoinPointManagerImpl defines implements two of the basic methods
063: * <code>JoinPointManager</code>. Subclasses of <code>AbstractJoinPointManager</code>
064: * should define only the link between registering event requests and the proper notification.
065: * They should use the <code>notifyListeners</code> method in order to notify the listeners
066: * of an event that this event occured, and invoke <code>handleExceptions</code> to handle
067: * notification exceptions. By providing an implementation of <code>handleExceptions</code>
068: * with a different <code>handleExceptions</code> method, subclasses may change the policy
069: * for exception handling.
070: * <p>
071: * All implementations of <code>AbstractJoinPointManager</code> should also define the
072: * abstract methods <code>suspendListenerNotification</code> and <code>resumeListenerNotification</code>
073: *
074: * @version $Revision: 1.4 $
075: * @author Andrei Popovici
076: * @author Angela Nicoara
077: */
078: public class JoinPointManager extends JoinPointHook implements
079: JoinPointQuery {
080:
081: private static ProsePermission permission = new ProsePermission(
082: "registerListener");
083:
084: // mapping JoinPointRequest -> List(JoinPointListener)
085: protected final Map req2listener;
086:
087: // mapping JoinPointListener -> List(JoinPointRequest)
088: protected final Map listener2req;
089:
090: // List(ClassLoadListeners)
091: protected final Set classLoadListeners;
092:
093: // indicates if this JoinPointManager is connected to the Hook or if it is the test JPM
094: protected boolean isConnected;
095:
096: // indicates if the table listener2req is maintained for Reverse Mapping.
097: protected boolean enableRevMap;
098:
099: protected final HashSet enabledJoinPoints = new HashSet();
100:
101: private JVMAspectInterface aspectInterface = null;
102: private Vector loadedClasses;
103: private ClassLoadConsumer classLoaderNotifier;
104:
105: /**
106: * Create an <code>JoinPointManagerImpl</code> with no registered listeners
107: * or events.
108: */
109: public JoinPointManager(boolean isConnected, JVMAspectInterface ai,
110: boolean enableRevMap) {
111: req2listener = new HashMap();
112: listener2req = new HashMap();
113: classLoadListeners = new HashSet();
114: this .isConnected = isConnected;
115: aspectInterface = ai;
116: this .enableRevMap = enableRevMap;
117: loadedClasses = new Vector();
118:
119: if (isConnected)
120: connectToJVMAI();
121: }
122:
123: public static class ClassLoadConsumer extends Thread {
124: public boolean isRunning = true;
125: JoinPointManager jpm;
126:
127: public ClassLoadConsumer(Vector classVector, JoinPointManager j) {
128: jpm = j;
129: }
130:
131: {
132: Class c = NoClassDefFoundError.class;
133: }
134:
135: public void run() {
136: while (isRunning) {
137: if (!jpm.loadedClasses.isEmpty()) {
138: Class c = (Class) jpm.loadedClasses.get(0);
139: try {
140: c.getDeclaredMethods();
141: } catch (NoClassDefFoundError e) {
142: c = null;
143: }
144:
145: synchronized (jpm.loadedClasses) {
146: if (!jpm.loadedClasses.isEmpty())
147: jpm.loadedClasses.remove(0);
148:
149: }
150: if (c != null)
151: jpm.notifyClassLoadListeners(c);
152: } else {
153: synchronized (jpm.loadedClasses) {
154: try {
155: jpm.loadedClasses.wait();
156: } catch (java.lang.InterruptedException e) {
157: }
158: ;
159: }
160: }
161: }
162:
163: }
164: }
165:
166: public void connectToJVMAI() {
167: if (aspectInterface == null)
168: throw new RuntimeException(
169: "Cannot have a NULL aspect interface");
170: loadedClasses = new Vector();
171: classLoaderNotifier = new ClassLoadConsumer(loadedClasses, this );
172: classLoaderNotifier.start();
173: aspectInterface.setJoinPointHook(this );
174: }
175:
176: public void disconnectFromJVMAI() {
177: if (aspectInterface == null)
178: return;
179: if (isConnected) {
180: aspectInterface.setJoinPointHook(null);
181: classLoaderNotifier.isRunning = false;
182: synchronized (loadedClasses) {
183: loadedClasses.notifyAll();
184: }
185: }
186:
187: // this should be part of a teardown procedure
188: listener2req.clear();
189: req2listener.clear();
190: }
191:
192: public JVMAspectInterface getAspectInterface() {
193: return aspectInterface;
194: }
195:
196: public boolean isReverseMappingEnabled() {
197: return enableRevMap;
198: }
199:
200: public void onFieldAccess(FieldAccessJoinPoint joinPoint) {
201: List caughtExceptions = null;
202: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
203: for (int i = 0; i < listeners.nrOfListeners; i++) {
204: try {
205: listeners.listenerArray[i].joinPointReached(joinPoint);
206: } catch (Exception e) {
207: if (caughtExceptions == null)
208: caughtExceptions = new Vector();
209: caughtExceptions.add(handleRuntimeException(e));
210: }
211: }
212:
213: handleExceptions(caughtExceptions, joinPoint);
214: }
215:
216: public void onFieldModification(FieldModificationJoinPoint joinPoint) {
217: List caughtExceptions = null;
218: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
219: for (int i = 0; i < listeners.nrOfListeners; i++) {
220: try {
221: listeners.listenerArray[i].joinPointReached(joinPoint);
222: } catch (Exception e) {
223: if (caughtExceptions == null)
224: caughtExceptions = new Vector();
225: caughtExceptions.add(handleRuntimeException(e));
226: }
227: }
228:
229: handleExceptions(caughtExceptions, joinPoint);
230:
231: }
232:
233: public void onMethodEntry(MethodEntryJoinPoint joinPoint) {
234: List caughtExceptions = null;
235: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
236: for (int i = 0; i < listeners.nrOfListeners; i++) {
237: try {
238: listeners.listenerArray[i].joinPointReached(joinPoint);
239: } catch (Exception e) {
240: if (caughtExceptions == null)
241: caughtExceptions = new Vector();
242: caughtExceptions.add(handleRuntimeException(e));
243: }
244: }
245:
246: handleExceptions(caughtExceptions, joinPoint);
247: }
248:
249: /**
250: *
251: */
252: public void onMethodExit(MethodExitJoinPoint joinPoint) {
253: List caughtExceptions = null;
254: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
255: for (int i = 0; i < listeners.nrOfListeners; i++) {
256: try {
257: listeners.listenerArray[i].joinPointReached(joinPoint);
258: } catch (Exception e) {
259: if (caughtExceptions == null)
260: caughtExceptions = new Vector();
261: caughtExceptions.add(handleRuntimeException(e));
262: }
263: }
264:
265: handleExceptions(caughtExceptions, joinPoint);
266: }
267:
268: /**
269: * Hook method to be called whenever a registered constructor is invoked.
270: */
271: public void onConstructor(ConstructorJoinPoint joinPoint) {
272: List caughtExceptions = null;
273: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
274: for (int i = 0; i < listeners.nrOfListeners; i++) {
275: try {
276: listeners.listenerArray[i].joinPointReached(joinPoint);
277: } catch (Exception e) {
278: if (caughtExceptions == null)
279: caughtExceptions = new Vector();
280: caughtExceptions.add(handleRuntimeException(e));
281: }
282: }
283:
284: handleExceptions(caughtExceptions, joinPoint);
285: }
286:
287: /**
288: * Hook method to be called whenever an Exception event is reported from
289: * the jvmai-interface.
290: * For every listener registered on an exception throw event it invoces the
291: * corresponding <code>joinPointReached</code>-method.
292: */
293: public void onExceptionThrow(ExceptionJoinPoint joinPoint) {
294: //System.out.println("JoinPointManager -> onExceptionThrow");
295: List caughtExceptions = null;
296: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
297: //System.out.println("JoinPointManager onExceptionThrow -> listeners.nrOfListeners = " + listeners.nrOfListeners);
298: //System.out.println("JoinPointManager onExceptionThrow -> listeners.toString = " + listeners.toString());
299:
300: for (int i = 0; i < listeners.nrOfListeners; i++) {
301: try {
302: listeners.listenerArray[i].joinPointReached(joinPoint);
303: } catch (Exception e) {
304: if (caughtExceptions == null)
305: caughtExceptions = new Vector();
306: caughtExceptions.add(handleRuntimeException(e));
307: }
308: }
309:
310: handleExceptions(caughtExceptions, joinPoint);
311: }
312:
313: /**
314: * Hook method to be called whenever an Exception Catch event is reported from
315: * the jvmai-interface.
316: * For every listener registered on an exception catch event it invoces the
317: * corresponding <code>joinPointReached</code>-method.
318: */
319: public void onExceptionCatch(ExceptionCatchJoinPoint joinPoint) {
320: //System.out.println("JoinPointManager -> onExceptionCatch");
321: List caughtExceptions = null;
322: ListenerList listeners = (ListenerList) joinPoint.getAopTag();
323:
324: //System.out.println("JoinPointManager onExceptionCatch -> listeners.nrOfListeners = " + listeners.nrOfListeners);
325: //System.out.println("JoinPointManager onExceptionCatch -> listeners.toString = " + listeners.toString());
326:
327: for (int i = 0; i < listeners.nrOfListeners; i++) {
328: try {
329: listeners.listenerArray[i].joinPointReached(joinPoint);
330: } catch (Exception e) {
331: if (caughtExceptions == null)
332: caughtExceptions = new Vector();
333: caughtExceptions.add(handleRuntimeException(e));
334: }
335: }
336: handleExceptions(caughtExceptions, joinPoint);
337: }
338:
339: public void onClassLoad(Class cls) {
340: // Supress notification for classes which are already loaded.
341: // Bugfix for multiple remote insertion of the same aspect.
342: //
343: // Only required if aspects are inserted remotely
344: // TODO: disable this if property 'prose.port' is not set.
345: try {
346: // look if cls is already in BCEL repository
347: if (aspectInterface instanceof SunBCELRepositoryInterface
348: && ((SunBCELRepositoryInterface) aspectInterface)
349: .isClassLoaded(cls.getName())) {
350: return;
351: }
352: } catch (Exception e) {
353: System.err.println("###" + e);
354: e.printStackTrace();
355: }
356:
357: // BIG FIXME: this is because of an error with versions prior to
358: // 1.4!. In addition, at this time (for whatever reason)
359: // I cannot check whether cls is assignable from ..
360:
361: synchronized (loadedClasses) {
362: loadedClasses.add(cls);
363: loadedClasses.notifyAll();
364: }
365: }
366:
367: /** Register the listener <code>lsnr</code> for events
368: * requested by <code>jpr</code>. If the request <code>jpr</code>
369: * is the first of its kind, the join corresponding join point
370: * will be enabled. More precise, if no other request with an equal
371: * singature has been previously registered, the join point
372: * will be enabled.
373: *
374: * This method checks for the permission ProsePermission "registerListener" to be present.
375: */
376: public void registerListener(JoinPointListener list,
377: JoinPointRequest req) {
378: // security check
379: //AccessController.checkPermission(permission); // FIXME
380:
381: //System.out.println("JoinPointManager - JoinPointListener(list) = " + list);
382: //System.out.println("JoinPointManager - JoinPointRequest(req) = " + req);
383:
384: ListenerList listeners = null;
385: synchronized (req2listener) {
386: listeners = (ListenerList) req2listener.get(req);
387: if (listeners == null) {
388: listeners = new ListenerList();
389: req2listener.put(req, listeners);
390: }
391: if (isConnected)
392: req.enableJoinPoint(listeners);
393: }
394:
395: // note the trick: add adds the element at the end of the list.
396: // therefore, during notification, it will be notified last.
397: // therefore, the registration-notification ordering constraint
398: // holds..yeyeyeye
399: listeners.add(list);
400: if (enableRevMap) {
401: Set joinpoints = null;
402: synchronized (listener2req) {
403: joinpoints = (Set) listener2req.get(list);
404: if (joinpoints == null) {
405: joinpoints = new HashSet();
406: listener2req.put(list, joinpoints);
407: }
408: }
409: joinpoints.add(req);
410: }
411: }
412:
413: /** Deregister listener <code>lsnr</code> from this JoinPointManager.
414: * As a result of this action, the listener <code>lsnr</code> will
415: * cease being notified of any kind of events. Upon this action,
416: * any 'lonely event' -- one for whom no listener exists will be
417: * disabled. More precisely, if <code>lsnr</code> was the last listener
418: * litening on envents with the signature <em>S</em>,
419: * <em>S.disableJoinPoint</em> will be performed.
420: */
421: public void unregisterListener(JoinPointListener listener) {
422: //iterate through our vectors...
423:
424: try {
425: if (listener instanceof Insertable)
426: ((Insertable) listener).withdrawalAction(true);
427: } catch (Throwable e) {
428: // this must be ignored. A malicious crosscut may
429: // want to remain forever inserted. In fact,
430: // the unregistration should be robust.
431: e.printStackTrace();
432: }
433:
434: Collection toRemoveKey = new Vector();
435: synchronized (req2listener) {
436: Iterator i = req2listener.keySet().iterator();
437: while (i.hasNext()) {
438: JoinPointRequest crtRequest = (JoinPointRequest) i
439: .next();
440: ListenerList crtListenerList = (ListenerList) req2listener
441: .get(crtRequest);
442:
443: crtListenerList.remove(listener);
444: if (crtListenerList.contains(listener)) {
445: throw new Error(
446: "Vector.removeAll works improperly; please reimplement");
447: }
448: if (crtListenerList.isEmpty()) {
449: if (isConnected)
450: crtRequest.disableJoinPoint();
451: toRemoveKey.add(crtRequest);
452: }
453: }
454: Iterator oldKeys = toRemoveKey.iterator();
455: while (oldKeys.hasNext()) {
456: Object key = oldKeys.next();
457: req2listener.remove(key);
458: }
459:
460: }
461:
462: if (enableRevMap)
463: listener2req.remove(listener);
464:
465: try {
466: if (listener instanceof Insertable)
467: ((Insertable) listener).withdrawalAction(true);
468: } catch (Throwable e) {
469: // this must be ignored. A malicious crosscut may
470: // want to remain forever inserted. In fact,
471: // the unregistration should be robust.
472: e.printStackTrace();
473: }
474: }
475:
476: /** Return the state of the join-point manager. The registeresd listeners and
477: * the associated requests will be returned.
478: */
479: public String toString() {
480: String isConnectedString = "(isNotConnected)";
481: if (isConnected)
482: isConnectedString = "(isConnected)";
483: StringBuffer result = new StringBuffer();
484: result.append(" Join Point Manager ("
485: + System.identityHashCode(this ) + "State "
486: + isConnectedString + ": \n");
487: result.append(req2listener.toString());
488: return result.toString();
489: }
490:
491: /** This method should be called if a notification fails. If the notification
492: * fails with a Runtime exception, the default implementation of this
493: * method throws the corresponding run-time exception. Otherwise it
494: * returns the exception that caused the failure.
495: *
496: * @param e the exception to be handled
497: * @return a non-runtime exception thrown by the advice
498: */
499: protected Exception handleRuntimeException(Exception e) {
500: // the obvious case
501:
502: if (e != null && e instanceof RuntimeException) {
503: throw (RuntimeException) e;
504: }
505:
506: // invoked via reflection
507: if (e instanceof InvocationTargetException) {
508: InvocationTargetException invokedViaReflection = (InvocationTargetException) e;
509: if (invokedViaReflection.getTargetException() != null
510: && invokedViaReflection.getTargetException() instanceof RuntimeException)
511: throw (RuntimeException) (invokedViaReflection
512: .getTargetException());
513: else {
514: Exception realException = (Exception) invokedViaReflection
515: .getTargetException();
516: if (realException != null)
517: return realException;
518: }
519: }
520:
521: return e;
522: }
523:
524: /** This method should be called if the notification fails for some of the
525: * listeners. Subclasses are encouraged to override this method in order to
526: * implement their own exception handling policy, e.g., removing the <em>bad</em>
527: * listeners from this <code>JoinPointManager</code>.
528: *
529: * @param exceptionList a list of <code>Exception</code> objects, thrown during the notification
530: * of listeners of <code>crtEvent</code>.
531: * @param crtEvent a <code>JoinPointEvent</code> whose listeners were not properly
532: * notified.
533: */
534: protected void handleExceptions(List exceptionList,
535: JoinPoint crtEvent) {
536:
537: if (exceptionList != null) {
538: Iterator it = exceptionList.iterator();
539: while (it.hasNext()) {
540: Logger.error("Notification failed for " + crtEvent,
541: (Exception) it.next());
542: }
543: }
544: }
545:
546: /** Notify all registered class load listeners that the class
547: * <code>newClass</code> has just been loaded and prepared.
548: * This method should be invoked by implementations of this abstract
549: * immediately after a class of intereest (containing potential join-points)
550: * is loaded and prepared.
551: *
552: * @param newClass the class that is new to the system
553: */
554: protected void notifyClassLoadListeners(Class newClass) {
555: synchronized (classLoadListeners) {
556: Iterator i = classLoadListeners.iterator();
557: while (i.hasNext()) {
558: ClassLoadListener crtListener = (ClassLoadListener) i
559: .next();
560: crtListener.classLoaded(newClass);
561: }
562: }
563: }
564:
565: /** Register a class load listener event. All class load listeners
566: * will be notified every time a class of interest (containing potential join-points)
567: * has been loaded.
568: *
569: * @param updateGuy the listener of class load events
570: */
571: public void registerListener(ClassLoadListener updateGuy) {
572: classLoadListeners.add(updateGuy);
573: }
574:
575: /** Unregister a class load listener.
576: *
577: * @param updateGuy the listener to be removed from the listeners list.
578: */
579: public void unregisterListener(ClassLoadListener updateGuy) {
580: classLoadListeners.remove(updateGuy);
581: }
582:
583: /** Suspend notification of all listeners interested in join-points
584: * that occur in the specified thread. This method is idempotent.
585: * Successive calls to this method with the same argument have
586: * the same effect as calling it only once.
587: *
588: */
589: public void suspendListenerNotification(Thread t) {
590: // if (isConnected && aspectInterface != null)
591: aspectInterface.suspendNotification(t);
592: }
593:
594: /** Resume the notification of listerners interested in join-points
595: * that occur in the specified thread.
596: */
597: public void resumeListenerNotification(Thread t) {
598: // if (isConnected && aspectInterface != null)
599: aspectInterface.resumeNotification(t);
600: }
601:
602: /**
603: * Returns all currently loaded classes in the virtual machine.
604: */
605: public List getLoadedClasses() {
606: List result = aspectInterface.getLoadedClasses();
607: return result;
608: }
609:
610: public Set allJoinpoints() {
611: return req2listener.keySet();
612: }
613:
614: public Set getCrosscuts(JoinPointRequest jpr) {
615: Set result = new HashSet();
616: if (jpr == null)
617: return result;
618:
619: ListenerList listeners = (ListenerList) req2listener.get(jpr);
620: if (listeners == null)
621: return result;
622: else
623: for (int i = 0; i < listeners.nrOfListeners; i++)
624: result.add(listeners.listenerArray[i]);
625:
626: return result;
627: }
628:
629: public JoinPointRequest createJoinPointRequest(String kind, Object o) {
630: if (MethodEntryJoinPoint.KIND.equals(kind))
631: return new MethodEntryRequest((Method) o, this );
632: if (MethodExitJoinPoint.KIND.equals(kind))
633: return new MethodExitRequest((Method) o, this );
634: if (MethodRedefineJoinPoint.KIND.equals(kind))
635: return new MethodRedefineRequest((Method) o, this );
636: if (FieldAccessJoinPoint.KIND.equals(kind))
637: return new FieldAccessRequest((Field) o, this );
638: if (FieldModificationJoinPoint.KIND.equals(kind))
639: return new FieldModificationRequest((Field) o, this );
640: if (ExceptionJoinPoint.KIND.equals(kind))
641: return new ExceptionThrowRequest((Class) o, this );
642: if (ExceptionCatchJoinPoint.KIND.equals(kind))
643: return new ExceptionCatchRequest((Class) o, this );
644: if (ConstructorJoinPoint.KIND.equals(kind))
645: return new ConstructorRequest((Constructor) o, this );
646: throw new RuntimeException("unknown kind");
647: }
648:
649: /**
650: *
651: */
652: public Set getJoinpoints(Crosscut cc) {
653: if (cc == null)
654: return (Set) null;
655:
656: if (enableRevMap) {
657: Set result = (Set) listener2req.get(cc);
658: if (result == null)
659: return new HashSet();
660: else
661: return result;
662: } else {
663: return new HashSet(cc.createRequest());
664: }
665: }
666:
667: }
668:
669: //======================================================================
670: //
671: // $Log: JoinPointManager.java,v $
672: // Revision 1.4 2005/06/25 16:56:13 anicoara
673: // Added additional comments
674: //
675: // Revision 1.3 2004/05/12 09:41:55 anicoara
676: // Remove the README.RVM file
677: //
678: // Revision 1.2 2003/07/10 15:25:04 apopovic
679: // Bug fix when classes were loaded too early (and getDelclaredMethod) threw
680: // an error
681: //
682: // Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
683: // Imported from ETH Zurich
684: //
685: // Revision 1.5 2003/07/02 12:42:54 anicoara
686: // Added CatchJoinPoint Functionality (Requests, Join-Points, Filters, CatchCuts, Tests)
687: //
688: // Revision 1.4 2003/06/26 09:31:03 popovici
689: // Bugfix: the asyncrhroous loadClassNotification used to load a class while notifying; result: deadlock; fixed
690: //
691: // Revision 1.3 2003/06/25 09:04:11 popovici
692: // Bug fix in synchronizing class producers and consumers; FIXME comment added to AbstractCrosscut
693: //
694: // Revision 1.2 2003/06/23 14:01:21 popovici
695: // Asynchronous aspect insertion on dynamically loaded classes
696: //
697: // Revision 1.1 2003/05/05 13:58:24 popovici
698: // renaming from runes to prose
699: //
700: // Revision 1.21 2003/04/26 18:51:37 popovici
701: // 1 Bug fix which lead to a refactoring step:
702: // 1. the bug: 'JoinPointRequests' used to write to a static list, which survived a startup/teardown;
703: // now this list belongs to the JoinPointManager;
704: // 2. the refactoring: the JoinPointManager now creates (and shares state) with join-points.
705: //
706: // Revision 1.20 2003/04/17 15:15:15 popovici
707: // Extension->Aspect renaming
708: //
709: // Revision 1.19 2003/04/17 12:49:27 popovici
710: // Refactoring of the crosscut package
711: // ExceptionCut renamed to ThrowCut
712: // McutSignature is now SignaturePattern
713: //
714: // Revision 1.18 2003/04/17 08:47:58 popovici
715: // Important functionality additions
716: // - Cflow specializers
717: // - Restructuring of the MethodCut, SetCut, ThrowCut, and GetCut (they are much smaller)
718: // - Transactional capabilities
719: // - Total refactoring of Specializer evaluation, which permits fine-grained distinction
720: // between static and dynamic specializers.
721: // - Functionality pulled up in abstract classes
722: // - Uniformization of advice methods patterns and names
723: //
724: // Revision 1.17 2003/03/04 18:36:05 popovici
725: // Organization of imprts
726: //
727: // Revision 1.16 2003/03/04 11:27:31 popovici
728: // Important refactorization step (march):
729: // - removal of 'JoinPointEvents'; JoinPoints now have the same function as events
730: // - reimplementation of the JVMAIDebuggerAspectInterface (better performance, coding conventions, removal of ProseVM
731: // structures
732: //
733: // Revision 1.15 2003/02/11 14:23:26 popovici
734: // Bug fix: 'insertion' action was performed in the JoinPointManger. This lead
735: //
736: // Revision 1.14 2002/11/26 17:15:17 pschoch
737: // RootComponent now added (replaces RootComponent now added (replaces old ProseSystem)
738: // ProseSystem now owns and starts the Aspect interface.
739: // ProseSystem now containes a 'test' AspectManager
740: // AspectManager now owns the JoinPointManager.
741: // ExtensionManger can be 'connected' to the JVM, or disconnected. The
742: // JoinPointManager of a connected Ext.Mgr enables joinpoints; the
743: // JoinPointManger of a disconnected Ext.Mgr never enables join-points
744: // Documentation updated accordingly.
745: //
746: // Revision 1.13 2002/10/31 18:26:54 pschoch
747: // Capability of crosscutting Exceptions added to prose.
748: //
749: // Revision 1.12 2002/10/25 07:42:38 popovici
750: // Undo Chnages Phillippe
751: //
752: // Revision 1.10 2002/10/17 17:05:54 pschoch
753: // Added throw capabability to JVMAI
754: //
755: // Revision 1.9 2002/10/17 12:23:44 pschoch
756: // Added throw capabability to JVMAI
757: //
758: // Revision 1.8 2002/09/21 14:04:34 popovici
759: // Bug 0000010 fixed. Added 'teardown' procedure
760: // in the JVMAI, Jikes & JDK prose implementation
761: //
762: // Revision 1.7 2002/05/28 15:50:10 popovici
763: // printStackTrace eliminated from the JoinPointManger. Used to give the impresion that
764: // run-time exceptions are true errors
765: //
766: // Revision 1.6 2002/03/28 13:48:49 popovici
767: // Mozilla-ified
768: //
769: // Revision 1.5 2002/03/27 13:56:38 popovici
770: // Legal and realease changes:
771: // added LEGAL & licenses
772: // added profiles/release
773: // added programs/* scripts for installation
774: // modified project/* files for installation
775: //
776: // Revision 1.4 2002/03/11 11:01:32 smarkwal
777: // JVMInfoInterface and JoinPointHook changed to abstract classes
778: //
779: // Revision 1.3 2002/02/21 12:51:43 popovici
780: // Dispatching efficiency issues:
781: // - Hook methods in the join point manager are now inlined (they
782: // do not use any more 'notifyListeners'
783: // - Aop tags are now of type 'ListenerList' which allows efficient
784: // array iteration
785: // - 'setWatch' methods modifiy to accomodate ListenerLists on EventRequests
786: //
787: // Revision 1.2 2002/02/05 10:01:02 smarkwal
788: // JVMDI-specific code replaced by JVMAI. Prose-implementation classes and reflection package removed.
789: //
790: // Revision 1.2 2001/12/07 17:13:02 popovici
791: // attach to local VM did not start jpm. Fixed
792: //
793: // Revision 1.1.1.1 2001/11/29 18:13:13 popovici
794: // Sources from runes
795: //
796: // Revision 1.1.2.11 2001/11/21 11:56:22 popovici
797: //
798: // -The sun.tools.agent and ch.ethz.inf.util.JVMDIUtil functionality
799: // replaced with the iks.jvmdi package. References to this old
800: // functionality replaced throughout the code.
801: // -Partial reimplementation of the ch.ethz.inf.iks.runes classes,
802: // part of their functionality moved to the ch.ethz.prose.reflect
803: // abstract classes. New classes and functionality added to the
804: // ch.ethz.prose.reflect package, partially to reflect the
805: // more stable features taken from the iks.runes packages, partially
806: // to reflect the structure of the VM (constant pool, etc). Functionality in
807: // ch.ethz.prose.crosscut and the junit classes adapted to use the
808: // new form of the ch.ethz.prose.reflect package
809: //
810: // Revision 1.1.2.10 2001/06/05 13:50:35 popovici
811: // method 'post' modified to consider class load events as well.
812: //
813: // Revision 1.1.2.9 2001/03/28 09:20:30 popovici
814: // Methods 'suspendListenerNotification' and 'resumeListenerNotification'
815: // implemented (body used to be commented because of bug in Agent.addSystemThread)
816: //
817: // Revision 1.1.2.8 2001/03/19 10:24:17 popovici
818: // Methods 'suspendListenerNotification' and 'resumeListenerNotification'
819: // implemented (empty body). FIXME: bug in 'Agent.addSystemThread'
820: //
821: // Revision 1.1.2.7 2000/12/01 13:52:47 groos
822: // Upon notification of an unknown event, a java.lang.InternalError is thrown.
823: //
824: // Revision 1.1.2.6 2000/11/21 14:32:10 groos
825: // added support for FieldAccessRequests and FieldModificationRequests:
826: // implements EventTypes,
827: // dispatches Event.FIELD_ACCESS and Event.FIELD_MODIFICATION,
828: // provides createFieldAccessRequest(Field f) and
829: // createFieldModificationRequest(Field f)
830: //
831: // Revision 1.1.2.5 2000/10/30 15:56:42 popovici
832: // Methods 'notifyListeners' 'registerListener' 'unregisterListener' 'hanldeExceptions' moved to AbstractJoinPointManger. Class now extends
833: // EventDispatcher for visibility reasons.
834: //
835: // Revision 1.1.2.4 2000/10/25 09:04:51 popovici
836: // Exception Handler added. Method 'toString' added.
837: //
838: // Revision 1.1.2.3 2000/10/24 17:56:52 popovici
839: // Proprietary event dispatcher specified. Additional method 'attachToLocalVM'
840: // boots the agent and does the setup.
841: //
842: // Revision 1.1.2.2 2000/10/23 19:05:09 popovici
843: // import declaration changed according to refactorization DEVEL_WS0001; some
844: // documentation added.
845: //
846: // Revision 1.1.2.1 2000/10/16 13:04:39 popovici
847: // Initial revision
848: //
|