Package org.aspectj.weaver.patterns

Source Code of org.aspectj.weaver.patterns.IfPointcut$IfTruePointcut

/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
*     PARC                 initial implementation
*     Alexandre Vasseur    if() implementation for @AJ style
* ******************************************************************/
package org.aspectj.weaver.patterns;

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.ast.Expr;
import org.aspectj.weaver.ast.Literal;
import org.aspectj.weaver.ast.Test;
import org.aspectj.weaver.ast.Var;

public class IfPointcut extends Pointcut {
  public ResolvedMember testMethod;
  public int extraParameterFlags;

    /**
     * A token source dump that looks like a pointcut (but is NOT parseable at all - just here to help debugging etc)
     */
    private String enclosingPointcutHint;

  public Pointcut residueSource;
  int baseArgsCount;
 
  //XXX some way to compute args

  public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) {
    this.testMethod = testMethod;
    this.extraParameterFlags = extraParameterFlags;
    this.pointcutKind = IF;
        this.enclosingPointcutHint = null;
  }

    /**
     * No-arg constructor for @AJ style, where the if() body is actually the @Pointcut annotated method
     */
    public IfPointcut(String enclosingPointcutHint) {
        this.pointcutKind = IF;
        this.enclosingPointcutHint = enclosingPointcutHint;
        this.testMethod = null;// resolved during concretize
        this.extraParameterFlags = -1;//allows to keep track of the @Aj style
    }

  public Set couldMatchKinds() {
    return Shadow.ALL_SHADOW_KINDS;
  }

  public FuzzyBoolean fastMatch(FastMatchInfo type) {
    return FuzzyBoolean.MAYBE;
  }
     
  protected FuzzyBoolean matchInternal(Shadow shadow) {
    //??? this is not maximally efficient
    return FuzzyBoolean.MAYBE;
  }

  public boolean alwaysFalse() {
    return false;
  }
 
  public boolean alwaysTrue() {
    return false;
  }
 
  // enh 76055
  public Pointcut getResidueSource() {
    return residueSource;
  }
 
  public void write(DataOutputStream s) throws IOException {
    s.writeByte(Pointcut.IF);
    s.writeBoolean(testMethod != null)// do we have a test method?
    if (testMethod != null) testMethod.write(s);
    s.writeByte(extraParameterFlags);
    writeLocation(s);
  }
  public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
    boolean hasTestMethod = s.readBoolean();
    ResolvedMember resolvedTestMethod = null
    if (hasTestMethod) {  // should always have a test method unless @AJ style
      resolvedTestMethod = ResolvedMemberImpl.readResolvedMember(s, context);
    }
    IfPointcut ret = new IfPointcut(resolvedTestMethod, s.readByte());
    ret.readLocation(context, s);
    return ret;
  }

  public void resolveBindings(IScope scope, Bindings bindings) {
    //??? all we need is good error messages in here in cflow contexts
  }
   
  public boolean equals(Object other) {
    if (!(other instanceof IfPointcut)) return false;
    IfPointcut o = (IfPointcut)other;
    if (o.testMethod==null) return (this.testMethod==null);
    return o.testMethod.equals(this.testMethod);
  }

    public int hashCode() {
        int result = 17;
        result = 37*result + testMethod.hashCode();
        return result;
    }

    public String toString() {
        if (extraParameterFlags < 0) {
            //@AJ style
            return "if()";
        } else {
        return "if(" + testMethod + ")";//FIXME AV - bad, this makes it unparsable. Perhaps we can use if() for code style behind the scene!
        }
  }

  //??? The implementation of name binding and type checking in if PCDs is very convoluted
  //    There has to be a better way...
    private boolean findingResidue = false;
 
  // Similar to lastMatchedShadowId - but only for if PCDs.
  private int ifLastMatchedShadowId;
  private Test ifLastMatchedShadowResidue;
 
  /**
   * At each shadow that matched, the residue can be different.
   */
  protected Test findResidueInternal(Shadow shadow, ExposedState state) {
    if (findingResidue) return Literal.TRUE;
    findingResidue = true;
    try {

      // Have we already been asked this question?
      if (shadow.shadowId == ifLastMatchedShadowId) return ifLastMatchedShadowResidue;
     
      Test ret = Literal.TRUE;
      List args = new ArrayList();
     
          // code style
            if (extraParameterFlags >= 0) {
                // If there are no args to sort out, don't bother with the recursive call
                if (baseArgsCount > 0) {
                    ExposedState myState = new ExposedState(baseArgsCount);
                    //??? we throw out the test that comes from this walk.  All we want here
                    //    is bindings for the arguments
                    residueSource.findResidue(shadow, myState);


                    // pr118149
                    // It is possible for vars in myState (which would normally be set
                    // in the call to residueSource.findResidue) to not be set (be null)
                    // in an Or pointcut with if expressions in both branches, and where
                    // one branch is known statically to not match. In this situation we
                    // simply return Test.
                    for (int i=0; i < baseArgsCount; i++) {
                        Var v = myState.get(i);
                        if (v == null) continue// pr118149
                        args.add(v);
                        ret = Test.makeAnd(ret,
                            Test.makeInstanceof(v,
                                testMethod.getParameterTypes()[i].resolve(shadow.getIWorld())));
                    }
                }

                // handle thisJoinPoint parameters
                if ((extraParameterFlags & Advice.ThisJoinPoint) != 0) {
                    args.add(shadow.getThisJoinPointVar());
                }

                if ((extraParameterFlags & Advice.ThisJoinPointStaticPart) != 0) {
                    args.add(shadow.getThisJoinPointStaticPartVar());
                }

                if ((extraParameterFlags & Advice.ThisEnclosingJoinPointStaticPart) != 0) {
                    args.add(shadow.getThisEnclosingJoinPointStaticPartVar());
                }
            } else {
                // @style is slightly different
                int currentStateIndex = 0;
                //FIXME AV - "args(jp)" test(jp, thejp) will fail here
                for (int i = 0; i < testMethod.getParameterTypes().length; i++) {
                    String argSignature = testMethod.getParameterTypes()[i].getSignature();
                    if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)) {
                        args.add(shadow.getThisJoinPointVar());
                    } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)) {
                        args.add(shadow.getThisJoinPointVar());
                    } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)) {
                        args.add(shadow.getThisJoinPointStaticPartVar());
                    } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) {
                        args.add(shadow.getThisEnclosingJoinPointStaticPartVar());
                    } else {
                        // we don't use i as JoinPoint.* can be anywhere in the signature in @style
                        Var v = state.get(currentStateIndex++);
                        args.add(v);
                        ret = Test.makeAnd(ret,
                            Test.makeInstanceof(v,
                                testMethod.getParameterTypes()[i].resolve(shadow.getIWorld())));
                    }
                }
            }

          ret = Test.makeAnd(ret, Test.makeCall(testMethod, (Expr[])args.toArray(new Expr[args.size()])));

      // Remember...
      ifLastMatchedShadowId = shadow.shadowId;
      ifLastMatchedShadowResidue = ret;
      return ret;
    } finally {
      findingResidue = false;
    }
  }
 

  // amc - the only reason this override seems to be here is to stop the copy, but
  // that can be prevented by overriding shouldCopyLocationForConcretization,
  // allowing me to make the method final in Pointcut.
