001: //
002: // This file is part of the midas 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 midas.
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: RemoteAspectManagerImpl.java,v 1.2 2003/08/26 19:55:01 anicoara Exp $
022: // =====================================================================
023: //
024: // (history at end)
025: //
026: package ch.ethz.prose.tools;
027:
028: import java.io.InputStream;
029: import java.rmi.RemoteException;
030: import java.util.Iterator;
031: import java.util.List;
032: import java.util.Vector;
033: import java.lang.reflect.Field;
034: import java.lang.reflect.Method;
035:
036: import ch.ethz.prose.Aspect;
037: import ch.ethz.prose.DefaultAspect;
038: import ch.ethz.prose.AspectManager;
039: import ch.ethz.prose.ProseSystem;
040: import ch.ethz.inf.util.Logger;
041: import ch.ethz.jvmai.JVMAspectInterface;
042: import ch.ethz.jvmai.SunBCELRepositoryInterface;
043: import ch.ethz.prose.crosscut.MethodRedefineCut;
044: import ch.ethz.prose.query.QueryManager;
045: import ch.ethz.prose.query.AspectSurrogate;
046: import ch.ethz.prose.crosscut.Crosscut;
047:
048: /** Class <code>RemoteAspectManagerImpl</code> a simple implementation for the
049: * <code>RemoteAspectManager</code> prose instance.
050: *
051: * <code>RemoteAspectManagerImpl</code> DOES NOT export the created objects;
052: * @version $Revision: 1.2 $
053: * @author Andrei Popovici
054: * @author Angela Nicoara
055: * @author Gerald Linhofer
056: */
057: public class RemoteAspectManagerImpl implements RemoteAspectManager {
058: private SunBCELRepositoryInterface ai; // only used for the remote insertion (event notification JVMDI + JVMTI)
059: private boolean isReal;
060: private boolean isRemote;
061: private AspectManager extMgr;
062: private QueryManager qMgr;
063:
064: public RemoteAspectManagerImpl(boolean real) throws RemoteException {
065: isReal = real;
066: }
067:
068: public void init() throws RemoteException {
069: if (extMgr == null) {
070: if (isReal)
071: extMgr = ProseSystem.getAspectManager();
072: else
073: extMgr = ProseSystem.getTestAspectManager();
074: qMgr = new QueryManager(extMgr);
075:
076: if (extMgr.getJoinPointManager().getAspectInterface() instanceof SunBCELRepositoryInterface) { // gerry
077: ai = (SunBCELRepositoryInterface) extMgr
078: .getJoinPointManager().getAspectInterface();
079: }
080: }
081: }
082:
083: /** Insert an extension into the underlying <code>ProseSystem</code>. */
084: public void insert(Aspect ext) throws RemoteException {
085: init();
086: insert(ext, null);
087: }
088:
089: public void withdraw(AspectSurrogate ext) throws RemoteException,
090: ClassNotFoundException {
091: init();
092: withdraw(ext, null);
093: }
094:
095: public void insert(Aspect ext, Object txId) throws RemoteException {
096: try {
097: init();
098:
099: // Workaround for MethodRedefineCuts and crosscutting aspects.
100: // The BCEL based implementation needs access to the aspects class file(s)
101: // to redefine the advice methods bodies.
102:
103: if (ai != null) {
104: // transfer ext and member classes to
105: // AspectInterfaces BCEL repository
106: putFullAspectIntoBCELRepository(ext);
107: }
108:
109: if (txId == null)
110: extMgr.insert(ext);
111: else
112: extMgr.insert(ext, txId);
113: } catch (Throwable t) {
114: throw new RemoteException(t.toString());
115: }
116: }
117:
118: /**
119: * Makes the declared fields of a class available
120: * to PROSE BCEL repository.
121: *
122: * @param cls The clasc
123: */
124: private void putFieldsIntoBCELRepository(Class cls) {
125: //System.err.println("RemoteAspectManagerImpl - putFieldsIntoBCELRepository => CLASS = " + cls.getName());
126: // get all fields that it declares
127: Field[] declaredFields = cls.getDeclaredFields();
128: for (int i = 0; i < declaredFields.length; i++) {
129: //System.err.println("RemoteAspectManagerImpl - putFieldsIntoBCELRepository + FIELDS.type = " + declaredFields[i].getType());
130: // Don't send classes primitive types
131: if (!declaredFields[i].getType().isPrimitive())
132: putClassFileIntoBCELRepository(declaredFields[i]
133: .getType());
134: }
135: }
136:
137: /**
138: * Makes the methods parameters of a class available
139: * to PROSE BCEL repository.
140: *
141: * @param cls The class
142: */
143: private void putMethodParametersIntoBCELRepository(Class cls) {
144: //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => CLASS = " + cls.getName());
145: Method[] methods = cls.getDeclaredMethods();
146: for (int i = 0; i < methods.length; i++) {
147: //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => METHODS = " + methods[i]);
148: Class[] param = methods[i].getParameterTypes();
149: for (int j = 0; j < param.length; j++) {
150: putClassFileIntoBCELRepository(param[j]);
151: //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => PARAM types: " + param[j].getName());
152: //System.err.println("RemoteAspectManagerImpl - putMethodParametersIntoBCELRepository => PARAM length: " + param.length);
153: }
154: // Put also the return type into the repository
155: putClassFileIntoBCELRepository(methods[i].getReturnType());
156: }
157: }
158:
159: /**
160: * Makes the crosscuts of an aspect available to the
161: * PROSE BCEL repository.
162: *
163: * @param ext The aspect
164: */
165: private void putCrosscutsIntoBCELRepository(Aspect ext) {
166: //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository => CLASS = " + ext.toString());
167: try {
168: Method m = null;
169: Class cls = ext.getClass();
170: if (DefaultAspect.class.isAssignableFrom(cls)) {
171: do {
172: cls = cls.getSuperclass();
173: } while (!DefaultAspect.class.equals(cls));
174: }
175: //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository => CROSSCUT = " + cls.getName());
176:
177: m = cls.getDeclaredMethod("crosscuts", new Class[] {});
178: m.setAccessible(true);
179: Crosscut[] cc = (Crosscut[]) m.invoke(ext, new Object[] {});
180:
181: //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository => Number of CROSSCUTS => " + cc.length);
182: for (int i = 0; i < cc.length; i++) {
183: //System.err.println("RemoteAspectManagerImpl - putCrosscutsIntoBCELRepository - CROSSCUT = " + cc[i].toString());
184: Class ccls = cc[i].getClass();
185: putFieldsIntoBCELRepository(ccls);
186: putMethodParametersIntoBCELRepository(ccls);
187: putClassFileIntoBCELRepository(ccls);
188: }
189: } catch (Exception e) {
190: System.err
191: .println("RemoteAspectManagerImpl - putCrosscutIntoBCELRepository: "
192: + e);
193: }
194: }
195:
196: /**
197: * Makes an aspect available to PROSEs BCEL repository.
198: * <P>
199: * The aspect, all classes of its fields and all member/inner
200: * classes will be added to the repository.
201: * <P>
202: * This fetches the aspects, its fields and inner classes,
203: * the public inner classes and fields of its super classes and its
204: * anonymous inner classes.
205: *
206: * @param ext the aspect
207: */
208: private void putFullAspectIntoBCELRepository(Aspect ext) {
209:
210: // 1. get all crosscuts and put them into the BCEL repository
211: putCrosscutsIntoBCELRepository(ext);
212:
213: Class clazz = ext.getClass();
214: do {
215: // 2. put the class into the repository
216: putClassFileIntoBCELRepository(clazz);
217:
218: // 3. put the types of the methods parameters into the repository
219: putMethodParametersIntoBCELRepository(clazz);
220:
221: // 4. put its fields into the repository
222: putFieldsIntoBCELRepository(clazz);
223:
224: // 5. put its declared inner classes into the repository
225: Class[] declaredClasses = clazz.getDeclaredClasses();
226: for (int i = 0; i < declaredClasses.length; i++) {
227: Class innerClass = declaredClasses[i];
228: putClassFileIntoBCELRepository(innerClass);
229: putFieldsIntoBCELRepository(innerClass);
230: putMethodParametersIntoBCELRepository(innerClass);
231: }
232:
233: // 6. put its anonymous inner classes into the repository
234: String extName = clazz.getName();
235: int j = 1;
236: InputStream classFile;
237: // Anonymous inner classes are numbered beginning from 1.
238: // Following approach reconstructs the filenames and tries to get
239: // the according files. If no file is found, all anonymous inner classes are
240: // already processed.
241: while (null != (classFile = ext.getClass()
242: .getResourceAsStream(
243: extName.replace('.', '/') + "$" + j
244: + ".class"))) {
245: String clsName = extName + "$" + j;
246: ai.addBCELClassDefiniton(classFile, clsName);
247: j++;
248: }
249:
250: // 7. do the same thing for its super class (until the class 'Aspect' is reached)
251: // looking for 'DefaultAspect' might be more efficient. But this is
252: // safe, in case an aspect class was directly derived from 'Aspect'.
253: clazz = clazz.getSuperclass();
254: } while (!clazz.equals(Aspect.class));
255: }
256:
257: /**
258: * Makes a class file available to PROSEs BCEL repository.
259: * <P>
260: * (for this method, the client must be connected to a PROSE VM
261: * that uses a HotSwap based execution monitor)
262: *
263: * @param cls the class that will be transfered
264: */
265: private void putClassFileIntoBCELRepository(Class cls) {
266: //System.err.println("RemoteAspectManagerImpl - putClassFileIntoBCELRepository => CLASS = " + cls.getName());
267: //System.err.println("RemoteAspectManagerImpl - putClassFileIntoBCELRepository => class name: " + cls.getName() + " converted to" + cls.getName().replace('.','/') + ".class");
268: InputStream classFile = cls.getResourceAsStream(cls.getName()
269: .replace('.', '/')
270: + ".class");
271: if (null != classFile && null != ai) {
272: ((SunBCELRepositoryInterface) ai).addBCELClassDefiniton(
273: classFile, cls.getName());
274: Logger.message("transfered class file " + cls.getName());
275: } else {
276: Logger
277: .warning("RemoteAspectManager.putClassFileInBCELRepository failed for "
278: + cls + " (AspectInterface: " + ai + ")");
279: }
280: }
281:
282: public void withdraw(AspectSurrogate ext, Object txId)
283: throws RemoteException, ClassNotFoundException {
284: init();
285: Aspect asp = qMgr.reconstructAspect(ext);
286:
287: List x = new Vector((extMgr.getAllAspects()));
288: int extIndx = x.indexOf(asp);
289: if (extIndx >= 0) {
290: if (txId == null) {
291: extMgr.withdraw((Aspect) (x.get(extIndx)));
292: } else
293: extMgr.withdraw((Aspect) (x.get(extIndx)), txId);
294: } else {
295: Logger.message("extension " + ext + " not known");
296: throw new RuntimeException("extension " + ext
297: + " not known");
298: }
299: }
300:
301: public void commit(Object txId) throws RemoteException {
302: init();
303: extMgr.commit(txId);
304: }
305:
306: public void abort(Object txId) throws RemoteException {
307: init();
308: extMgr.abort(txId);
309: }
310:
311: /**
312: * Return a list of the current inserted extensions.
313: */
314: public List allAspects() throws RemoteException {
315: init();
316: return qMgr.queryAllAspects();
317: }
318:
319: public List allJoinpoints() throws RemoteException {
320: init();
321: return qMgr.queryAllJoinpoints();
322: }
323:
324: /**
325: * Return a List of Tupel objects (without duplicates) that represents the result of querying the system
326: * with a list of Aspects.
327: */
328: public List queryAspects(List aspectList, int selectFields,
329: int groupBy) throws RemoteException {
330: init();
331: return qMgr.queryAspects(aspectList, selectFields, groupBy);
332: }
333:
334: /**
335: * Return a List of Tupel objects (without duplicates) that represents the result of querying the system
336: * with a list of Crosscuts.
337: */
338: public List queryCrosscuts(List crosscutList, int selectFields,
339: int groupBy) throws RemoteException {
340: init();
341: return qMgr.queryCrosscuts(crosscutList, selectFields, groupBy);
342: }
343:
344: /**
345: * Return a List of Tupel objects (without duplicates) that represents the result of querying the system
346: * with a list of JoinPointRequests.
347: */
348: public List queryJoinpoints(List joinpointList, int selectFields,
349: int groupBy) throws RemoteException {
350: init();
351: return qMgr.queryJoinpoints(joinpointList, selectFields,
352: groupBy);
353: }
354:
355: }
356:
357: //======================================================================
358: //
359: // $Log: RemoteAspectManagerImpl.java,v $
360: // Revision 1.2 2003/08/26 19:55:01 anicoara
361: // Bug fix: JVM1.4.1 blocks (add the init method)
362: //
363: // Revision 1.1.1.1 2003/07/02 15:30:52 apopovic
364: // Imported from ETH Zurich
365: //
366: // Revision 1.1 2003/05/25 13:25:17 popovici
367: // Refactoring
368: // inf.iks.tools is now prose.tools
369: // Stupid 'MyTableModel' renamed to 'WorksheetClientMode'
370: // - other renamings from bad names to reasonable names
371: //
372: // Revision 1.8 2003/05/25 11:48:51 popovici
373: // Major transformation of the prose tools:
374: // - GUI now stable and supports aspect insertion from another classpath than its own
375: // - CommandlineProseClient supports transactions test managers, independent classpath and has a better errhanling
376: //
377: // Revision 1.7 2003/05/20 16:05:00 popovici
378: //
379: // New QueryManager replaces functionality in AspectManager (better Soc)
380: // New 'Surrogate' classes for usage in the QueryManager
381: // The 'RemoteAspectManager' and tools modified to use the Surrogates and the QueryManager
382: //
383: // Revision 1.6 2003/05/05 14:03:13 popovici
384: // renaming from runes to prose
385: //
386: // Revision 1.5 2003/04/17 15:14:56 popovici
387: // Extension->Aspect renaming
388: //
389: // Revision 1.4 2003/04/17 12:49:45 popovici
390: // Refactoring of the crosscut package
391: // ExceptionCut renamed to ThrowCut
392: // McutSignature is now SignaturePattern
393: //
394: // Revision 1.3 2003/04/17 08:47:06 popovici
395: // Important functionality additions
396: // - Cflow specializers
397: // - Restructuring of the MethodCut, SetCut, ThrowCut, and GetCut (they are much smaller)
398: // - Transactional capabilities
399: // - Total refactoring of Specializer evaluation, which permits fine-grained distinction
400: // between static and dynamic specializers.
401: // - Functionality pulled up in abstract classes
402: // - Uniformization of advice methods patterns and names
403: //
404: // Revision 1.2 2003/03/04 18:35:57 popovici
405: // Organization of imprts
406: //
407: // Revision 1.1 2003/02/17 09:23:53 popovici
408: // RemoteAspectManager interface, implementation, and client added;
409: // Benchmark changed to work with the remote aspect manager;
410: // Benchmark changed to include aspect insertion;
411: //
412: // Revision 1.2 2002/07/25 08:55:39 popovici
413: // Mozilla Licensing
414: //
415: // Revision 1.1.1.1 2001/11/30 14:50:28 popovici
416: // Sources from runes
417: //
418: // Revision 1.1.2.1 2001/03/26 15:05:43 mrmuller
419: // adapted to new package structure
420: //
421: // Revision 1.1.2.4 2001/02/20 10:13:14 popovici
422: // -Bug fix: 'withdrawExtnesion' now matches specified extension against
423: // existing ones, thus complying to the new 'ProseSystem' specs.
424: // -'insertExtensions' throws on 'AspectManagerException'
425: //
426: // Revision 1.1.2.3 2001/02/15 15:20:08 popovici
427: // Removed some messages to stderr.
428: //
429: // Revision 1.1.2.2 2001/02/15 11:40:57 popovici
430: // Documentation Improvements
431: //
432: // Revision 1.1.2.1 2001/02/14 13:44:40 popovici
433: // Initial Revision
434: //
435: // Revision 1.1.2.2 2001/01/23 09:28:08 popovici
436: // extensions() now returns a set of Exensions
437: //
438: // Revision 1.1.2.1 2000/10/24 17:45:54 popovici
439: // 'addExtension' renamed to 'insertExtension'
440: // 'removeExtension' renamed to 'withdrawExtension'
441: // method 'extensions' added
442: //
443: // Revision 1.1 2000/10/16 11:53:25 popovici
444: // Initial Revision
445: //
|