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 Angela Nicoara and Gerald Linhofer.
017: // All Rights Reserved.
018: //
019: // Contributor(s):
020: // $Id$
021: // =====================================================================
022: //
023: // (history at end)
024: //
025:
026: package ch.ethz.prose.crosscut;
027:
028: // used packages
029: import java.lang.reflect.InvocationTargetException;
030: import java.lang.reflect.Method;
031: import java.lang.reflect.Constructor;
032: import java.util.Arrays;
033: import java.util.Iterator;
034: import java.util.List;
035: import java.util.Vector;
036:
037: import ch.ethz.jvmai.JoinPoint;
038: import ch.ethz.prose.engine.JoinPointRequest;
039: import ch.ethz.jvmai.ConstructorJoinPoint;
040: import ch.ethz.prose.filter.ANDingPointCutter;
041: import ch.ethz.prose.filter.PointCutter;
042:
043: /**
044: * Class ConstructorCut represents a crosscut. Such a crosscut
045: * defines a pattern (for matching specific join-points) and a method
046: * to be executed. Users must subclass <code>ConstructorCut</code>.
047: * There are two main modalities for subclassing:
048: * <h3>The tipical way (normal user)</h3>
049: * Define exactly one method (e.g., <code>METHOD_ARGS(Bar thisO,Baz param1)</code>).
050: * This method is both the advice action to be executed and it defines
051: * a pattern. Thus, just entries and exits of invocations of the form
052: * <code>Bar.*(Baz)</code> will be considered join-points of this
053: * crosscut.
054: * <p>
055: * This crosscut defines a crosscut for all entry-
056: * points of the matched constructor.
057: * <p>
058: * Use <code>pointCutter</code> to further restrict the number of
059: * points were advices are executed.
060: *
061: * @version $Revision$
062: * @author Angela Nicoara
063: * @author Gerald Linhofer
064: */
065: public abstract class ConstructorCut extends AbstractCrosscut implements
066: java.io.Serializable {
067:
068: ///////////////////////////////////////////////////////////////////////////////////////////
069: /// THE CROSSCUT: ADVICE METHOD + ADVICE EXECUTION put together
070: ///////////////////////////////////////////////////////////////////////////////////////////
071:
072: /**
073: * Override the value of this variable if you want to change the
074: * name of the method wildcards.
075: */
076: public void METHOD_ARGS() {
077: }
078:
079: /**
080: * If you have more than one method in this class, determining the
081: * name of the advice method will use the value of this method. This
082: * variable should then be initialized with the name of the method
083: * you want to call as advice method.
084: */
085:
086: transient boolean isInitialized = false;
087: transient ConstructorCutSpecializer ccutSpecializer = null;
088: transient ConstructorCutSignaturePattern adviceSignature = null;
089: String toStringSignature;
090:
091: private void initState() throws MissingInformationException {
092:
093: if (isInitialized)
094: return;
095: isInitialized = true;
096:
097: adviceSignature = new ConstructorCutSignaturePattern(this );
098: ccutSpecializer = new ConstructorCutSpecializer(adviceSignature);
099:
100: toStringSignature = adviceSignature.toString();
101:
102: }
103:
104: /**
105: * We want people to subclass this class.
106: * Create a <code>ConstructorCut</code> object.
107: *
108: * @throws MissingInformationException this crosscut does
109: * not define an advice method / or does not override methodAdvice.
110: */
111: protected ConstructorCut() throws MissingInformationException {
112: initState();
113: }
114:
115: public void insertionAction(boolean beforeInsertion) {
116: super .insertionAction(beforeInsertion);
117:
118: // we might provide an initstate here for the case
119: // this crosscut is deserialized and the
120: // static initializer or the constructor are not properly
121: // called
122: initState();
123: }
124:
125: /**
126: * Return all potential classes to which this crosscut applies:
127: * To all loaded classes, apply the <code>isPotentialCrosscutClass</code>
128: * selector.
129: */
130: protected Class[] potentialCrosscutClasses()
131: throws MissingInformationException {
132: // get exactly one method declared in this class with more
133: // than one argument
134:
135: Class[] result = new Class[] {};
136: List searchList = new Vector(Arrays.asList(super
137: .potentialCrosscutClasses()));
138:
139: // if the receiver class is not a wildcard, we add the
140: // receiver class to the potential crosscut classes
141: Class receiverClass = adviceSignature.getReceiverType();
142: if (receiverClass != null
143: && !Wildcard.class.isAssignableFrom(receiverClass)
144: && !searchList.contains(receiverClass))
145: searchList.add(receiverClass);
146: Vector resultList = new Vector();
147:
148: // then we search in the search list
149: Iterator i = searchList.iterator();
150: while (i.hasNext()) {
151: Class crtCls = (Class) i.next();
152: if (isPotentialCrosscutClass(crtCls))
153: resultList.add(crtCls);
154: }
155:
156: // and return the corresponding array
157: result = (Class[]) resultList.toArray(new Class[] {});
158: return result;
159: }
160:
161: /** Return true only if
162: *
163: * <ol>
164: * <li> This crosscut redefines the <code>methodAdvice</code> method, <em>OR</em>
165: * <li> if this crosscut defines an advice, and the corresponding <code>UserDefinedMCSignature</code>
166: * matches the target class <code>crtCls</code>.
167: * </ol>
168: */
169: protected boolean isPotentialCrosscutClass(Class crtCls)
170: throws MissingInformationException {
171: return adviceSignature.matchesTarget(crtCls);
172: }
173:
174: /**
175: * Retrieve those constructors belonging to <code>theClass</code>
176: * which have the same signature as the advice methods. Use the
177: * <code>UserDefinedMCSignature</code> object (<code>adviceSignature</code>)
178: * to determine which constructors defined in class <code>theClass</code>
179: * match the pattern.
180: * (if wildcards
181: * are present, they use them to match more constructors in <code>theClass</code>)
182: * <p>
183: * Return a list of <code>JoinPointRequest</code> objects corresponding
184: * to all locations of the matched constructors.
185: * <p>
186: * <em>This implementation will return just Constructor-Entry locations.</em>.
187: */
188: protected CrosscutRequest doCreateRequest(Class theClass) {
189:
190: //1. retrieve those constructors TCM belonging to class theClass
191: // for which the following holds:
192: // if M[i] is not a wildcard, M[i] is assignable from TCM[i]
193: // if M[i] is a wildcard, TCM[i] matches M[i] or
194: // TCM[i..TCM.lenth] matches M[i]
195: CrosscutRequest result = new CrosscutRequest();
196:
197: //take the constructors declared in the given class only (ignore
198: //inherited constructors!)
199: //A possible problem might occur because of the access control
200: Constructor[] constructorArray = null;
201:
202: try {
203: constructorArray = theClass.getDeclaredConstructors();
204: } catch (NoClassDefFoundError e) {
205: return result;
206: }
207:
208: for (int i = 0; i < constructorArray.length; i++) {
209: Class[] params = constructorArray[i].getParameterTypes();
210: JoinPointRequest crtRequest;
211:
212: crtRequest = requestFactory.createJoinPointRequest(
213: ConstructorJoinPoint.KIND, constructorArray[i]);
214: if (ccutSpecializer.isSpecialRequest(crtRequest))
215: result.add(crtRequest);
216: }
217:
218: return result;
219: }
220:
221: /**
222: * Create an action to execute the advice which matched the
223: * constructor in which the location of <code>jpe</code> resides.
224: *
225: * @exception InvocationTargetException some error occured inside
226: * the advice method.
227: * @exception IllegalAccessException the advice method was not public
228: */
229: public void joinPointAction(ConstructorJoinPoint ev)
230: throws IllegalAccessException, InvocationTargetException {
231: constructorAdvice(ev);
232: }
233:
234: // /**
235: // * Create an action to execute the advice which matched the
236: // * method in which the location of <code>jpe</code> resides.
237: // *
238: // * @exception InvocationTargetException some error occured inside
239: // * the advice method.
240: // * @exception IllegalAccessException the advice method was not public
241: // */
242: // public void joinPointAction(MethodExitJoinPoint ev) throws IllegalAccessException, InvocationTargetException
243: // {
244: // // call advice
245: // methodAdvice(ev);
246: // }
247: //
248: //
249: /** If 'constructorAdvice' has been redefined, then we will deal with a
250: * 'DefaultMcutSignature'. But in THAT case, this method
251: * will be never executed.
252: *
253: */
254: private void constructorAdvice(JoinPoint joinPoint)
255: throws InvocationTargetException, IllegalAccessException {
256:
257: // create the appropriate 'adviceExecutionObject';
258: CcutAdvice toRun = null;
259: switch (adviceSignature.signatureCathegory) {
260: case SignaturePattern.SIGNATURE__EMPTY:
261: METHOD_ARGS();
262: break;
263: case SignaturePattern.SIGNATURE__CONCRETE__CONCRETE:
264: toRun = new ConcreteConcreteCcutAdvice(this , joinPoint,
265: (ConstructorCutSignaturePattern) adviceSignature);
266: break;
267: case SignaturePattern.SIGNATURE__WILDCARD__CONCRETE:
268: toRun = new WildcardConcreteCcutAdvice(this , joinPoint,
269: (ConstructorCutSignaturePattern) adviceSignature);
270: break;
271: case SignaturePattern.SIGNATURE__WILDCARD__WILDCARD:
272: toRun = new WildcardWildcardCcutAdvice(this , joinPoint,
273: (ConstructorCutSignaturePattern) adviceSignature);
274: break;
275: case SignaturePattern.SIGNATURE__CONCRETE__WILDCARD:
276: toRun = new ConcreteWildcardCcutAdvice(this , joinPoint,
277: (ConstructorCutSignaturePattern) adviceSignature);
278: break;
279: default:
280: toRun = new DefaultCcutAdvice(this , joinPoint,
281: (ConstructorCutSignaturePattern) adviceSignature);
282: break;
283: }
284:
285: toRun.execute();
286:
287: }
288:
289: public PointCutter equivalentSpecializer() {
290: initState();
291: if (getSpecializer() == null)
292: return ccutSpecializer;
293: else
294: return new ANDingPointCutter(ccutSpecializer,
295: (PointCutter) getSpecializer());
296: }
297:
298: /**
299: * Get advice method, i.e. <code>METHOD_ARGS(...)</code>. The advice
300: * method is used by the full code weaver.
301: *
302: * @return advice method
303: */
304: public Method getMethod() {
305: return adviceSignature.methodObj;
306: }
307:
308: public String toString() {
309: return " Crosscut: 'ConstructorCut' \n" + " Advice:"
310: + toStringSignature + "\n" + " PointCutter: "
311: + getSpecializer() + "\n";
312: }
313: }
314:
315: //======================================================================
316: //
317: // $Log$
318: //
|