]> source.dussan.org Git - aspectj.git/commitdiff
impl and test for dec precedence in aop.xml without extends
authoravasseur <avasseur>
Thu, 27 Oct 2005 11:43:16 +0000 (11:43 +0000)
committeravasseur <avasseur>
Thu, 27 Oct 2005 11:43:16 +0000 (11:43 +0000)
docs/devGuideDB/ltw.xml
loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
loadtime/src/org/aspectj/weaver/loadtime/definition/Definition.java
loadtime/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
tests/java5/ataspectj/ataspectj/ConcreteAtAspectTest.java
tests/java5/ataspectj/ataspectj/ConcretePrecedenceAspectTest.java [new file with mode: 0644]
tests/java5/ataspectj/ataspectj/aop-concreteprecedenceaspect.xml [new file with mode: 0644]
tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjLTWTests.java
tests/src/org/aspectj/systemtest/ajc150/ataspectj/ltw.xml

index 45c98d712f4c1bbdb38fb3be91c936b157990e0e..d3d9636b2664a60b0f2bf6b8c727cf258f1f9b97 100644 (file)
                 // here we are using a singleton aspect
                 AbstractAspect concreteInstance = Aspects.aspectOf(myConcreteAspectClass);
             ]]></programlisting>
-        </sect2>
+       </sect2>
 
+        <sect2 id="concrete-aspect-precedence" xreflabel="concrete-aspect-precedence">
+            <title>Using Concrete Aspects to define precedence</title>
+            <para>
+                As described in the previous section, the <literal>concrete-aspect</literal> element in
+                <literal>META-INF/aop.xml</literal> gives the option to declare the precedence, just as
+                <literal>@DeclarePrecedence</literal> or <literal>declare precedence</literal> do in
+                aspect source code.
+            </para>
+            <para>
+                Sometimes it is required to declare precedence without extending any abstract aspect
+                as well. For such a need, it is possible to use the <literal>concrete-aspect</literal>
+                element without the <literal>extends</literal> attribute and without any
+                <literal>pointcut</literal> nested element, but only with a <literal>precedence</literal>
+                attribute.
+                Consider the following:
+            </para>
+            <programlisting><![CDATA[
+                <aspectj>
+                    <concrete-aspect name="mypack.__MyDeclarePrecedence"
+                                     precedence="*..*Security*, Logging+, *"/>
+                </aspectj>
+            ]]></programlisting>
+            <para>
+                This deployment time declaration is only defining a precedence rule. You have to remember
+                that the <literal>name</literal> attribute must be a valid fully qualified class name
+                that will be then reserved for this concrete-aspect and must not conflict with other classes
+                you deploy.
+            </para>
+        </sect2>
         <!-- TODO someone implement that -->
         <!--
         <sect2 id="configuring-load-time-weaving-with-properties-files" xreflabel="configuring-load-time-weaving-with-properties-files">
         </sect2>
     </sect1>
 </chapter>
-
index fb30edd6e7b114376cecc67e885748c5eabdb7a8..897e17f52ed6d531905c823ddfda1c6940b3d2c0 100644 (file)
@@ -34,6 +34,7 @@ import org.aspectj.weaver.bcel.LazyClassGen;
 import org.aspectj.weaver.bcel.LazyMethodGen;
 import org.aspectj.weaver.loadtime.definition.Definition;
 import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.PerSingleton;
 
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
@@ -102,6 +103,26 @@ public class ConcreteAspectCodeGen {
             return false;
         }
 
