Package ch.ethz.prose.crosscut

Source Code of ch.ethz.prose.crosscut.SignaturePattern

//
//  This file is part of the prose package.
//
//  The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (the "License"); you may not use this file except in
//  compliance with the License. You may obtain a copy of the License at
//  http://www.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS" basis,
//  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
//  for the specific language governing rights and limitations under the
//  License.
//
//  The Original Code is prose.
//
//  The Initial Developer of the Original Code is Andrei Popovici. Portions
//  created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
//  All Rights Reserved.
//
//  Contributor(s):
//  $Id: SignaturePattern.java,v 1.3 2008/11/18 11:36:07 anicoara Exp $
//  =====================================================================
//

package ch.ethz.prose.crosscut;

// used packages
import java.lang.reflect.Method;
import java.lang.Class;


/**
* Every Crosscut contains a method to be executed when a join-point is hit.
* In the case of <code>MethodCut</code> objects, the SignaturePattern has three
* roles:
* <ul>
* <li> The pattern role: through a special signature, define matches for the
* target class, and for the parameters of the methods belonging to the target.
*
* <li> The method finder role: determine which method o of the crosscut
* must be ivoked upon a hit join-point.
*
* <li> The optimization role: to cathegorize the signature of  the advice
* method, such that the subsequent execution of the advice method is efficient.
* The categorization is currently performed according to the <code>SIGNATURE__XXX</code>
* constants.
* </ul>
*
* @version  $Revision: 1.3 $
* @author  Andrei Popovici
*/
public abstract class SignaturePattern {

  // work constants           bit 3     bit 2
  protected final static int WILDCARD_1 = 0x02;
  protected final static int WILDCARD_2 = 0x04;
  protected final static int CONCRETE_1=  0x08;
  protected final static int CONCRETE_2=  0x01;

  /// constants reflecting the cathegory of the signature of <code>methodObj</code>
  protected static final int SIGNATURE__WILDCARD__WILDCARD = WILDCARD_1 | WILDCARD_2;
  protected static final int SIGNATURE__WILDCARD__CONCRETE = WILDCARD_1 | CONCRETE_2;
  protected static final int SIGNATURE__CONCRETE__WILDCARD = CONCRETE_1 | WILDCARD_2;
  protected static final int SIGNATURE__CONCRETE__CONCRETE = CONCRETE_1 | CONCRETE_2;
  protected static final int SIGNATURE__ARBITRARY = 0;
  protected static final int SIGNATURE__EMPTY     = 0x1000;

  /** The signature cathegory of <code>methodObj</code>.
   */
  protected int     signatureCathegory = SIGNATURE__ARBITRARY;

  /** The method to be invoked upon reaching a joinpoint,
   * or <code>null</code> if the enclosing
   * Crosscut defines its own <code>adviceMethod</code>.
   */
  protected transient Method  methodObj = null;

  /** The signature of <code>methodObj</code>, equivalent to
   *  <code>methodObj.getParameterTypes()</code>. Present
   * for efficiency reasons.
   */
  protected transient Class[] signature = null;

  protected transient Class wildcardClass = null;

  /**
   * Return the number of arguments required by this advice.
   */
  protected int getLength() {
    return signature.length;
  }

  protected Class getReceiverType() {
    if (signature.length == 0)
      return null;
    else
      return signature[0];
  }

  /** When no advice action is set, it returns true.
   * If an advice action exists, it returns true
   * if the pattern-matching signature acepts <code>actualClass</code>
   * as a potential crosscut class.
   */
  protected boolean matchesTarget(Class actualClass) {
    if (signatureCathegory == SIGNATURE__EMPTY)
      return true;
    else
      return isAssignable(actualClass, signature[0]);
  }


