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:
022: package ch.ethz.prose.crosscut;
023:
024: import java.io.Serializable;
025: import java.lang.reflect.Method;
026: import java.lang.Error;
027: import java.lang.Class;
028: import java.lang.ArrayIndexOutOfBoundsException;
029:
030: ///////////////////////////////////////////////////////////////////////////////////////////
031: /// ADVICE DEFINITION (STATIC PART)
032: ///////////////////////////////////////////////////////////////////////////////////////////
033:
034: /** Every Crosscut contains a method to be executed when a join-point is hit.
035: * In the case of <code>MethodCut</code> objects, the advice method has three
036: * roles:
037: * <ul>
038: * <li> The pattern role: through a special signature, define matches for the
039: * target class, and for the parameters of the methods belonging to the target.
040: *
041: * <li> The method finder role: determine which method o of the crosscut
042: * must be ivoked upon a hit join-point.
043: *
044: * <li> The optimization role: to cathegorize the signature of the advice
045: * method, such that the subsequent execution of the advice method is efficient.
046: * The categorization is currently performed according to the <code>SIGNATURE__XXX</code>
047: * constants.
048: * </ul>
049: */
050: class MethodCutSignaturePattern extends SignaturePattern implements
051: Serializable {
052: private static final long serialVersionUID = 4051049674519426361L;
053: private final MethodCut methodCut;
054:
055: /**
056: * Create an <code>UserDefinedMCSignature</code> that encapsulates the
057: * method to be executed.
058: * <p>
059: * Postcondition: methodObj is properly initialized
060: * <p>
061: * Implementation:
062: * <ul>
063: * <li> if <code>crsc</code> (i.e., a subclass of FunctionalCrossscut)
064: * <em>defines</em> exaclty one method, this method is
065: * the advice method.
066: *
067: * <li> If <code>crsc</code> defines several methods, the one whose
068: * name corresponds to <code>crsc.ADVICE_NAME()</code> is the advice method
069: * </ul>
070: * @throws MissingInformationExeception crsc does not define a method at all,
071: * or if it defines several, none of them matches <code>crsc.ADVICE_NAME()</code>.
072: *
073: */
074: protected MethodCutSignaturePattern(MethodCut crsc)
075: throws MissingInformationException {
076: this .methodCut = crsc;
077: initFromMethod(crsc.getClass(), "METHOD_ARGS", REST.class,
078: MethodCut.class);
079: }
080:
081: /** Returns <code>true</code> if the signature of
082: * <code>methoObj</code>, seen as a pattern,
083: * matches the signature (the parameter types) for
084: * <code>actualMehtod</code>.
085: */
086: protected boolean matchesParameters(Method actualMethod) {
087: if (signatureCathegory == SIGNATURE__EMPTY)
088: return true;
089: else
090: return doMatchLength(actualMethod)
091: && doMatchSignature(actualMethod);
092: }
093:
094: private Class[] subarray(Class[] arr, int index) {
095: Class[] result = new Class[arr.length - index];
096: System.arraycopy(arr, index, result, 0, result.length);
097: return result;
098: }
099:
100: private boolean doMatchSignature(Method actualMethod) throws Error {
101: boolean signatureOK = true;
102: Class[] params = actualMethod.getParameterTypes();
103: for (int j = 1; j < signature.length && signatureOK; j++) {
104: int adviceParamPos = j;
105: int actualParamPos = j - 1;
106:
107: try {
108: if (isAssignable(subarray(params, actualParamPos),
109: signature[adviceParamPos]))
110: signatureOK = true;
111: else if (isAssignable(params[actualParamPos],
112: signature[adviceParamPos])) {
113: // if the current advice Param is the last one, the length must concide
114: signatureOK = true;
115: if (adviceParamPos + 1 == signature.length) {
116: signatureOK = (signature.length == params.length + 1);
117: }
118: } else
119: signatureOK = false;
120:
121: } catch (ArrayIndexOutOfBoundsException e) {
122: signatureOK = false;
123: }
124: }
125: return signatureOK;
126: }
127:
128: private boolean doMatchLength(Method actualMethod) {
129: Class[] params = actualMethod.getParameterTypes();
130: return ((signature.length == 1 && params.length == 0) || signature.length > 1);
131: }
132:
133: public String toString() {
134: return methodObj.toString();
135: }
136: }
|