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: // Contributor(s):
017: // $Id$
018: // =====================================================================
019: //
020: // (history at end)
021: //
022:
023: package ch.ethz.inf.iks.jvmai.jvmdi;
024:
025: import java.lang.reflect.Member;
026: import java.util.Collection;
027:
028: import ch.ethz.jvmai.MethodWeaver;
029: import ch.ethz.jvmai.JVMAIRuntimeException;
030:
031: /*
032: * Modifies a given class to support advice execution.
033: * Container for MethodWeavers, which does the code
034: * manipulations. Use the static method {@link
035: * #getWeaver(Method)} to get an instance of an
036: * {@link ch.ethz.jvmai.MethodWeaver}.
037: *
038: * Wrapper for the real ClassWeaver implementation.
039: * Selects which ClassWeaver to use, and forwards calls to this.
040: *
041: * @author Angela Nicoara
042: * @author Gerald Linhofer
043: * @version $Revision: 1.1.2.2 $
044: */
045: public abstract class HotSwapClassWeaver {
046: // The wrapper for the real class weaver
047: private static HotSwapClassWeaverWrapper wwrapper = null;
048: static {
049: // get class weavers name
050: String classWeaverName = System
051: .getProperty("ch.ethz.prose.HotSwapClassWeaver");
052: if (null == classWeaverName)
053: // select the default class weaver (that will be used if the property above is not set)
054: classWeaverName = "ch.ethz.inf.iks.jvmai.jvmdi.HotSwapSimpleClassWeaver";
055: //classWeaverName = "ch.ethz.inf.iks.jvmai.jvmdi.HotSwapAdvancedClassWeaver";
056: // get class weaver wrapper class
057: Class weaverClass;
058: try {
059: weaverClass = Class.forName(classWeaverName + "Wrapper");
060: } catch (ClassNotFoundException e) {
061: throw new JVMAIRuntimeException(
062: "can not get HotSwapClassWeaver: probably the property <ch.ethz.prose.HotSwapClassWeaver> was set to an invalid class");
063: }
064: // create an instance of a class weaver wrapper
065: try {
066: wwrapper = (HotSwapClassWeaverWrapper) weaverClass
067: .newInstance();
068: } catch (IllegalAccessException e1) {
069: throw new JVMAIRuntimeException("");
070: } catch (InstantiationException e2) {
071: throw new JVMAIRuntimeException("can not instantiate "
072: + classWeaverName + "1");
073: }
074: }
075:
076: // status codes ClassWeaver instances
077: public static final int WEAVER_STATUS_UNINITIALIZED = 0x0;
078: public static final int WEAVER_STATUS_INITIALIZED = 0x1;
079: /// Indicates modifications of the target class that were not yet woven
080: public static final int WEAVER_STATUS_MODIFIED = 0x2;
081: /// Target class was modified
082: public static final int WEAVER_STATUS_WOVEN = 0x4;
083: public static final int WEAVER_UNCHANGED_MASK = 0x6;
084:
085: /**
086: * String representation of the JVMAI class.
087: */
088: public static final String JVMAI_CLASS = "ch.ethz.inf.iks.jvmai.jvmdi.HotSwapAspectInterfaceImpl";
089:
090: //- Forwarders ---------------------------------------------------------------------
091:
092: /**
093: * Get a unique method weaver for 'target'.
094: *
095: * @param target method for which a weaver will be returned.
096: * @return MethodWeaver associated to <CODE>target</CODE>.
097: */
098: static public MethodWeaver getWeaver(Member target) /*throws ClassNotFoundException*/{
099: return wwrapper.getWeaver(target);
100: }
101:
102: /**
103: * Re-Weaves all modified classes and activates them.
104: */
105: static public void commit() {
106: //System.out.println("HotSwapClassWeaver.commit()");
107: wwrapper.commit();
108: }
109:
110: /**
111: * Resets all woven classes.
112: */
113: static public void resetAll() {
114: //System.out.println("HotSwapClassWeaver.resetAll()");
115: wwrapper.resetAll();
116: }
117:
118: /**
119: * Returns the Member object associated to <CODE>methodId</CODE>
120: * or <CODE>null</CODE>, if <CODE>methodID</CODE> is not a valid
121: * id.
122: *
123: * @param methodId id for the Method that will be returned.
124: * @return Method associated to <CODE>methodID<CODE> or <CODE>null</CODE>.
125: * @throws ArrayOutOfBoundException
126: */
127: public static Member idToMethod(int methodId) {
128: return wwrapper.idToMethod(methodId);
129: }
130:
131: /**
132: * Sets the aspect interface, must be called before any call to
133: * {@link #commit commit}.
134: *
135: * @param ai
136: */
137: public synchronized static void setAspectInterface(
138: HotSwapAspectInterfaceImpl ai) {
139: wwrapper.setAspectInterface(ai);
140: }
141:
142: //- Implementations--------------------------------------------------------------------
143:
144: /**
145: * Redefines existing classes, actually only method bodies may be redefined,
146: * but the JVMDI and JVMTI functions requieres the whole class code. The parameters
147: * are two arrays of the same size, each entry of one array corresponds to the
148: * entry with the same index in the other array.
149: * The class that should be redefined must exist in the JVM (they must be loaded
150: * in advance).
151: *
152: * Required for JVMDI/JVMTI HotSwap advice weaving.
153: *
154: * @param cls Array of Class objects that should get redefined
155: * @param definitions Array of class definitions, which are arrays of bytes,
156: * the definition is in the same form like in a class file.
157: * @exception UnmodifiableClassException <CODE>cls</CODE> contains a not modifiable
158: * class (for example an interface or a class that's not in the class path).
159: * @exception IlligalClassFormatException <CODE>definitions</CODE> contains a invalide
160: * class definition
161: * @exception RuntimeException could not apply operation.
162: * @exception NullPointerException if <CODE>cls</CODE> is <CODE>null</CODE>.
163: * @exception IlligalArgumentExceptin <CODE>definitions</CODE> is <CODE>null</CODE>.
164: */
165: public static void redefineClasses(Class[] cls, byte[][] definitions) {
166: // check preconditions
167: checkWatchPrecondition(cls, definitions);
168:
169: // check if number of classes == number of class definitions
170: if (definitions.length != cls.length)
171: throw new RuntimeException(
172: "JVMAspectInterface.setRedefineClasses: number of classes not equal to number of class definitions");
173:
174: doRedefineClasses(cls, definitions);
175: }
176:
177: /**
178: * Redefines an existing class, actually only method bodies may be redefined,
179: * but the JVMDI and JVMTI functions requieres the whole class code.
180: * The class that should be redefined must exist in the JVM (they must be loaded
181: * in advance).
182: *
183: * Required for JVMDI/JVMTI HotSwap advice weaving.
184: *
185: * @param cl Class objects that should get redefined
186: * @param definition class definition,
187: * the definition is in the same form like in a class file.
188: * @exception UnmodifiableClassException <CODE>cl</CODE> is a not modifiable
189: * class (for example an interface or a class that's not in the class path).
190: * @exception IlligalClassFormatException <CODE>definition</CODE> is a invalide
191: * class definition
192: * @exception RuntimeException could not apply operation.
193: * @exception NullPointerException if <CODE>cl</CODE> is <CODE>null</CODE>.
194: * @exception IlligalArgumentExceptin <CODE>definition</CODE> is <CODE>null</CODE>.
195: */
196: public static void redefineClass(Class cl, byte[] definition) {
197: // check preconditions
198: checkWatchPrecondition(cl, definition);
199:
200: doRedefineClass(cl, definition);
201: }
202:
203: /**
204: * Check if the parameters are not null and if this object
205: * was initialized. If not an exception will be thrown.
206: *
207: * @param arg
208: * @param aopTag
209: * @throws NotInitializedException this object was not initialized.
210: * @throws NullPointerException <CODE>arg<CODE> is <CODE>null</CODE>.
211: * @throws IlligalArgumentExceptin <CODE>aopTag</CODE> is <CODE>null</CODE>.
212: */
213: private static void checkWatchPrecondition(Object arg, Object aopTag) {
214: if (arg == null)
215: throw new NullPointerException(
216: "HotSwapAspectInterfaceImpl.setWatch: null argument parameter");
217: if (aopTag == null)
218: throw new IllegalArgumentException(
219: "HotSwapAspectInterfaceImpl.setWatch: null aopTag value");
220: }
221:
222: /**
223: * Redefines existing classes, actually only method bodies may be redefined,
224: * but the JVMDI and JVMTI functions requieres the whole class code. The parameters
225: * are two arrays of the same size, each entry of one array corresponds to the
226: * entry with the same index in the other array.
227: * The class that should be redefined must exist in the JVM (they must be loaded
228: * in advance).
229: *
230: * Required for JVMDI/JVMTI HotSwap advice weaving.
231: *
232: * @param cls Array of Class objects that should get redefined
233: * @param definitions Array of class definitions, which are arrays of bytes,
234: * the definition is in the same form like in a class file.
235: * @exception UnmodifiableClassException <CODE>cls</CODE> contains a not modifiable
236: * class (for example an interface or a class that's not in the class path).
237: * @exception IlligalClassFormatException <CODE>definitions</CODE> contains a invalide
238: * class definition
239: */
240: private static native void doRedefineClasses(Class[] c,
241: byte[][] definition);
242:
243: /**
244: * Redefines an existing class, actually only method bodies may be redefined,
245: * but the JVMDI and JVMTI functions requieres the whole class code.
246: * The class that should be redefined must exist in the JVM (they must be loaded
247: * in advance).
248: *
249: * Required for JVMDI/JVMTI HotSwap advice weaving.
250: *
251: * @param cl Class objects that should get redefined
252: * @param definition class definition,
253: * the definition is in the same form like in a class file.
254: * @exception UnmodifiableClassException <CODE>cl</CODE> is a not modifiable
255: * class (for example an interface or a class that's not in the class path).
256: * @exception IlligalClassFormatException <CODE>definition</CODE> is a invalide
257: * class definition
258: */
259: private static native void doRedefineClass(Class c,
260: byte[] definition);
261:
262: /**
263: * This method is not implemented! Dont use it,
264: * it will always throw an exception.
265: *
266: * @throws NotImplementedException always thrown
267: */
268: public abstract Class getTargetClass();
269:
270: /**
271: * This method is not implemented! Dont use it,
272: * it will always throw an exception.
273: *
274: * @throws NotImplementedException always thrown
275: */
276: public abstract Collection getMethods();
277: }
278:
279: //======================================================================
280: //
281: // $Log$
282: //
|