Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* *******************************************************************
* Copyright (c) 2004 IBM Corporation.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* ******************************************************************/
package org.aspectj.weaver.patterns;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.patterns.Pointcut.MatchesNothingPointcut;
/**
* @author colyer
*
* Performs term rewriting for pointcut expressions.
*
*/
public class PointcutRewriter {
private static final boolean WATCH_PROGRESS = false;
/**
* Set forcerewrite if you want to override the checking for something already in DNF (useful for
* some testing)
* Repeated processing of something already in DNF is expensive (it ends up being done for
* every pointcut on every incremental compile) - so let's not do it if we don't have to.
* See pr113257
*/
public Pointcut rewrite(Pointcut pc,boolean forceRewrite) {
Pointcut result = pc;//checkPC(result);
if (forceRewrite || !isDNF(pc)) {
if (WATCH_PROGRESS) System.out.println("Initial pointcut is ==> " + format(pc));
result = distributeNot(result);//checkPC(result);
if (WATCH_PROGRESS) System.out.println("Distributing NOT gives ==> " + format(result));
result = pullUpDisjunctions(result);//checkPC(result);
if (WATCH_PROGRESS) System.out.println("Pull up disjunctions gives ==> " + format(result));
} else {
if (WATCH_PROGRESS) System.out.println("Not distributing NOTs or pulling up disjunctions, already DNF ==> "+format(pc));
}
result = simplifyAnds(result); //checkPC(result);
if (WATCH_PROGRESS) System.out.println("Simplifying ANDs gives ==> " + format(result));
result = removeNothings(result); //checkPC(result);
if (WATCH_PROGRESS) System.out.println("Removing nothings gives ==> " + format(result));
result = sortOrs(result); //checkPC(result);
if (WATCH_PROGRESS) System.out.println("Sorting ORs gives ==> " + format(result));
return result;
}
// /**
// * Checks pointcuts - used for debugging.
// * - this variant checks if the context has been lost, since
// * that can indicate an NPE will happen later reporting a message (pr162657).
// * Not finished, but helped locate the problem ;)
// */
// private void checkPC(Pointcut pc) {
// if (isNot(pc)) {
// NotPointcut npc = (NotPointcut)pc;
// checkPC(npc.getNegatedPointcut());
// if (npc.getSourceContext()==null) {
// System.out.println("Lost context for "+npc);
// throw new RuntimeException("Lost context");
// }
// } else if (isOr(pc)) {
// OrPointcut opc = (OrPointcut)pc;
// checkPC(opc.getLeft());
// checkPC(opc.getRight());
// if (opc.getSourceContext()==null) {
// System.out.println("Lost context for "+opc);
// throw new RuntimeException("Lost context");
// }
// } else if (isAnd(pc)) {
// AndPointcut apc = (AndPointcut)pc;
// checkPC(apc.getLeft());
// checkPC(apc.getRight());
// if (apc.getSourceContext()==null) {
// System.out.println("Lost context for "+apc);
// throw new RuntimeException("Lost context");
// }
// } else {
// if (pc.getSourceContext()==null) {
// System.out.println("Lost context for "+pc);
// throw new RuntimeException("Lost context");
// }
// }
// }
public Pointcut rewrite(Pointcut pc) {
return rewrite(pc,false);
}
/**
* Check if a pointcut is in DNF - if it is then it should be lots of 'ORs' up the
* top with 'ANDs' beneath them.
*/
private boolean isDNF(Pointcut pc) {
return isDNFHelper(pc,true);
}
/**
* Helper function for determining DNFness. Records when we have crossed the point of allowing ORs.
*/
private boolean isDNFHelper(Pointcut pc,boolean canStillHaveOrs) {
if (isAnd(pc)) {
AndPointcut ap = (AndPointcut)pc;
return isDNFHelper(ap.getLeft(),false) && isDNFHelper(ap.getRight(),false);
} else if (isOr(pc)) {
if (!canStillHaveOrs) return false;
OrPointcut op = (OrPointcut)pc;
return isDNFHelper(op.getLeft(),true) && isDNFHelper(op.getRight(),true);
} else if (isNot(pc)) {
return isDNFHelper(((NotPointcut)pc).getNegatedPointcut(),canStillHaveOrs);
} else {
return true;
}
}
/**
* Allows formatting of the output pointcut for debugging...
*/
public static String format(Pointcut p) {
String s = p.toString();
// Regex param needs '(' and '*' changing to '.'
// s = s.replaceAll("persingleton.pkg1.monitoring.ErrorMonitoring.","M");
// s = s.replaceAll("args.BindingTypePattern.java.lang.Throwable, 0.","Z");
// s = s.replaceAll("within.pkg1.monitoring.DoMonitorErrors+.","X");
// s=s.replaceAll("within.pkg1.monitoring....","Y");
// s=s.replaceAll("if.true.","N");
return s;
}
// !!X => X
// !(X && Y) => !X || !Y
// !(X || Y) => !X && !Y
private Pointcut distributeNot(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut) pc;
Pointcut notBody = distributeNot(npc.getNegatedPointcut());
if (isNot(notBody)) {
// !!X => X
return ((NotPointcut)notBody).getNegatedPointcut();
} else if (isAnd(notBody)) {
// !(X && Y) => !X || !Y
AndPointcut apc = (AndPointcut) notBody;
Pointcut newLeft = distributeNot(new NotPointcut(apc.getLeft(),npc.getStart()));
Pointcut newRight = distributeNot(new NotPointcut(apc.getRight(),npc.getStart()));
return new OrPointcut(newLeft,newRight);
} else if (isOr(notBody)) {
// !(X || Y) => !X && !Y
OrPointcut opc = (OrPointcut) notBody;
Pointcut newLeft = distributeNot(new NotPointcut(opc.getLeft(),npc.getStart()));
Pointcut newRight = distributeNot(new NotPointcut(opc.getRight(),npc.getStart()));
return new AndPointcut(newLeft,newRight);
} else {
return new NotPointcut(notBody,npc.getStart());
}
} else if (isAnd(pc)) {
AndPointcut apc = (AndPointcut) pc;
Pointcut left = distributeNot(apc.getLeft());
Pointcut right = distributeNot(apc.getRight());
return new AndPointcut(left,right);
} else if (isOr(pc)) {
OrPointcut opc = (OrPointcut) pc;
Pointcut left = distributeNot(opc.getLeft());
Pointcut right = distributeNot(opc.getRight());
return new OrPointcut(left,right);
} else {
return pc;
}
}
// A && (B || C) => (A && B) || (A && C)
// (A || B) && C => (A && C) || (B && C)
private Pointcut pullUpDisjunctions(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut)pc;
return new NotPointcut(pullUpDisjunctions(npc.getNegatedPointcut()));
} else if (isAnd(pc)) {
AndPointcut apc = (AndPointcut) pc;
// dive into left and right here...
Pointcut left = pullUpDisjunctions(apc.getLeft());
Pointcut right = pullUpDisjunctions(apc.getRight());
if (isOr(left) && !isOr(right)) {
// (A || B) && C => (A && C) || (B && C)
Pointcut leftLeft = ((OrPointcut)left).getLeft();
Pointcut leftRight = ((OrPointcut)left).getRight();
return pullUpDisjunctions(
new OrPointcut(
new AndPointcut(leftLeft,right),
new AndPointcut(leftRight,right))
);
} else if (isOr(right) && !isOr(left)) {
// A && (B || C) => (A && B) || (A && C)
Pointcut rightLeft = ((OrPointcut)right).getLeft();
Pointcut rightRight = ((OrPointcut)right).getRight();
return pullUpDisjunctions(
new OrPointcut(
new AndPointcut(left,rightLeft),
new AndPointcut(left,rightRight))
);
} else if (isOr(right) && isOr(left)) {
// (A || B) && (C || D) => (A && C) || (A && D) || (B && C) || (B && D)
Pointcut A = pullUpDisjunctions(((OrPointcut)left).getLeft());
Pointcut B = pullUpDisjunctions(((OrPointcut)left).getRight());
Pointcut C = pullUpDisjunctions(((OrPointcut)right).getLeft());
Pointcut D = pullUpDisjunctions(((OrPointcut)right).getRight());
Pointcut newLeft = new OrPointcut(
new AndPointcut(A,C),
new AndPointcut(A,D)
);
Pointcut newRight = new OrPointcut(
new AndPointcut(B,C),
new AndPointcut(B,D)
);
return pullUpDisjunctions(new OrPointcut(newLeft,newRight));
} else {
return new AndPointcut(left,right);
}
} else if (isOr(pc)){
OrPointcut opc = (OrPointcut) pc;
return new OrPointcut(pullUpDisjunctions(opc.getLeft()),
pullUpDisjunctions(opc.getRight()));
} else {
return pc;
}
}
/**
* Returns a NOTted form of the pointcut p - we cope with already NOTted pointcuts.
*/
public Pointcut not(Pointcut p) {
if (isNot(p)) {
return ((NotPointcut)p).getNegatedPointcut();
}
return new NotPointcut(p);
}
/**
* Passed an array of pointcuts, returns an AND tree with them in.
*/
public Pointcut createAndsFor(Pointcut[] ps) {
if (ps.length==1) return ps[0]; // dumb case
if (ps.length==2) { // recursion exit case
return new AndPointcut(ps[0],ps[1]);
}
// otherwise ...
Pointcut[] subset = new Pointcut[ps.length-1];
for (int i = 1; i < ps.length; i++) {
subset[i-1]=ps[i];
}
return new AndPointcut(ps[0],createAndsFor(subset));
}
// NOT: execution(* TP.*(..)) => within(TP) && execution(* *(..))
// since this breaks when the pattern matches an interface
// NOT: withincode(* TP.*(..)) => within(TP) && withincode(* *(..))
// since this is not correct when an aspect makes an ITD
// private Pointcut splitOutWithins(Pointcut pc) {
// if (isExecution(pc)) {
// KindedPointcut kpc = (KindedPointcut) pc;
// SignaturePattern sp = kpc.signature;
// TypePattern within = sp.getDeclaringType();
// if (isAnyType(within)) return pc;
// SignaturePattern simplified = removeDeclaringTypePattern(sp);
// return new AndPointcut(new WithinPointcut(within),
// new KindedPointcut(kpc.kind,simplified));
// } else if (isNot(pc)) {
// return new NotPointcut(splitOutWithins(((NotPointcut)pc).getNegatedPointcut()));
// } else if (isAnd(pc)) {
// AndPointcut apc = (AndPointcut) pc;
// return new AndPointcut(splitOutWithins(apc.getLeft()),
// splitOutWithins(apc.getRight()));
// } else if (isOr(pc)) {
// OrPointcut opc = (OrPointcut) pc;
// return new OrPointcut(splitOutWithins(opc.getLeft()),
// splitOutWithins(opc.getRight()));
// } else {
// return pc;
// }
// }
// private SignaturePattern removeDeclaringTypePattern(SignaturePattern sp) {
// return new SignaturePattern(
// sp.getKind(),
// sp.getModifiers(),
// sp.getReturnType(),
// TypePattern.ANY,
// sp.getName(),
// sp.getParameterTypes(),
// sp.getThrowsPattern(),
// sp.getAnnotationPattern()
// );
// }
// this finds the root of each && tree and then aggregates all of the branches
// into a sorted set:
// - duplicates are removed
// - A && !A is replaced by a matchesNothingPointcut
// - the kind(s) matched by the set are evaluated
// - elements are sorted by evaluation complexity
// - the result is written out with the least expensive branch leftmost
private Pointcut simplifyAnds(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut) pc;
Pointcut notBody = npc.getNegatedPointcut();
if (isNot(notBody)) {
// !!X => X
return simplifyAnds(((NotPointcut)notBody).getNegatedPointcut());
} else {
return new NotPointcut(simplifyAnds(npc.getNegatedPointcut()));
}
} else if (isOr(pc)) {
OrPointcut opc = (OrPointcut) pc;
return new OrPointcut(simplifyAnds(opc.getLeft()),simplifyAnds(opc.getRight()));
} else if (isAnd(pc)) {
return simplifyAnd((AndPointcut)pc);
} else {
return pc;
}
}
private Pointcut simplifyAnd(AndPointcut apc) {
SortedSet nodes = new TreeSet(new PointcutEvaluationExpenseComparator());
collectAndNodes(apc,nodes);
// look for A and !A, or IfFalse
for (Iterator iter = nodes.iterator(); iter.hasNext();) {
Pointcut element = (Pointcut) iter.next();
if (element instanceof NotPointcut) {
Pointcut body = ((NotPointcut)element).getNegatedPointcut();
if (nodes.contains(body)) return Pointcut.makeMatchesNothing(body.state);
}
if (element instanceof IfPointcut) {
if (((IfPointcut)element).alwaysFalse()) return Pointcut.makeMatchesNothing(element.state);
}
// If it can't match anything, the whole AND can't match anything
if (element.couldMatchKinds()==Shadow.NO_SHADOW_KINDS_BITS) return element;
}
if (apc.couldMatchKinds()==Shadow.NO_SHADOW_KINDS_BITS) return Pointcut.makeMatchesNothing(apc.state);
// write out with cheapest on left
Iterator iter = nodes.iterator();
Pointcut result = (Pointcut) iter.next();
while(iter.hasNext()) {
Pointcut right = (Pointcut) iter.next();
result = new AndPointcut(result,right);
}
return result;
}
private Pointcut sortOrs(Pointcut pc) {
SortedSet nodes = new TreeSet(new PointcutEvaluationExpenseComparator());
collectOrNodes(pc,nodes);
// write out with cheapest on left
Iterator iter = nodes.iterator();
Pointcut result = (Pointcut) iter.next();
while(iter.hasNext()) {
Pointcut right = (Pointcut) iter.next();
result = new OrPointcut(result,right);
}
return result;
}
/**
* Removes MATCHES_NOTHING pointcuts
*/
private Pointcut removeNothings(Pointcut pc) {
if (isAnd(pc)) {
AndPointcut apc = (AndPointcut)pc;
Pointcut right = removeNothings(apc.getRight());
Pointcut left = removeNothings(apc.getLeft());
if (left instanceof MatchesNothingPointcut || right instanceof MatchesNothingPointcut) return new MatchesNothingPointcut();
return new AndPointcut(left,right);
} else if (isOr(pc)) {
OrPointcut opc = (OrPointcut)pc;
Pointcut right = removeNothings(opc.getRight());
Pointcut left = removeNothings(opc.getLeft());
if (left instanceof MatchesNothingPointcut
&& !(right instanceof MatchesNothingPointcut)) {
return right;
} else if (right instanceof MatchesNothingPointcut
&& !(left instanceof MatchesNothingPointcut)) {
return left;
} else if (!(left instanceof MatchesNothingPointcut)
&& !(right instanceof MatchesNothingPointcut)) {
return new OrPointcut(left,right);
} else if (left instanceof MatchesNothingPointcut
&& right instanceof MatchesNothingPointcut) {
return new MatchesNothingPointcut();
}
}
return pc;
}
private void collectAndNodes(AndPointcut apc,Set nodesSoFar) {
Pointcut left = apc.getLeft();
Pointcut right = apc.getRight();
if (isAnd(left)) {
collectAndNodes((AndPointcut)left,nodesSoFar);
} else {
nodesSoFar.add(left);
}
if (isAnd(right)) {
collectAndNodes((AndPointcut)right,nodesSoFar);
} else {
nodesSoFar.add(right);
}
}
private void collectOrNodes(Pointcut pc, Set nodesSoFar) {
if (isOr(pc)) {
OrPointcut opc = (OrPointcut) pc;
collectOrNodes(opc.getLeft(),nodesSoFar);
collectOrNodes(opc.getRight(),nodesSoFar);
} else {
nodesSoFar.add(pc);
}
}
private boolean isNot(Pointcut pc) {
return (pc instanceof NotPointcut);
}
private boolean isAnd(Pointcut pc) {
return (pc instanceof AndPointcut);
}
private boolean isOr(Pointcut pc) {
return (pc instanceof OrPointcut);
}
}