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 Developers of the Original Code are Angela Nicoara 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: import java.io.Serializable;
029: import java.lang.reflect.Constructor;
030: import java.lang.Error;
031: import java.lang.Class;
032: import java.lang.ArrayIndexOutOfBoundsException;
033:
034: ///////////////////////////////////////////////////////////////////////////////////////////
035: /// ADVICE DEFINITION (STATIC PART)
036: ///////////////////////////////////////////////////////////////////////////////////////////
037:
038: /** Every Crosscut contains a method to be executed when a join-point is hit.
039: * In the case of <code>ConstructorCut</code> objects, the advice method has three
040: * roles:
041: * <ul>
042: * <li> The pattern role: through a special signature, define matches for the
043: * target class, and for the parameters of the constructors belonging to the target.
044: *
045: * <li> The method finder role: determine which method o of the crosscut
046: * must be ivoked upon a hit join-point.
047: *
048: * <li> The optimization role: to cathegorize the signature of the advice
049: * method, such that the subsequent execution of the advice method is efficient.
050: * The categorization is currently performed according to the <code>SIGNATURE__XXX</code>
051: * constants.
052: * </ul>
053: */
054: class ConstructorCutSignaturePattern extends SignaturePattern implements
055: Serializable {
056: /**
057: * The "Serial Version Unique Identifier", used for seriallizing this class.
058: */
059: private static final long serialVersionUID = 3257284738426220597L;
060:
061: /**
062: * Associated ConstructorCut object.
063: */
064: private final ConstructorCut constructorCut;
065:
066: /**
067: * Create an <code>UserDefinedCCSignature</code> that encapsulates the
068: * method to be executed.
069: * <p>
070: * Postcondition: methodObj is properly initialized
071: * <p>
072: * Implementation:
073: * <ul>
074: * <li> if <code>crsc</code> (i.e., a subclass of FunctionalCrossscut)
075: * <em>defines</em> exaclty one method, this method is
076: * the advice method.
077: *
078: * <li> If <code>crsc</code> defines several methods, the one whose
079: * name corresponds to <code>crsc.ADVICE_NAME()</code> is the advice method
080: * </ul>
081: * @throws MissingInformationExeception crsc does not define a method at all,
082: * or if it defines several, none of them matches <code>crsc.ADVICE_NAME()</code>.
083: *
084: */
085: protected ConstructorCutSignaturePattern(ConstructorCut crsc)
086: throws MissingInformationException {
087: this .constructorCut = crsc;
088: initFromMethod(crsc.getClass(), "METHOD_ARGS", REST.class,
089: ConstructorCut.class);
090: }
091:
092: /** Returns <code>true</code> if the signature of
093: * <code>constructorObj</code>, seen as a pattern,
094: * matches the signature (the parameter types) for
095: * <code>actualConstructor</code>.
096: */
097: protected boolean matchesParameters(Constructor actualConstructor) {
098: if (signatureCathegory == SIGNATURE__EMPTY)
099: return true;
100: else
101: return doMatchLength(actualConstructor)
102: && doMatchSignature(actualConstructor);
103: }
104:
105: /**
106: * Returns a subarray of <CODE>arr</CODE> beginning at
107: * <CODE>index</CODE>.
108: * @param arr the array
109: * @param index the index from where the subarray should
110: * be copied.
111: * @return the subarray
112: */
113: private Class[] subarray(Class[] arr, int index) {
114: Class[] result = new Class[arr.length - index];
115: System.arraycopy(arr, index, result, 0, result.length);
116: return result;
117: }
118:
119: private boolean doMatchSignature(Constructor actualConstructor)
120: throws Error {
121: boolean signatureOK = true;
122: Class[] params = actualConstructor.getParameterTypes();
123: for (int j = 1; j < signature.length && signatureOK; j++) {
124: int adviceParamPos = j;
125: int actualParamPos = j - 1;
126:
127: try {
128: if (isAssignable(subarray(params, actualParamPos),
129: signature[adviceParamPos]))
130: signatureOK = true;
131: else if (isAssignable(params[actualParamPos],
132: signature[adviceParamPos])) {
133: // if the current advice Param is the last one, the length must concide
134: signatureOK = true;
135: if (adviceParamPos + 1 == signature.length) {
136: signatureOK = (signature.length == params.length + 1);
137: }
138: } else
139: signatureOK = false;
140:
141: } catch (ArrayIndexOutOfBoundsException e) {
142: signatureOK = false;
143: }
144: }
145: return signatureOK;
146: }
147:
148: private boolean doMatchLength(Constructor actualConstructor) {
149: Class[] params = actualConstructor.getParameterTypes();
150: return ((signature.length == 1 && params.length == 0) || signature.length > 1);
151: }
152:
153: public String toString() {
154: return methodObj.toString();
155: }
156: }
157:
158: //======================================================================
159: //
160: // $Log$
161: //
|