ConstructorCut.java :  » Byte-Code » PROSE » ch » ethz » prose » crosscut » Java Open Source

Java Open Source » Byte Code » PROSE 
PROSE » ch » ethz » prose » crosscut » ConstructorCut.java
//
//  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 Angela Nicoara and Gerald Linhofer. 
//  All Rights Reserved.
//
//  Contributor(s):
//  $Id$
//  =====================================================================
//
// (history at end)
//

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 tipical 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$
 * @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";
  }
}


//======================================================================
//
// $Log$
//
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.