  protected boolean isAssignable(Class actualParameterType, Class formalParameterType) throws Error {   
    if (Wildcard.class.isAssignableFrom(formalParameterType)) {
      try  {
        if (((Wildcard)formalParameterType.newInstance()).isAssignableFrom(actualParameterType))
          return true;

        // the Wilcard specification states that wildcard classes
        // should have an emtpy default constructor. If they
        // don't have: it is a RUNES IMPLEMENTATION ERROR
      }
      catch (IllegalAccessException noConstructor) {
        throw new Error(noConstructor.toString());
      }
      catch (InstantiationException wrongConstructor) {
        throw new Error(wrongConstructor.toString());
      }
      return false;
    }
    //else if ( formalParameterType.isAssignableFrom(actualParameterType))  //BEFORE - BUGFIX - different class loaders (Tomcat)
    //  return true;                            //BEFORE - BUGFIX - different class loaders (Tomcat)
    //else                                  //BEFORE - BUGFIX - different class loaders (Tomcat)
    //  return false;                            //BEFORE - BUGFIX - different class loaders (Tomcat)

    else {                                  //PLUS - BUGFIX - different class loaders (Tomcat)
      Class actualFormalParameterType = formalParameterType;        //PLUS - BUGFIX
      try {                                //PLUS - BUGFIX
        actualFormalParameterType = actualParameterType.getClassLoader().loadClass(formalParameterType.getName())//PLUS - BUGFIX
        if (actualFormalParameterType == null) actualFormalParameterType = formalParameterType;            //PLUS - BUGFIX
      } catch(Exception e) { }                                            //PLUS - BUGFIX
      boolean result = (actualFormalParameterType.isAssignableFrom(actualParameterType));                //PLUS - BUGFIX
      //System.err.println("SignaturePattern - isAssignable - Class  => " + formalParameterType + " is assignable from " + actualFormalParameterType + ":" + result);
      return result;                                                  //PLUS - BUGFIX
    }

  }


  protected void initFromMethod(Class methodClass, String adviceName, Class wildcardClass,Class htop) {

    this.wildcardClass = wildcardClass;
    initAdviceMethod(methodClass,adviceName,htop);
    signature = methodObj.getParameterTypes();
    initSignatureCathegory();
  }


  private void initAdviceMethod(Class methodClass,String adviceName,Class hierarchyTop) {
    int      ambigousCnt = 0;
    Method   mObj = null;
    Class    crtClass = methodClass;

    // look up a method with the name 'adviceName'; if such a method is found,
    while (crtClass != null &&
        !crtClass.equals(hierarchyTop) &&          // (e.g., crtClass != MethodCut)
        hierarchyTop.isAssignableFrom(crtClass) && // (e.g., crtClass subclass of MethodCut)
        mObj == null) {

      Method[] methods = crtClass.getDeclaredMethods();
      ambigousCnt = 0;

      // we have to select some method
      // try to match a method with such a name

      for (int i=0; i < methods.length; i++)
        if ( methods[i].getName().equals(adviceName)) {
          mObj = methods[i];
          ambigousCnt++;
        }

      crtClass=crtClass.getSuperclass();
    }

    if (mObj == null)
      throw new MissingInformationException("No advice action specified");
    if (ambigousCnt > 1)
      throw new MissingInformationException("Two advice methods detected. Ambigous advice specification");

    try  {
      mObj.setAccessible(true);
    }
    catch (SecurityException opaqueCrosscut) {
      // this is not very likely to ocurr
    }

    methodObj = mObj;
  }


  private void initSignatureCathegory() {
    Method m = methodObj;
    int optimization = SIGNATURE__ARBITRARY;
    Class[] adviceParamTypes = m.getParameterTypes();

    if (adviceParamTypes.length == 0) {
      signatureCathegory = SIGNATURE__EMPTY;
      return;
    }

    // figure out whether the receiver is a wildcard
    if (ANY.class.isAssignableFrom(adviceParamTypes[0]))
      optimization |= WILDCARD_1;
    else
      optimization |= CONCRETE_1;


    // figure out whether *all* parameters are wildcard
    boolean restIsWildcard = true;
    boolean restIsConcrete = true;
    for (int i = 1; i < adviceParamTypes.length; i++) {
      if (Wildcard.class.isAssignableFrom(adviceParamTypes[i]))
        restIsConcrete = false;
      else
        restIsWildcard = false;
    }

    // and update the result
    if (restIsWildcard && adviceParamTypes.length == 2 &&  adviceParamTypes[1].equals(wildcardClass))
      optimization |= WILDCARD_2;
    if (restIsConcrete)
      optimization |= CONCRETE_2;

    signatureCathegory = optimization;
  }


  protected boolean isAssignable(Class[] actualParameterType, Class formalParameterType) {
    if (Wildcard.class.isAssignableFrom(formalParameterType)) {
      try  {
        if (((Wildcard)formalParameterType.newInstance()).isAssignableFrom(actualParameterType))
          return true;
      }
      catch (IllegalAccessException noConstructor) {
        throw new Error(noConstructor.toString());
      }
      catch (InstantiationException wrongConstructor) {
        throw new Error(wrongConstructor.toString());
      }
      return false;
    }
    else
      return false;
  }

}
TOP

Related Classes of ch.ethz.prose.crosscut.SignaturePattern

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.