//  public Pointcut concretize(ResolvedType inAspect, IntMap bindings) {
//    return this.concretize1(inAspect, bindings);
//  }
 
  protected boolean shouldCopyLocationForConcretize() {
    return false;
  }
 
  private IfPointcut partiallyConcretized = null;
  public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType,  IntMap bindings) {
    //System.err.println("concretize: " + this + " already: " + partiallyConcretized);
   
    if (isDeclare(bindings.getEnclosingAdvice())) {
      // Enforce rule about which designators are supported in declare
      inAspect.getWorld().showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
          bindings.getEnclosingAdvice().getSourceLocation(),
          null);
      return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
    }

    if (partiallyConcretized != null) {
      return partiallyConcretized;
    }

        final IfPointcut ret;
        if (extraParameterFlags < 0 && testMethod == null) {
            // @AJ style, we need to find the testMethod in the aspect defining the "if()" enclosing pointcut
            ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
            if (def != null) {
                ResolvedType aspect = inAspect.getWorld().resolve(def.getDeclaringType());
                for (Iterator memberIter = aspect.getMethods(); memberIter.hasNext();) {
                    ResolvedMember method = (ResolvedMember) memberIter.next();
                    if (def.getName().equals(method.getName())
                        && def.getParameterTypes().length == method.getParameterTypes().length) {
                        boolean sameSig = true;
                        for (int j = 0; j < method.getParameterTypes().length; j++) {
                            UnresolvedType argJ = method.getParameterTypes()[j];
                            if (!argJ.equals(def.getParameterTypes()[j])) {
                                sameSig = false;
                                break;
                            }
                        }
                        if (sameSig) {
                            testMethod = method;
                            break;
                        }
                    }
                }
                if (testMethod == null) {
                    inAspect.getWorld().showMessage(
                            IMessage.ERROR,
                            "Cannot find if() body from '" + def.toString() + "' for '" + enclosingPointcutHint + "'",
                            this.getSourceLocation(),
                            null
                    );
                    return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
                }
            } else {
                testMethod = inAspect.getWorld().resolve(bindings.getAdviceSignature());
            }
            ret = new IfPointcut(enclosingPointcutHint);
            ret.testMethod = testMethod;
        } else {
            ret = new IfPointcut(testMethod, extraParameterFlags);
        }
        ret.copyLocationFrom(this);
        partiallyConcretized = ret;

    // It is possible to directly code your pointcut expression in a per clause
    // rather than defining a pointcut declaration and referencing it in your
    // per clause.  If you do this, we have problems (bug #62458).  For now,
    // let's police that you are trying to code a pointcut in a per clause and
    // put out a compiler error.
    if (bindings.directlyInAdvice() && bindings.getEnclosingAdvice()==null) {
      // Assumption: if() is in a per clause if we say we are directly in advice
      // but we have no enclosing advice.
      inAspect.getWorld().showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.IF_IN_PERCLAUSE),
          this.getSourceLocation(),null);
      return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
    }
   
    if (bindings.directlyInAdvice()) {
      ShadowMunger advice = bindings.getEnclosingAdvice();
      if (advice instanceof Advice) {
        ret.baseArgsCount = ((Advice)advice).getBaseParameterCount();
      } else {
        ret.baseArgsCount = 0;
      }
      ret.residueSource = advice.getPointcut().concretize(inAspect, inAspect, ret.baseArgsCount, advice);
    } else {
      ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
      if (def == CflowPointcut.CFLOW_MARKER) {
        inAspect.getWorld().showMessage(IMessage.ERROR,
            WeaverMessages.format(WeaverMessages.IF_LEXICALLY_IN_CFLOW),
            getSourceLocation(), null);
        return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
      }
      ret.baseArgsCount = def.getParameterTypes().length;

            // for @style, we have implicit binding for JoinPoint.* things
            //FIXME AV - will lead to failure for "args(jp)" test(jp, thejp) / see args() implementation
            if (ret.extraParameterFlags < 0) {
                ret.baseArgsCount = 0;
                for (int i = 0; i < testMethod.getParameterTypes().length; i++) {
                    String argSignature = testMethod.getParameterTypes()[i].getSignature();
                    if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)
                        || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)
                        || AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)
                        || AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) {
                        ;
                    } else {
                        ret.baseArgsCount++;
                    }
                }
            }

      IntMap newBindings = IntMap.idMap(ret.baseArgsCount);
      newBindings.copyContext(bindings);
      ret.residueSource = def.getPointcut().concretize(inAspect, declaringType, newBindings);
    }
   
    return ret;
  }

  // we can't touch "if" methods
  public Pointcut parameterizeWith(Map typeVariableMap) {
    return this;
  }
 
