package org.aspectj.weaver.patterns;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.CompressingDataOutputStream;
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.World;
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 ;
private final String enclosingPointcutHint;
public Pointcut residueSource;
int baseArgsCount;
public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) {
this.testMethod = testMethod;
this.extraParameterFlags = extraParameterFlags;
this.pointcutKind = IF;
this.enclosingPointcutHint = null;
}
public IfPointcut(String enclosingPointcutHint) {
this.pointcutKind = IF;
this.enclosingPointcutHint = enclosingPointcutHint;
this.testMethod = null;
this.extraParameterFlags = -1;
}
@Override
public int couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS_BITS;
}
@Override
public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE;
}
@Override
protected FuzzyBoolean matchInternal(Shadow shadow) {
if ((extraParameterFlags & Advice.ConstantReference) != 0) {
if ((extraParameterFlags & Advice.ConstantValue) != 0) {
return FuzzyBoolean.YES;
} else {
return FuzzyBoolean.NO;
}
}
return FuzzyBoolean.MAYBE;
}
public boolean alwaysFalse() {
return false;
}
public boolean alwaysTrue() {
return false;
}
public Pointcut getResidueSource() {
return residueSource;
}
@Override
public void write(CompressingDataOutputStream s) throws IOException {
s.writeByte(Pointcut.IF);
s.writeBoolean(testMethod != null);
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) {
resolvedTestMethod = ResolvedMemberImpl.readResolvedMember(s, context);
}
IfPointcut ret = new IfPointcut(resolvedTestMethod, s.readByte());
ret.readLocation(context, s);
return ret;
}
@Override
public void resolveBindings(IScope scope, Bindings bindings) {
}
@Override
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);
}
@Override
public int hashCode() {
int result = 17;
result = 37 * result + testMethod.hashCode();
return result;
}
@Override
public String toString() {
if (extraParameterFlags < 0) {
return "if()";
} else {
return "if(" + testMethod + ")";
}
}
private boolean findingResidue = false;
private int ifLastMatchedShadowId;
private Test ifLastMatchedShadowResidue;
@Override
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (findingResidue) {
return Literal.TRUE;
}
findingResidue = true;
try {
if (shadow.shadowId == ifLastMatchedShadowId) {
return ifLastMatchedShadowResidue;
}
Test ret = Literal.TRUE;
List<Var> args = new ArrayList<Var>();
if (extraParameterFlags >= 0) {
if ((extraParameterFlags & Advice.ConstantReference) != 0) {
if ((extraParameterFlags & Advice.ConstantValue) != 0) {
ret = Literal.TRUE;
ifLastMatchedShadowId = shadow.shadowId;
ifLastMatchedShadowResidue = ret;
return ret;
} else {
ret = Literal.FALSE;
ifLastMatchedShadowId = shadow.shadowId;
ifLastMatchedShadowResidue = ret;
return ret;
}
}
if (baseArgsCount > 0) {
ExposedState myState = new ExposedState(baseArgsCount);
myState.setConcreteAspect(state.getConcreteAspect());
residueSource.findResidue(shadow, myState);
UnresolvedType[] pTypes = (testMethod == null ? null : testMethod.getParameterTypes());
if (pTypes != null && baseArgsCount > pTypes.length) {
throw new BCException("Unexpected problem with testMethod " + testMethod + ": expecting " + baseArgsCount
+ " arguments");
}
for (int i = 0; i < baseArgsCount; i++) {
Var v = myState.get(i);
if (v == null) {
continue;
}
args.add(v);
ret = Test.makeAnd(ret, Test.makeInstanceof(v, pTypes[i].resolve(shadow.getIWorld())));
}
}
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());
}
if ((extraParameterFlags & Advice.ThisAspectInstance) != 0) {
args.add(shadow.getThisAspectInstanceVar(state.getConcreteAspect()));
}
} else {
int currentStateIndex = 0;
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 {
if (state.size() == 0 || currentStateIndex > state.size()) {
String[] paramNames = testMethod.getParameterNames();
StringBuffer errorParameter = new StringBuffer();
if (paramNames != null) {
errorParameter.append(testMethod.getParameterTypes()[i].getName()).append(" ");
errorParameter.append(paramNames[i]);
shadow.getIWorld()
.getMessageHandler()
.handleMessage(
MessageUtil.error("Missing binding for if() pointcut method. Parameter " + (i + 1)
+ "(" + errorParameter.toString()
+ ") must be bound - even in reference pointcuts (compiler limitation)",
testMethod.getSourceLocation()));
} else {
shadow.getIWorld()
.getMessageHandler()
.handleMessage(
MessageUtil.error("Missing binding for if() pointcut method. Parameter " + (i + 1)
+ " must be bound - even in reference pointcuts (compiler limitation)",
testMethod.getSourceLocation()));
}
return Literal.TRUE;
}
Var v = state.get(currentStateIndex++);
while (v == null && currentStateIndex < state.size()) {
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()])));
ifLastMatchedShadowId = shadow.shadowId;
ifLastMatchedShadowResidue = ret;
return ret;
} finally {
findingResidue = false;
}
}
@Override
protected boolean shouldCopyLocationForConcretize() {
return false;
}
private IfPointcut partiallyConcretized = null;
@Override
public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
if (isDeclare(bindings.getEnclosingAdvice())) {
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) {
ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
if (def != null) {
ResolvedType aspect = inAspect.getWorld().resolve(def.getDeclaringType());
for (Iterator memberIter = aspect.getMethods(true, true); 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;
if (bindings.directlyInAdvice() && bindings.getEnclosingAdvice() == null) {
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;
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;
}
@Override
public Pointcut parameterizeWith(Map typeVariableMap, World w) {
return this;
}
public static IfPointcut makeIfFalsePointcut(State state) {
IfPointcut ret = new IfFalsePointcut();
ret.state = state;
return ret;
}
@Override
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;
}
@Override
public int couldMatchKinds() {
return Shadow.NO_SHADOW_KINDS_BITS;
}
@Override
public boolean alwaysFalse() {
return true;
}
@Override
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Literal.FALSE;
}
@Override
public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.NO;
}
@Override
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.NO;
}
@Override
public void resolveBindings(IScope scope, Bindings bindings) {
}
@Override
public void postRead(ResolvedType enclosingType) {
}
@Override
public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
if (isDeclare(bindings.getEnclosingAdvice())) {
inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
bindings.getEnclosingAdvice().getSourceLocation(), null);
return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
}
return makeIfFalsePointcut(state);
}
@Override
public void write(CompressingDataOutputStream s) throws IOException {
s.writeByte(Pointcut.IF_FALSE);
}
@Override
public int hashCode() {
int result = 17;
return result;
}
@Override
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;
}
@Override
public boolean alwaysTrue() {
return true;
}
@Override
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Literal.TRUE;
}
@Override
public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.YES;
}
@Override
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.YES;
}
@Override
public void resolveBindings(IScope scope, Bindings bindings) {
}
@Override
public void postRead(ResolvedType enclosingType) {
}
@Override
public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
if (isDeclare(bindings.getEnclosingAdvice())) {
inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
bindings.getEnclosingAdvice().getSourceLocation(), null);
return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
}
return makeIfTruePointcut(state);
}
@Override
public void write(CompressingDataOutputStream s) throws IOException {
s.writeByte(IF_TRUE);
}
@Override
public int hashCode() {
int result = 37;
return result;
}
@Override
public String toString() {
return "if(true)";
}
}
public void setAlways(boolean matches) {
extraParameterFlags |= Advice.ConstantReference;
if (matches) {
extraParameterFlags |= Advice.ConstantValue;
}
}
}