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: ProseSystem.java,v 1.2 2003/08/26 19:50:30 anicoara Exp $
022: // =====================================================================
023: //
024: // (history at end)
025: //
026:
027: package ch.ethz.prose;
028:
029: // used packages
030: import java.lang.reflect.Constructor;
031: import java.security.AccessControlException;
032: import java.security.AccessController;
033: import java.security.PrivilegedActionException;
034: import java.security.PrivilegedExceptionAction;
035: import java.util.StringTokenizer;
036:
037: import ch.ethz.jvmai.JVMAspectInterface;
038: import ch.ethz.inf.util.Logger;
039:
040: /**
041: * Class ProseSystem represents the user view of the system.
042: * It allows to start and stop prose, and to get access
043: * to an code <code>AspectManager</code>Users
044: * program aspects and they will insert them into the system
045: * using the <code>insertExtension</code> and <code>withdrawExtension</code>
046: * methods of the extension manager.
047: * <p>
048: * This class is also used for bootstrapping the system. Before using
049: * the extension system, users of this class (eventually applications)
050: * will have to call
051: * <blockquote><pre>
052: * ProseSystem.startup();
053: * Another way to start this system happens over the <code>RootComponent<code/>
054: * module.
055: * </pre></blockquote>
056: * this will setup the system, according to special system properties too,
057: * like
058: * <ul>
059: * <li> <code>ch.ethz.prose.EXManager</code>
060: * </ul>
061: * <P>
062: * Known Properties:
063: * <UL>
064: * <LI><CODE>ch.ethz.prose.JVMAIProvider</CODE> <b>Values:class names</b> <br>
065: * <b>Usage:</b> controlls the creation of the JVMAI</LI>
066: * <LI><CODE>ch.ethz.prose.EXManager</CODE> <B>Values:class name</B> <BR>
067: * <B>Usage:</B> controlls the creation of the extension manager (<CODE>AspectManager</CODE>)</LI>
068: * <LI><CODE>ch.ethz.prose.HotSwapClassWeaver</CODE> <B>Values: class Name</B> <BR>
069: * <B>Usage:</B> controlls which class weaver implementation should be used
070: * (only for HotSwap <CODE>JVMAIProvider</CODE> and <CODE>EXManager</CODE>)</LI>
071: * <LI><CODE>ch.ethz.prose.JVMAIPackagePrefixes</CODE> <b>Values: package prefixes</b> <br>
072: * <b>Usage:</b> controlls the package prefixes eliminated or used by jvmai</LI>
073: * <LI><CODE>ch.ethz.prose.JVMAIOpenWorldAssumption</CODE> <b>Values:true or false</b> <br>
074: * <b>Usage:</b> controlls whether prose uses an open world (excludes package prefixes) or
075: * a closed world (includes package prefixes)</LI>
076: * <LI><CODE>prose.port</CODE> <B>Values: port number (integer with value from 1 to 65535)</B> <BR>
077: * <B>Usage:</B> enables prose clients to connect to specified port</LI>
078: * </UL>
079: *
080: *
081: * @version $Revision: 1.2 $
082: * @author Andrei Popovici
083: * @author Angela Nicoara
084: */
085: public class ProseSystem implements Component {
086:
087: static private AspectManager currentExtM = null;
088: static private AspectManager testExtM = null;
089: static private JVMAspectInterface aspectInterface = null;
090: static boolean systemUp = false;
091: static ProsePermission permission = new ProsePermission(
092: "startupExtensionSystem");
093:
094: // caching Variables as input to function <JoinPointManager>.connectToJVMAI
095: static ch.ethz.jvmai.Provider provider = null;
096: static String[] packagePrefixes = null;
097: static boolean openWorldAssumption;
098:
099: /** Start up application-specific functionality.
100: * This method should be called before using the extension system.
101:
102: * <p><em>Note:this method is idempotent. Succesive, successful calls to
103: * <code>startup</code> have the same effect as a single call.
104: * Use <code>teardown</code> in between to actualy re-do the startup. NOT YET IMPLEMENTED.</em><p>
105: *
106: * Note: in case that the ProsePermission "startupExtensionSystem" is granted to the
107: * caller, this method is executed as privileged only restricted
108: * by the permissions not granted to RUNES classes
109: *
110: * @exception SystemStartupException one of the specified properties did
111: * not comply to the startup/teardown naming convention or one of the
112: * startup methods of additional systems failed.
113: *
114: */
115: public synchronized static void startup()
116: throws SystemStartupException {
117: if (systemUp)
118: return;
119:
120: // ATENTION!
121: // Because the JVM 1.4.1 blocks, we run "RemoteProseComponent" before "ProseSystem".
122: if (!System.getProperty("prose.port", "UNKNOWN").equals(
123: "UNKNOWN"))
124: ch.ethz.prose.tools.RemoteProseComponent.startup();
125: try {
126: Thread.sleep(500);
127: } catch (InterruptedException e) {
128: }
129:
130: try {
131: // security check
132: //AccessController.checkPermission(permission); // FIXME : uncomment this line.
133:
134: // if no exception occurred, we can perform the startup under priv. rights
135: AccessController
136: .doPrivileged(new PrivilegedExceptionAction() {
137: public Object run()
138: throws SystemStartupException {
139: doStartup();
140: return null;
141: }
142: });
143:
144: } catch (AccessControlException e) {
145: // we start the system in the standard way
146: doStartup();
147:
148: } catch (PrivilegedActionException e) {
149: e.printStackTrace();
150: throw new SystemStartupException(e.toString());
151: }
152:
153: /* ATENTION!
154: * Because the JVM 1.4.1 blocks, we run "RemoteProseComponent" before "ProseSystem".
155: if (!System.getProperty("prose.port","UNKNOWN").equals("UNKNOWN"))
156: ch.ethz.prose.tools.RemoteProseComponent.startup();
157: */
158:
159: systemUp = true;
160: }
161:
162: /**
163: * the real startup method
164: */
165: private synchronized static void doStartup()
166: throws SystemStartupException {
167:
168: try {
169:
170: // get the jvmai-provider
171: String providerClassName = System
172: .getProperty("ch.ethz.prose.JVMAIProvider");
173: if (providerClassName == null)
174: providerClassName = "ch.ethz.inf.iks.jvmai.jvmdi.DebuggerProvider";
175:
176: Class providerClass = Class.forName(providerClassName);
177: provider = (ch.ethz.jvmai.Provider) providerClass
178: .newInstance();
179:
180: packagePrefixes = new String[0];
181: openWorldAssumption = true;
182:
183: String packageList = System
184: .getProperty("ch.ethz.prose.JVMAIPackagePrefixes");
185: String openWorldParam = System
186: .getProperty("ch.ethz.prose.JVMAIOpenWorldAssumption");
187:
188: if (packageList == null && openWorldParam == null) {
189: packagePrefixes = new String[] { "ch.ethz.prose." };
190: openWorldAssumption = true;
191: } else {
192: if (packageList == null) {
193: packagePrefixes = new String[0];
194: } else {
195: StringTokenizer tokenizer = new StringTokenizer(
196: packageList, ",");
197: packagePrefixes = new String[tokenizer
198: .countTokens()];
199: for (int p = 0; p < packagePrefixes.length; p++) {
200: packagePrefixes[p] = tokenizer.nextToken();
201: }
202: }
203: if (openWorldParam == null) {
204: openWorldAssumption = true;
205: } else {
206: openWorldAssumption = openWorldParam.toUpperCase()
207: .equals("TRUE");
208: }
209:
210: }
211: // initialize the aspect interface and the info interface
212: aspectInterface = provider.getAspectInterface();
213:
214: // start the aspect interface!
215: aspectInterface.startup(packagePrefixes,
216: openWorldAssumption);
217:
218: aspectInterface.suspendNotification(Thread.currentThread());
219:
220: // set the default extension manager
221: String extMName = System
222: .getProperty("ch.ethz.prose.EXManager");
223: if (extMName != null) {
224: Class[] paramTypes = new Class[] { boolean.class,
225: JVMAspectInterface.class };
226: Object[] params = new Object[] { Boolean.TRUE,
227: aspectInterface };
228: Class extMClass = Class.forName(extMName);
229: Constructor extMConstructor = extMClass
230: .getConstructor(paramTypes);
231: currentExtM = (AspectManager) extMConstructor
232: .newInstance(params);
233: params[0] = Boolean.FALSE;
234: testExtM = (AspectManager) extMConstructor
235: .newInstance(params);
236: } else {
237: currentExtM = new LocalAspectManager(true,
238: aspectInterface);
239: testExtM = new LocalAspectManager(false,
240: aspectInterface);
241: }
242: currentExtM.startup();
243: testExtM.startup();
244:
245: systemUp = true;
246: } catch (Throwable e) {
247: e.printStackTrace();
248: if (currentExtM != null) {
249: currentExtM.teardown();
250: currentExtM = null;
251: }
252:
253: if (testExtM != null) {
254: currentExtM.teardown();
255: testExtM = null;
256: }
257: if (aspectInterface != null)
258: aspectInterface.teardown();
259: aspectInterface = null;
260:
261: if (e instanceof SystemStartupException)
262: throw (SystemStartupException) e;
263:
264: throw new SystemStartupException(e.toString());
265: } finally {
266: // start doing aspects
267: if (aspectInterface != null)
268: aspectInterface.resumeNotification(Thread
269: .currentThread());
270: }
271: Logger.message("ProseComponent.startup: succeeded! ");
272: }
273:
274: /** Tear down prose funtionality. Withdraw all existing aspects and remove the
275: * current AspectManager and JoinPointManager.
276: *
277: * <p><em>Note:this method is idempotent. Succesive, successful calls to
278: * <code>teardown</code> have the same effect as a single call.
279: * </em>.
280: *
281: * @exception SystemTeardownException if the teardown fails
282: */
283: public static void teardown() throws SystemTeardownException {
284: if (!systemUp)
285: return;
286: if (getAspectManager() != null) {
287: currentExtM.teardown();
288: currentExtM = null;
289: }
290:
291: if (getTestAspectManager() != null) {
292: testExtM.teardown();
293: testExtM = null;
294: }
295:
296: if (aspectInterface != null)
297: aspectInterface.teardown();
298:
299: aspectInterface = null;
300:
301: systemUp = false;
302: }
303:
304: /**
305: * Returns <code>true</code> if the local AspectManager
306: * is set up and running.
307: */
308: public static boolean isActive() {
309:
310: return systemUp;
311: }
312:
313: /**
314: * Return the aspect manager currently in use.
315: */
316: public static AspectManager getAspectManager() {
317: try {
318: startup();
319: } catch (Exception e) {
320: }
321: return currentExtM;
322: }
323:
324: /**
325: * Return the currently used extension manager for testing aspects. This
326: * extension manager is not attached to the JVMAI System.
327: */
328: public static AspectManager getTestAspectManager() {
329: try {
330: startup();
331: } catch (Exception e) {
332: }
333: return testExtM;
334: }
335: }
336:
337: //======================================================================
338: //
339: // $Log: ProseSystem.java,v $
340: // Revision 1.2 2003/08/26 19:50:30 anicoara
341: // Bug fix: JVM1.4.1 blocks (RemoteProseComponent should run before ProseSystem)
342: //
343: // Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
344: // Imported from ETH Zurich
345: //
346: // Revision 1.4 2003/06/10 12:59:47 popovici
347: // startup and teardown idempotence used to produce a startup during the teardown;
348: // flag is now set *after* the teardown has successfully completed
349: //
350: // Revision 1.3 2003/05/26 17:49:44 popovici
351: // changes in the portnames; idempotent methods better implemented. ProseSystem now depends on the remote prose
352: //
353: // Revision 1.2 2003/05/26 13:28:50 popovici
354: // Documentation Improvements
355: //
356: // Revision 1.1 2003/05/05 13:58:32 popovici
357: // renaming from runes to prose
358: //
359: // Revision 1.1 2003/04/17 15:15:05 popovici
360: // Extension->Aspect renaming
361: //
362: // Revision 1.16 2003/04/17 12:49:40 popovici
363: // Refactoring of the crosscut package
364: // ExceptionCut renamed to ThrowCut
365: // McutSignature is now SignaturePattern
366: //
367: // Revision 1.15 2003/04/17 08:47:13 popovici
368: // Important functionality additions
369: // - Cflow specializers
370: // - Restructuring of the MethodCut, SetCut, ThrowCut, and GetCut (they are much smaller)
371: // - Transactional capabilities
372: // - Total refactoring of Specializer evaluation, which permits fine-grained distinction
373: // between static and dynamic specializers.
374: // - Functionality pulled up in abstract classes
375: // - Uniformization of advice methods patterns and names
376: //
377: // Revision 1.14 2003/03/05 16:24:19 popovici
378: // Added the jvmai properties for prose startup
379: //
380: // Revision 1.13 2003/03/04 18:36:36 popovici
381: // Organization of imprts
382: //
383: // Revision 1.12 2003/03/04 11:27:14 popovici
384: // Important refactorization step (march):
385: // - removal of 'JoinPointEvents'; JoinPoints now have the same function as events
386: // - reimplementation of the JVMAIDebuggerAspectInterface (better performance, coding conventions, removal of ProseVM
387: // structures
388: //
389: // Revision 1.11 2003/01/27 13:01:19 pschoch
390: // Now implements Interface Component
391: //
392: // Revision 1.10 2002/11/27 17:11:01 popovici
393: // the DebuggerProvider is now the default provider of the extension
394: // system.
395: //
396: // Revision 1.9 2002/11/26 17:14:31 pschoch
397: // RootComponent now added (replaces RootComponent now added (replaces old ProseSystem)
398: // ProseSystem now owns and starts the Aspect interface.
399: // ProseSystem now containes a 'test' AspectManager
400: // AspectManager now owns the JoinPointManager.
401: // ExtensionManger can be 'connected' to the JVM, or disconnected. The
402: // JoinPointManager of a connected Ext.Mgr enables joinpoints; the
403: // JoinPointManger of a disconnected Ext.Mgr never enables join-points
404: // Documentation updated accordingly.
405: //
406: // Revision 1.8 2002/10/31 16:47:13 pschoch
407: // Method setJoinPointManager fixed
408: //
409: // Revision 1.7 2002/10/25 07:42:32 popovici
410: // Undo Chnages Phillippe
411: //
412: // Revision 1.5 2002/03/28 13:48:34 popovici
413: // Mozilla-ified
414: //
415: // Revision 1.4 2002/02/18 14:40:36 popovici
416: // Bug fix in ProseSystem; notification is now suspended during ProseSystem.startup
417: //
418: // Revision 1.3 2002/02/13 16:08:01 smarkwal
419: // does not rely anymore on Provider.getProvider()
420: //
421: // Revision 1.2 2002/02/05 10:17:32 smarkwal
422: // JVMDI-specific code replaced by JVMAI. Implementation-classes and reflection-package removed.
423: //
424: // Revision 1.1.1.1 2001/11/29 18:13:15 popovici
425: // Sources from runes
426: //
427: // Revision 1.1.2.15 2001/06/15 08:06:50 popovici
428: // Property tags added for the ExtnsionSystem class
429: //
430: // Revision 1.1.2.14 2001/04/27 07:31:57 popovici
431: // Documentation fix (minor).
432: //
433: // Revision 1.1.2.13 2001/04/13 09:12:08 mrmuller
434: // system now flaged as running as soon as the local extension manager is working
435: //
436: // Revision 1.1.2.12 2001/03/26 15:04:06 mrmuller
437: // improved exception handling
438: //
439: // Revision 1.1.2.11 2001/03/22 17:10:28 mrmuller
440: // replaced PrivilegedAction with PrivilegedExceptionAction
441: //
442: // Revision 1.1.2.10 2001/03/16 13:14:18 mrmuller
443: // added isActive() method. startup now runs privileged if caller was granted ProsePermission "startupExtensionSystem"
444: //
445: // Revision 1.1.2.9 2001/02/28 13:46:37 popovici
446: // More explicit exception handling in the case of target extensions for
447: // startup and teardown
448: //
449: // Revision 1.1.2.8 2001/02/23 16:29:53 mrmuller
450: // Added logging output
451: //
452: // Revision 1.1.2.7 2001/02/22 16:18:49 popovici
453: // method 'setup' removed.
454: // - method 'withdrawAll' made more robust for the case no extension manager is set
455: // - methods 'teardown' and 'startup' enhanced with the idempotent functionality
456: //
457: // Revision 1.1.2.6 2001/02/20 09:29:02 popovici
458: // Withdrawal of extensions and removal of managers in teardown.
459: //
460: // Revision 1.1.2.5 2001/02/07 14:09:39 popovici
461: // - Idempotence Functionality added but commented out, since junit tests do not support it yetExtensionSystem.java
462: // - Documentation for startup/teardown updated
463: //
464: // Revision 1.1.2.4 2001/02/07 11:51:07 popovici
465: // - AspectManager functionality moved to 'LocalAspectManager'
466: // - methods 'startup' and 'teardown' and the startup/teardown framework
467: // added.
468: // - method 'applicationSetup' removed.
469: //
470: // Revision 1.1.2.3 2001/01/23 09:28:52 popovici
471: // extensions() changed to comply to new ExtensionManger Interface
472: //
473: // Revision 1.1.2.2 2000/10/27 08:41:35 groos
474: // - misc doc typo corrections
475: // - suggestion of how to format code
476: // (no code change, just reformatting)
477: //
478: // Revision 1.1.2.1 2000/10/24 17:48:01 popovici
479: // Initial Revision
480: //
|