]> source.dussan.org Git - aspectj.git/commitdiff
support for 3rd party integration with pointcut parsing /matching
authoracolyer <acolyer>
Thu, 2 Dec 2004 15:00:18 +0000 (15:00 +0000)
committeracolyer <acolyer>
Thu, 2 Dec 2004 15:00:18 +0000 (15:00 +0000)
weaver/src/org/aspectj/weaver/patterns/NotPointcut.java
weaver/src/org/aspectj/weaver/patterns/Pointcut.java
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java
weaver/src/org/aspectj/weaver/tools/PointcutParser.java [new file with mode: 0644]

index 292bf92eeb4bc0a3bf7d6b740c07187207f6a1e3..6bf9c9d735dbba329432621e727b11a0bd93abf4 100644 (file)
@@ -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();
index b7ebca222191edbe741caceebf6fd48567889c07..2c42179bcb061cd35b01576279eab5a0c424bc63 100644 (file)
@@ -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;
+               
        }
        
 
index f1592f16142ef8a5ecd71eb4aa0b364b13fa6856..c7784e2b32b7d5efac0c202dd5523ee26241d56d 100644 (file)
@@ -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 (file)
index 0000000..87a50e8
--- /dev/null
@@ -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:
+     * <ul>
+     * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+     * <li>Pointcut expressions must be self-contained :- they cannot contain references
+     * to other named pointcuts
+     * <li>The pointcut expression must be anonymous with no formals allowed.
+     * </ul>
+     */
+    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:
+     * <ul>
+     * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+     * <li>Pointcut expressions must be self-contained :- they cannot contain references
+     * to other named pointcuts
+     * <li>The pointcut expression must be anonymous with no formals allowed.
+     * </ul>
+     * @param supportedPointcutKinds a set of PointcutPrimitives this parser
+     * should support
+     * @throws UnsupportedOperationException if the set contains if, cflow, or
+     * cflow below
+     */
+    public PointcutParser(Set/*<PointcutPrimitives>*/ 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());
+        }
+    }
+}