Package ch.ethz.prose.crosscut

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

//
//  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 Angela Nicoara. Portions
//  created by Angela Nicoara are Copyright (C) 2004 Angela Nicoara.
//  All Rights Reserved.
//
//  Contributor(s):
//  $Id: ConstructorCut.java,v 1.2 2008/11/18 11:36:07 anicoara Exp $
//  =====================================================================
//

package ch.ethz.prose.crosscut;

// used packages
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import ch.ethz.jvmai.JoinPoint;
import ch.ethz.prose.engine.JoinPointRequest;
import ch.ethz.jvmai.ConstructorJoinPoint;
import ch.ethz.prose.filter.ANDingPointCutter;
import ch.ethz.prose.filter.PointCutter;

/**
* Class ConstructorCut represents a crosscut. Such a crosscut
* defines a pattern (for matching specific join-points) and a method
* to be executed. Users must subclass <code>ConstructorCut</code>.
* There are two main modalities for subclassing:
* <h3>The typical way (normal user)</h3>
* Define exactly one method (e.g., <code>METHOD_ARGS(Bar thisO,Baz param1)</code>).
* This method is both the advice action to be executed and it defines
* a pattern.  Thus, just entries and exits of invocations of the form
* <code>Bar.*(Baz)</code> will be considered join-points of this
* crosscut.
* <p>
* This crosscut defines a crosscut for all entry-
* points of the matched constructor.
* <p>
* Use <code>pointCutter</code> to further restrict the number of
* points were advices are executed.
*
* @version  $Revision: 1.2 $
* @author  Angela Nicoara
* @author  Gerald Linhofer
*/
public abstract class ConstructorCut extends AbstractCrosscut implements java.io.Serializable {

  ///////////////////////////////////////////////////////////////////////////////////////////
  ///  THE CROSSCUT: ADVICE METHOD + ADVICE EXECUTION put together
  ///////////////////////////////////////////////////////////////////////////////////////////

  /**
   * Override the value of this variable if you want to change the
   * name of the method wildcards.
   */
  public void METHOD_ARGS(){}

  /**
   * If you have more than one method in this class, determining the
   * name of the advice method will use the value of this method. This
   * variable should then be initialized with the name of the method
   * you want to call as advice method.
   */

  transient boolean   isInitialized = false;
  transient ConstructorCutSpecializer ccutSpecializer = null;
  transient ConstructorCutSignaturePattern adviceSignature = null;
  String toStringSignature;

  private void initState() throws MissingInformationException {
    if (isInitialized) return;
    isInitialized=true;

    adviceSignature = new ConstructorCutSignaturePattern(this);
    ccutSpecializer = new ConstructorCutSpecializer(adviceSignature);

    toStringSignature = adviceSignature.toString();
  }

  /**
   * We want people to subclass this class.
   * Create a <code>ConstructorCut</code> object.
   *
   * @throws MissingInformationException this crosscut does
   * not define an advice method / or does not override methodAdvice.
   */
  protected ConstructorCut() throws MissingInformationException {
    initState();
  }

  public void insertionAction(boolean beforeInsertion) {
    super.insertionAction(beforeInsertion);

    // we might provide an initstate here for the case
    // this crosscut is deserialized and the
    // static initializer or the constructor are not properly
    // called
    initState();
  }

  /**
   * Return all potential classes to which this crosscut applies:
   * To all loaded classes, apply the <code>isPotentialCrosscutClass</code>
   * selector.
   */
  protected Class[] potentialCrosscutClasses() throws MissingInformationException {
    // get exactly one method declared in this class with more
    // than one argument

    Class[] result = new Class[]{};
    List searchList = new Vector(Arrays.asList(super.potentialCrosscutClasses()));

    // if the receiver class is not a wildcard, we add the
    // receiver class to the potential crosscut classes
    Class   receiverClass=adviceSignature.getReceiverType();
    if (receiverClass!= null && !Wildcard.class.isAssignableFrom(receiverClass) &&
        !searchList.contains(receiverClass))
      searchList.add(receiverClass);
    Vector resultList = new Vector();

    // then we search in the search list
    Iterator i = searchList.iterator();
    while (i.hasNext()) {
      Class crtCls=(Class)i.next();
      if (isPotentialCrosscutClass(crtCls))
        resultList.add(crtCls);
    }

    // and return the corresponding array
    result = (Class[])resultList.toArray(new Class[]{});
    return result;
  }

  /** Return true only if
   * <ol>
   * <li> This crosscut redefines the <code>methodAdvice</code>  method, <em>OR</em>
   * <li> if this crosscut defines an advice, and the corresponding <code>UserDefinedMCSignature</code>
   * matches the target class <code>crtCls</code>.
   * </ol>
   */
  protected boolean isPotentialCrosscutClass(Class crtCls) throws MissingInformationException {
    return adviceSignature.matchesTarget(crtCls);
  }