//  public static Pointcut MatchesNothing = new MatchesNothingPointcut();
//  ??? there could possibly be some good optimizations to be done at this point
  public static IfPointcut makeIfFalsePointcut(State state) {
    IfPointcut ret = new IfFalsePointcut();
    ret.state = state;
    return ret;
  }

    public Object accept(PatternNodeVisitor visitor, Object data) {
        return visitor.visit(this, data);
    }

  public static class IfFalsePointcut extends IfPointcut {
   
    public IfFalsePointcut() {
      super(null,0);
            this.pointcutKind = Pointcut.IF_FALSE;
    }
   
    public Set couldMatchKinds() {
      return Collections.EMPTY_SET;
    }
   
    public boolean alwaysFalse() {
      return true;
    }
   
    protected Test findResidueInternal(Shadow shadow, ExposedState state) {
      return Literal.FALSE; // can only get here if an earlier error occurred
    }

    public FuzzyBoolean fastMatch(FastMatchInfo type) {
      return FuzzyBoolean.NO;
    }
   
    protected FuzzyBoolean matchInternal(Shadow shadow) {
      return FuzzyBoolean.NO;
    }
   
    public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
      return FuzzyBoolean.NO;
    }

    public void resolveBindings(IScope scope, Bindings bindings) {
    }
   
    public void postRead(ResolvedType enclosingType) {
    }

    public Pointcut concretize1(
      ResolvedType inAspect,
      ResolvedType declaringType,
      IntMap bindings) {
      if (isDeclare(bindings.getEnclosingAdvice())) {
        // Enforce rule about which designators are supported in declare
        inAspect.getWorld().showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
          bindings.getEnclosingAdvice().getSourceLocation(),
          null);
        return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
      }
      return makeIfFalsePointcut(state);
    }


    public void write(DataOutputStream s) throws IOException {
      s.writeByte(Pointcut.IF_FALSE);
    }
   
      public int hashCode() {
          int result = 17;
          return result;
      }
   
      public String toString() {
      return "if(false)";
   
  }

  public static IfPointcut makeIfTruePointcut(State state) {
    IfPointcut ret = new IfTruePointcut();
    ret.state = state;
    return ret;
  }

  public static class IfTruePointcut extends IfPointcut {
     
    public IfTruePointcut() {
      super(null,0);
            this.pointcutKind = Pointcut.IF_TRUE;
    }

    public boolean alwaysTrue() {
      return true;
    }
   
    protected Test findResidueInternal(Shadow shadow, ExposedState state) {
      return Literal.TRUE; // can only get here if an earlier error occurred
    }

    public FuzzyBoolean fastMatch(FastMatchInfo type) {
      return FuzzyBoolean.YES;
    }
   
    protected FuzzyBoolean matchInternal(Shadow shadow) {
      return FuzzyBoolean.YES;
    }
   
    public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
      return FuzzyBoolean.YES;
    }

    public void resolveBindings(IScope scope, Bindings bindings) {
    }
   
    public void postRead(ResolvedType enclosingType) {
    }

    public Pointcut concretize1(
      ResolvedType inAspect,
      ResolvedType declaringType,
      IntMap bindings) {
      if (isDeclare(bindings.getEnclosingAdvice())) {
        // Enforce rule about which designators are supported in declare
        inAspect.getWorld().showMessage(IMessage.ERROR,
            WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
            bindings.getEnclosingAdvice().getSourceLocation(),
            null);
        return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
      }
      return makeIfTruePointcut(state);
    }


    public void write(DataOutputStream s) throws IOException {
      s.writeByte(IF_TRUE);
    }
   
      public int hashCode() {
          int result = 37;
          return result;
      }
   
      public String toString() {
      return "if(true)";
   
  }

}

TOP

Related Classes of org.aspectj.weaver.patterns.IfPointcut$IfTruePointcut

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.