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: RootComponent.java,v 1.1.1.1 2003/07/02 15:30:51 apopovic Exp $
022: // =====================================================================
023: //
024: // (history at end)
025: //
026:
027: package ch.ethz.prose;
028:
029: // used packages
030: import java.lang.reflect.InvocationTargetException;
031: import java.lang.reflect.Method;
032: import java.lang.reflect.Modifier;
033: import java.util.Arrays;
034: import java.util.Enumeration;
035: import java.util.Iterator;
036: import java.util.List;
037: import java.util.Set;
038: import java.util.TreeSet;
039: import java.util.Vector;
040:
041: /**
042: * Class RootComponent looks for properties called
043: * "ch.ethz.prose.ESSystem.X", where X is 0,1,2,..; If this
044: * property is defined and represents a class name which
045: * has two static methods with no parameters called <code>startup</code>
046: * and <code>teardown</code> then the <code>startup</code> method is
047: * called for this class. These methods should only throw
048: * <code>SystemStartupException</code> or
049: * <code>SystemTeardownException</code> respectively.
050: * The class specified in the property has to implement the interface
051: * <code>Component</code>.
052: * <P>
053: * Used Properties:
054: * <UL>
055: * <LI><CODE>ch.ethz.prose.ESSystem.X</CODE>
056: * <b>Values:</b> A class name containing static startup and teardown methods.
057: * Current possible values:
058: * <ul>
059: * <li> <code>ch.ethz.prose.ExtensionViewerSystem</code>
060: * <li> <code>ch.ethz.prose.dist.JiniExtensionSystem</code>
061: * <li> <code>ch.ethz.prose.dist.RemoteExtensionSystem</code>
062: * </ul>
063: * <br>
064: * <b>Usage:</b> controls aditional services to be started up together
065: * with the <code>ProseSystem</code> itself. Note that <em>X</em> is
066: * a placeholder for 1,2,3,..</LI>
067: * </UL>
068: *
069: * @version $Revision: 1.1.1.1 $
070: * @author Philippe Schoch
071: */
072: public class RootComponent implements Component {
073:
074: static List startupMethods = null;
075: static List teardownMethods = null;
076: public static boolean reverseOrder = false;
077:
078: static boolean isStarted = false;
079:
080: protected RootComponent() {
081: }
082:
083: /**
084: * Search the property set for properies named
085: * <code>ch.ethz.prose.ESSystem.X</code>, where X may be
086: * 0, 1, 2, ..etc.
087: * If the values of the properties denote classnames and
088: * each of the classNames has a method called <code>startup</code> throwing
089: * a <code>ExtensionSystemStartupException</code> and a method called <code>teardown</code>
090: * throwing a <code>ExtensionSystemTeardownException</code> then this <code>startup</code>
091: * method is executed.
092: */
093: public static synchronized void startup()
094: throws SystemStartupException {
095: if (isStarted)
096: return;
097: isStarted = true;
098:
099: startupMethods = new Vector();
100: teardownMethods = new Vector();
101:
102: // initialize the startup/teardown methods of all components
103: initStartupTeardownMethods();
104:
105: // call inital startup functionality of all components
106: doStartup();
107: }
108:
109: /**
110: * Call every <code>teardown</code> method one by one of every started <code>Component</code>
111: * in the order they are started.
112: * If <code>teardown</code> methods should be called in the reverse order as the <code>startup</code> calls
113: * simply set the flag <code>reverseOrder</code> to <code>true</code>. By default this flag is set to
114: * <code>false<code/>.
115: */
116: public synchronized static void teardown()
117: throws SystemTeardownException {
118: if (!isStarted)
119: return;
120: isStarted = false;
121: if (reverseOrder) {
122: synchronized (teardownMethods) {
123: List temp = new Vector();
124: while (!(teardownMethods.isEmpty())) {
125: temp.add(0, ((Vector) teardownMethods)
126: .firstElement());
127: teardownMethods.remove(0);
128: }
129: teardownMethods = temp;
130: }
131: }
132:
133: // call inital teardown functionality of all components
134: doTeardown();
135: }
136:
137: private static void initStartupTeardownMethods()
138: throws SystemStartupException {
139: Set propNames = new TreeSet();
140: List clsNames = new Vector();
141: Enumeration keys = System.getProperties().keys();
142: String propPrefix = "ch.ethz.prose.ESSystem.";
143:
144: // retrieve the matching property names
145: while (keys.hasMoreElements()) {
146: String crtPropName = (String) keys.nextElement();
147: if (crtPropName.startsWith(propPrefix)
148: && crtPropName.length() > propPrefix.length())
149: propNames.add(crtPropName);
150: }
151:
152: Iterator j = propNames.iterator();
153: while (j.hasNext())
154: clsNames.add(System.getProperty((String) j.next()));
155:
156: // retrieve the matching classNames
157: Iterator i = clsNames.iterator();
158: while (i.hasNext()) {
159: String crtClsName = null;
160: Method startupMethod = null;
161: Method teardownMethod = null;
162: try {
163: crtClsName = (String) i.next();
164: Class sysClass = Class.forName(crtClsName);
165: startupMethod = sysClass.getMethod("startup",
166: new Class[] {});
167: teardownMethod = sysClass.getMethod("teardown",
168: new Class[] {});
169:
170: if (((startupMethod.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
171: || ((teardownMethod.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
172: || (!Arrays.asList(
173: startupMethod.getExceptionTypes())
174: .contains(SystemStartupException.class))
175: || (!Arrays
176: .asList(
177: teardownMethod
178: .getExceptionTypes())
179: .contains(SystemTeardownException.class)))
180: throw new SystemStartupException(
181: "methods startup/teardown are non-static or don't have"
182: + " compatible throws clauses");
183: } catch (ClassNotFoundException noSuchClass) {
184: throw new SystemStartupException("Startup class "
185: + crtClsName + " not found");
186: } catch (NoSuchMethodException noSuchMethod) {
187: throw new SystemStartupException(
188: "startup and teardown methods not present in class "
189: + crtClsName);
190: }
191:
192: startupMethods.add(startupMethod);
193: teardownMethods.add(teardownMethod);
194: }
195:
196: // Collections.reverse(teardownMethods);
197: }
198:
199: private static void doStartup() throws SystemStartupException {
200: Iterator i = null;
201:
202: i = startupMethods.iterator();
203:
204: try {
205: while (i.hasNext()) {
206: Method crtMeth = (Method) i.next();
207: crtMeth.invoke(null, new Object[] {});
208: }
209: } catch (IllegalAccessException notPublic) {
210: notPublic.printStackTrace();
211: throw new SystemStartupException(
212: "Cannot access startup method");
213: } catch (InvocationTargetException realException) {
214: realException.printStackTrace();
215: throw (SystemStartupException) realException
216: .getTargetException();
217: }
218: }
219:
220: private static void doTeardown() throws SystemTeardownException {
221: Iterator i = null;
222:
223: i = teardownMethods.iterator();
224:
225: try {
226: while (i.hasNext()) {
227: Method crtMeth = (Method) i.next();
228: crtMeth.invoke(null, new Object[] {});
229: }
230: } catch (IllegalAccessException notPublic) {
231: throw new SystemTeardownException(
232: "Cannot access teardown method");
233: } catch (InvocationTargetException realException) {
234: throw (SystemTeardownException) realException
235: .getTargetException();
236: }
237: }
238:
239: }
240:
241: //======================================================================
242: //
243: // $Log: RootComponent.java,v $
244: // Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
245: // Imported from ETH Zurich
246: //
247: // Revision 1.3 2003/05/26 17:49:44 popovici
248: // changes in the portnames; idempotent methods better implemented. ProseSystem now depends on the remote prose
249: //
250: // Revision 1.2 2003/05/06 15:51:27 popovici
251: // Mozilla-ification
252: //
253: // Revision 1.1 2003/05/05 13:58:31 popovici
254: // renaming from runes to prose
255: //
256: // Revision 1.6 2003/04/17 15:15:13 popovici
257: // Extension->Aspect renaming
258: //
259: // Revision 1.5 2003/03/04 18:36:38 popovici
260: // Organization of imprts
261: //
262: // Revision 1.4 2003/03/04 11:27:15 popovici
263: // Important refactorization step (march):
264: // - removal of 'JoinPointEvents'; JoinPoints now have the same function as events
265: // - reimplementation of the JVMAIDebuggerAspectInterface (better performance, coding conventions, removal of ProseVM
266: // structures
267: //
268: // Revision 1.3 2003/01/17 21:09:46 pschoch
269: // Bug fix: in RootComponent new variable propNames for sorting PropertyNames; variable clsNames changed to Vector
270: //
271: // Revision 1.2 2003/01/17 12:14:42 pschoch
272: // Bug fixes
273: // Unused variable 'clsObjects' deleted
274: // Variable 'clsNames' changed from 'HashSet' to 'TreeSet' to enforce
275: // property reading in the correct order
276: //
277: // Revision 1.1 2002/11/26 17:14:32 pschoch
278: // RootComponent now added (replaces RootComponent now added (replaces old ProseSystem)
279: // ProseSystem now owns and starts the Aspect interface.
280: // ProseSystem now containes a 'test' AspectManager
281: // AspectManager now owns the JoinPointManager.
282: // ExtensionManger can be 'connected' to the JVM, or disconnected. The
283: // JoinPointManager of a connected Ext.Mgr enables joinpoints; the
284: // JoinPointManger of a disconnected Ext.Mgr never enables join-points
285: // Documentation updated accordingly.
286: //
|