From c6f7ba2782307c17dcf4cf9aabc3770cae09a3a2 Mon Sep 17 00:00:00 2001 From: acolyer Date: Thu, 2 Dec 2004 15:00:18 +0000 Subject: [PATCH] support for 3rd party integration with pointcut parsing /matching --- .../aspectj/weaver/patterns/NotPointcut.java | 1 + .../org/aspectj/weaver/patterns/Pointcut.java | 4 + .../weaver/patterns/ThisOrTargetPointcut.java | 2 + .../aspectj/weaver/tools/PointcutParser.java | 172 ++++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 weaver/src/org/aspectj/weaver/tools/PointcutParser.java diff --git a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java index 292bf92ee..6bf9c9d73 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java @@ -38,6 +38,7 @@ public class NotPointcut extends Pointcut { setLocation(pointcut.getSourceContext(), startPos, pointcut.getEnd()); } + public Pointcut getNegatedPointcut() { return body; } public FuzzyBoolean fastMatch(FastMatchInfo type) { return body.fastMatch(type).not(); diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java index b7ebca222..2c42179bc 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java @@ -52,6 +52,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression public static final State RESOLVED = new State("resolved", 1); public static final State CONCRETE = new State("concrete", 2); + private byte pointcutKind; public State state; @@ -126,6 +127,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression public static final byte NONE = 20; + public byte getPointcutKind() { return pointcutKind; } // internal, only called from resolve protected abstract void resolveBindings(IScope scope, Bindings bindings); @@ -245,7 +247,9 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression throw new BCException("unknown kind: " + kind); } ret.state = RESOLVED; + ret.pointcutKind = kind; return ret; + } diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java index f1592f161..c7784e2b3 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java @@ -56,6 +56,8 @@ public class ThisOrTargetPointcut extends NameBindingPointcut { this.type = type; } + public boolean isThis() { return isThis; } + public FuzzyBoolean fastMatch(FastMatchInfo type) { return FuzzyBoolean.MAYBE; } diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutParser.java b/weaver/src/org/aspectj/weaver/tools/PointcutParser.java new file mode 100644 index 000000000..87a50e80c --- /dev/null +++ b/weaver/src/org/aspectj/weaver/tools/PointcutParser.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.aspectj.weaver.tools; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.aspectj.weaver.internal.tools.PointcutExpressionImpl; +import org.aspectj.weaver.patterns.AndPointcut; +import org.aspectj.weaver.patterns.NotPointcut; +import org.aspectj.weaver.patterns.OrPointcut; +import org.aspectj.weaver.patterns.ParserException; +import org.aspectj.weaver.patterns.PatternParser; +import org.aspectj.weaver.patterns.Pointcut; +import org.aspectj.weaver.patterns.ThisOrTargetPointcut; + +/** + * A PointcutParser can be used to build PointcutExpressions for a + * user-defined subset of AspectJ's pointcut language + */ +public class PointcutParser { + + private Set supportedPrimitives; + + /** + * @return a Set containing every PointcutPrimitive except + * if, cflow, and cflowbelow (useful for passing to + * PointcutParser constructor). + */ + public static Set getAllSupportedPointcutPrimitives() { + Set primitives = new HashSet(); + primitives.add(PointcutPrimitives.ADVICE_EXECUTION); + primitives.add(PointcutPrimitives.ARGS); + primitives.add(PointcutPrimitives.CALL); + primitives.add(PointcutPrimitives.EXECUTION); + primitives.add(PointcutPrimitives.GET); + primitives.add(PointcutPrimitives.HANDLER); + primitives.add(PointcutPrimitives.INITIALIZATION); + primitives.add(PointcutPrimitives.PRE_INITIALIZATION); + primitives.add(PointcutPrimitives.SET); + primitives.add(PointcutPrimitives.STATIC_INITIALIZATION); + primitives.add(PointcutPrimitives.TARGET); + primitives.add(PointcutPrimitives.THIS); + primitives.add(PointcutPrimitives.WITHIN); + primitives.add(PointcutPrimitives.WITHIN_CODE); + return primitives; + } + + /** + * Create a pointcut parser that can parse the full AspectJ pointcut + * language with the following exceptions: + * + */ + public PointcutParser() { + supportedPrimitives = getAllSupportedPointcutPrimitives(); + } + + /** + * Create a pointcut parser that can parse pointcut expressions built + * from a user-defined subset of AspectJ's supported pointcut primitives. + * The following restrictions apply: + * + * @param supportedPointcutKinds a set of PointcutPrimitives this parser + * should support + * @throws UnsupportedOperationException if the set contains if, cflow, or + * cflow below + */ + public PointcutParser(Set/**/ supportedPointcutKinds) { + supportedPrimitives = supportedPointcutKinds; + for (Iterator iter = supportedPointcutKinds.iterator(); iter.hasNext();) { + PointcutPrimitives element = (PointcutPrimitives) iter.next(); + if ((element == PointcutPrimitives.IF) || + (element == PointcutPrimitives.CFLOW) || + (element == PointcutPrimitives.CFLOW_BELOW)) { + throw new UnsupportedOperationException("Cannot handle if, cflow, and cflowbelow primitives"); + } + } + } + + + /** + * Parse the given pointcut expression. + * @throws UnsupportedOperationException if the parser encounters a + * primitive pointcut expression of a kind not supported by this PointcutParser. + * @throws IllegalArgumentException if the expression is not a well-formed + * pointcut expression + */ + public PointcutExpression parsePointcutExpression(String expression) + throws UnsupportedOperationException, IllegalArgumentException { + PointcutExpressionImpl pcExpr = null; + try { + Pointcut pc = new PatternParser(expression).parsePointcut(); + validateAgainstSupportedPrimitives(pc); + pcExpr = new PointcutExpressionImpl(pc); + } catch (ParserException pEx) { + throw new IllegalArgumentException(pEx.getMessage()); + } + return pcExpr; + } + + private void validateAgainstSupportedPrimitives(Pointcut pc) { + switch(pc.getPointcutKind()) { + case Pointcut.AND: + validateAgainstSupportedPrimitives(((AndPointcut)pc).getLeft()); + validateAgainstSupportedPrimitives(((AndPointcut)pc).getRight()); + break; + case Pointcut.ARGS: + if (!supportedPrimitives.contains(PointcutPrimitives.ARGS)) + throw new UnsupportedOperationException("args is not supported by this parser"); + break; + case Pointcut.CFLOW: + throw new UnsupportedOperationException("cflow and cflowbelow are not supported by this parser"); + case Pointcut.HANDLER: + if (!supportedPrimitives.contains(PointcutPrimitives.HANDLER)) + throw new UnsupportedOperationException("handler is not supported by this parser"); + break; + case Pointcut.IF: + case Pointcut.IF_FALSE: + case Pointcut.IF_TRUE: + throw new UnsupportedOperationException("if is not supported by this parser"); + case Pointcut.KINDED: + break; + case Pointcut.NOT: + validateAgainstSupportedPrimitives(((NotPointcut)pc).getNegatedPointcut()); + break; + case Pointcut.OR: + validateAgainstSupportedPrimitives(((OrPointcut)pc).getLeft()); + validateAgainstSupportedPrimitives(((OrPointcut)pc).getRight()); + break; + case Pointcut.REFERENCE: + throw new UnsupportedOperationException("reference pointcuts are not supported by this parser"); + case Pointcut.THIS_OR_TARGET: + boolean isThis = ((ThisOrTargetPointcut)pc).isThis(); + if (isThis && !supportedPrimitives.contains(PointcutPrimitives.THIS)) { + throw new UnsupportedOperationException("this is not supported by this parser"); + } else if (!supportedPrimitives.contains(PointcutPrimitives.TARGET)) { + throw new UnsupportedOperationException("target is not supported by this parser"); + } + break; + case Pointcut.WITHIN: + if (!supportedPrimitives.contains(PointcutPrimitives.WITHIN)) + throw new UnsupportedOperationException("within is not supported by this parser"); + break; + case Pointcut.WITHINCODE: + if (!supportedPrimitives.contains(PointcutPrimitives.WITHIN_CODE)) + throw new UnsupportedOperationException("withincode is not supported by this parser"); + break; + case Pointcut.NONE: // deliberate fall-through + default: + throw new UnsupportedOperationException("Unknown pointcut kind: " + pc.getPointcutKind()); + } + } +} -- 2.39.5