+        // name must be undefined so far
+        ResolvedType current = m_world.resolve(m_concreteAspect.name, true);
+        if (!current.isMissing()) {
+            reportError("Attempt to concretize but choosen aspect name already defined: " + stringify());
+            return false;
+        }
+
+        // it can happen that extends is null, for precedence only declaration
+        if (m_concreteAspect.extend == null && m_concreteAspect.precedence != null) {
+            if (m_concreteAspect.pointcuts.isEmpty()) {
+                m_isValid = true;
+                m_perClause = new PerSingleton();
+                m_parent = null;
+                return true;// no need to checks more in that special case
+            } else {
+                reportError("Attempt to use nested pointcuts without extends clause: "+stringify());
+                return false;
+            }
+        }
+
         m_parent = m_world.resolve(m_concreteAspect.extend, true);
         // handle inner classes
         if (m_parent.equals(ResolvedType.MISSING)) {
@@ -136,13 +157,6 @@ public class ConcreteAspectCodeGen {
             return false;
         }
 
-        // must be undefined so far
-        ResolvedType current = m_world.resolve(m_concreteAspect.name, true);
-        if (!current.isMissing()) {
-            reportError("Attempt to concretize but choosen aspect name already defined:" + stringify());
-            return false;
-        }
-
         // must have all abstractions defined
         List elligibleAbstractions = new ArrayList();
         Iterator methods = m_parent.getMethods();
@@ -202,15 +216,15 @@ public class ConcreteAspectCodeGen {
         //TODO AV - abstract away from BCEL...
         // @Aspect //inherit clause from m_parent
         // @DeclarePrecedence("....") // if any
-        // public class xxxName extends xxxExtends {
-        //    @Pointcut(xxxExpression-n)
-        //    private void xxxName-n() {}
+        // public class xxxName [extends xxxExtends] {
+        //    [@Pointcut(xxxExpression-n)
+        //    public void xxxName-n() {}]
         // }
 
         // @Aspect public class ...
         LazyClassGen cg = new LazyClassGen(
                 m_concreteAspect.name.replace('.', '/'),
-                m_parent.getName(),
+                (m_parent==null)?"java/lang/Object":m_parent.getName().replace('.', '/'),
                 null,//TODO AV - we could point to the aop.xml that defines it and use JSR-45
                 Modifier.PUBLIC + Constants.ACC_SUPER,
                 EMPTY_STRINGS,
@@ -252,7 +266,7 @@ public class ConcreteAspectCodeGen {
         InstructionList cbody = init.getBody();
         cbody.append(InstructionConstants.ALOAD_0);
         cbody.append(cg.getFactory().createInvoke(
-                m_parent.getName().replace('.', '/'),
+                (m_parent==null)?"java/lang/Object":m_parent.getName().replace('.', '/'),
                 "<init>",
                 Type.VOID,
                 EMPTY_TYPES,
@@ -265,7 +279,7 @@ public class ConcreteAspectCodeGen {
             Definition.Pointcut abstractPc = (Definition.Pointcut) it.next();
 
             LazyMethodGen mg = new LazyMethodGen(
-                    Modifier.PUBLIC,
+                    Modifier.PUBLIC,//TODO AV - respect visibility instead of opening up?
                     Type.VOID,
                     abstractPc.name,
                     EMPTY_TYPES,
index 87c2f82e2e358c9d49d15097559654991010b587..9bea5cd2dbeb8612c816b9af739d10d2f4ce55d8 100644 (file)
@@ -85,7 +85,15 @@ public class Definition {
 
         public ConcreteAspect(String name, String extend, String precedence) {
             this.name = name;
-            this.extend = extend;
+            // make sure extend set to null if ""
+            if (extend == null || extend.length() == 0) {
+                this.extend = null;
+                if (precedence == null || precedence.length() == 0) {
+                    throw new RuntimeException("Not allowed");
+                }
+            } else {
+                this.extend = extend;
+            }
             this.precedence = precedence;
             this.pointcuts = new ArrayList();
         }
index 1aeccaf1d23d81ac672042d5562e1a07a2c3b513..ac80afd20e338746dbbf811a6dc0df01b1945388 100644 (file)
@@ -151,10 +151,11 @@ public class DocumentParser extends DefaultHandler {
             String name = attributes.getValue(NAME_ATTRIBUTE);
             String extend = attributes.getValue(EXTEND_ATTRIBUTE);
             String precedence = attributes.getValue(PRECEDENCE_ATTRIBUTE);
-            if (!isNull(name) && !isNull(extend)) {
-                if (isNull(precedence)) {
+            if (!isNull(name)) {
+                if (isNull(precedence) && !isNull(extend)) {//if no precedence, then extends must be there
                     m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend);
-                } else {
+                } else if (!isNull(precedence)) {
+                    // wether a pure precedence def, or an extendsANDprecedence def.
                     m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend, precedence);
                 }
                 m_definition.getConcreteAspects().add(m_lastConcreteAspect);
index 2d673ca9fdd73b58045c199384cbe4b2b1c2e2eb..3aa5cea7a4665170caf4a2410f53a48752f0e26d 100644 (file)
@@ -17,6 +17,7 @@ import junit.framework.TestSuite;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.Aspects;
 
 /**
  * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
@@ -61,6 +62,15 @@ public class ConcreteAtAspectTest extends TestCase {
         assertEquals(3, I);
     }
 
+    public void tesCanLoad() {
+        try {
+            Class jitAspect = Class.forName("ataspectj.Foo");
+            Object aspect = Aspects.aspectOf(jitAspect);
+        } catch (Throwable t) {
+            fail(t.toString());
+        }
+    }
+
     public static void main(String[] args) {
         TestHelper.runAndThrowOnFailure(suite());
     }
diff --git a/tests/java5/ataspectj/ataspectj/ConcretePrecedenceAspectTest.java b/tests/java5/ataspectj/ataspectj/ConcretePrecedenceAspectTest.java
new file mode 100644 (file)
index 0000000..c873028
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * 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://eclipse.org/legal/epl-v10.html 
+ * 
+ * Contributors:
+ *   Alexandre Vasseur         initial implementation
+ *******************************************************************************/
+package ataspectj;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+
+/**
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class ConcretePrecedenceAspectTest extends TestCase {
+
+    static String LOG = "";
+
+    void target() {
+        LOG = LOG + "target ";
+    }
+
+    @Aspect
+    static class TestAspect_1 {
+        @Before("execution(* ataspectj.ConcretePrecedenceAspectTest.target())")
+        public void before() {
+            LOG = LOG + "1 ";
+        }
+    }
+
+    @Aspect
+    static class TestAspect_2 {
+        @Before("execution(* ataspectj.ConcretePrecedenceAspectTest.target())")
+        public void before() {
+            LOG = LOG + "2 ";
+        }
+    }
+
+    @Aspect
+    static class TestAspect_3 {
+        @Before("execution(* ataspectj.ConcretePrecedenceAspectTest.target())")
+        public void before() {
+            LOG = LOG + "3 ";
+        }
+    }
+
+    public void testPrecedenceFromXML() {
+        LOG = "";
+        target();
+        assertEquals("2 3 1 target ", LOG);
+    }
+
+    public static void main(String[] args) {
+        TestHelper.runAndThrowOnFailure(suite());
+    }
+
+    public static Test suite() {
+        return new TestSuite(ConcretePrecedenceAspectTest.class);
+    }
+
+}
diff --git a/tests/java5/ataspectj/ataspectj/aop-concreteprecedenceaspect.xml b/tests/java5/ataspectj/ataspectj/aop-concreteprecedenceaspect.xml
new file mode 100644 (file)
index 0000000..a3dbc39
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<aspectj>
+    <weaver options="-XmessageHandlerClass:ataspectj.TestHelper -1.5"/>
+    <aspects>
+        <concrete-aspect
+                name="ataspectj.Foo"
+                precedence="*..*_2, *..*_3, *..*_1"/>
+        <aspect name="ataspectj.ConcretePrecedenceAspectTest.TestAspect_1"/>
+        <aspect name="ataspectj.ConcretePrecedenceAspectTest.TestAspect_2"/>
+        <aspect name="ataspectj.ConcretePrecedenceAspectTest.TestAspect_3"/>
+    </aspects>
+</aspectj>
index 49e9e785018f93f82cc8e6c7cd45e4bab1a2766b..ae8f478f7c30bf7488f944fe75e16d6394210fe9 100644 (file)
@@ -102,6 +102,10 @@ public class AtAjLTWTests extends XMLBasedAjcTestCase {
         runTest("ConcreteAspect");
     }
 
+    public void testConcretePrecedenceAspect() {
+        runTest("ConcretePrecedenceAspect");
+    }
+
     public void testAspectOfWhenAspectNotInInclude() {
         runTest("AspectOfWhenAspectNotInInclude");
     }
index 257d56805c1b07d6a86e78e0a9ecac9581c618bd..dcb9f3918b6e0aa3a3f4bc1efc4745fb1eb03e0b 100644 (file)
         <run class="ataspectj.ConcreteAspectTest" ltw="ataspectj/aop-concreteaspect.xml"/>
     </ajc-test>
 
+    <ajc-test dir="java5/ataspectj" title="ConcretePrecedenceAspect">
+        <compile
+            files="ataspectj/ConcretePrecedenceAspectTest.java,ataspectj/TestHelper.java"
+            options="-1.5 -Xdev:NoAtAspectJProcessing -XnoWeave"
+            />
+        <run class="ataspectj.ConcretePrecedenceAspectTest" ltw="ataspectj/aop-concreteprecedenceaspect.xml"/>
+    </ajc-test>
+
     <ajc-test dir="java5/ataspectj" title="AspectOfWhenAspectNotInInclude">
         <compile
             files="ataspectj/bugs/AspectOfWhenAspectNotInIncludeTest.java,ataspectj/TestHelper.java"