  /**
   * Retrieve those constructors belonging to <code>theClass</code>
   * which have the same signature as the advice methods. Use the
   * <code>UserDefinedMCSignature</code> object (<code>adviceSignature</code>)
   * to determine which constructors defined in class <code>theClass</code>
   * match the pattern.
   * (if wildcards are present, they use them to match more constructors in <code>theClass</code>)
   * <p>
   * Return a list of <code>JoinPointRequest</code> objects corresponding
   * to all locations of the matched constructors.
   * <p>
   * <em>This implementation will return just Constructor-Entry locations.</em>.
   */
  protected CrosscutRequest doCreateRequest(Class theClass) {

    //1.  retrieve those constructors TCM belonging to class theClass
    //    for which the following holds:
    //    if M[i] is not a wildcard, M[i] is assignable from TCM[i]
    //    if M[i] is a wildcard, TCM[i] matches M[i] or
    //    TCM[i..TCM.lenth] matches M[i]
    CrosscutRequest result = new CrosscutRequest();

    //take the constructors declared in the given class only (ignore
    //inherited constructors!)
    //A possible problem might occur because of the access control
    Constructor[] constructorArray = null;

    try { constructorArray = theClass.getDeclaredConstructors(); }
    catch (NoClassDefFoundError e) {
      return result;
    }

    for(int i=0; i<constructorArray.length; i++) {
      Class[] params = constructorArray[i].getParameterTypes();
      JoinPointRequest crtRequest;

      crtRequest = requestFactory.createJoinPointRequest(ConstructorJoinPoint.KIND,constructorArray[i]);
      if (ccutSpecializer.isSpecialRequest(crtRequest))
        result.add(crtRequest);
    }

    return result;
  }

  /**
   * Create an action to execute the advice which matched the
   *  constructor in which the location of <code>jpe</code>  resides.
   *
   * @exception InvocationTargetException some error occured inside
   * the advice method.
   * @exception IllegalAccessException the advice method was not public
   */
  public void joinPointAction(ConstructorJoinPoint ev) throws IllegalAccessException, InvocationTargetException {
    constructorAdvice(ev);
  }

  //  /**
  //   * Create an action to execute the advice which matched the
  //   *  method in which the location of <code>jpe</code>  resides.
  //   *
  //   * @exception InvocationTargetException some error occured inside
  //   * the advice method.
  //   * @exception IllegalAccessException the advice method was not public
  //   */
  //  public void joinPointAction(MethodExitJoinPoint ev) throws IllegalAccessException, InvocationTargetException
  //    {
  //      // call advice
  //      methodAdvice(ev);
  //    }
  //
  //
  /**
   * If 'constructorAdvice' has been redefined, then we will deal with a
   * 'DefaultMcutSignature'. But in THAT case, this method
   * will be never executed.
   *
   */
  private void constructorAdvice(JoinPoint joinPoint)
  throws InvocationTargetException, IllegalAccessException {

    // create the appropriate 'adviceExecutionObject';
    CcutAdvice toRun= null;
    switch(adviceSignature.signatureCathegory) {
    case SignaturePattern.SIGNATURE__EMPTY:
      METHOD_ARGS();
      break;
    case SignaturePattern.SIGNATURE__CONCRETE__CONCRETE:
      toRun = new ConcreteConcreteCcutAdvice(this, joinPoint,(ConstructorCutSignaturePattern)adviceSignature);
      break;
    case SignaturePattern.SIGNATURE__WILDCARD__CONCRETE:
      toRun = new WildcardConcreteCcutAdvice(this, joinPoint,(ConstructorCutSignaturePattern)adviceSignature);
      break;
    case SignaturePattern.SIGNATURE__WILDCARD__WILDCARD:
      toRun = new WildcardWildcardCcutAdvice(this, joinPoint,(ConstructorCutSignaturePattern)adviceSignature);
      break;
    case SignaturePattern.SIGNATURE__CONCRETE__WILDCARD:
      toRun = new ConcreteWildcardCcutAdvice(this, joinPoint,(ConstructorCutSignaturePattern)adviceSignature);
      break;
    default:
      toRun = new DefaultCcutAdvice(this, joinPoint,(ConstructorCutSignaturePattern)adviceSignature);
    break;
    }

    toRun.execute();
  }

  public PointCutter equivalentSpecializer() {
    initState();
    if (getSpecializer() == null)
      return ccutSpecializer;
    else
      return new ANDingPointCutter(ccutSpecializer,(PointCutter)getSpecializer());
  }

  /**
   * Get advice method, i.e. <code>METHOD_ARGS(...)</code>. The advice
   * method is used by the full code weaver.
   *
   * @return advice method
   */
  public Method getMethod() {
    return adviceSignature.methodObj;
  }

  public String toString() {
    return " Crosscut: 'ConstructorCut' \n" +
    " Advice:" +  toStringSignature +  "\n" +
    " PointCutter: " +  getSpecializer() + "\n";
  }
}
TOP

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

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.