// 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>
-
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;
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)) {
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();
//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,
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,
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,
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();
}
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);
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>
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());
}
--- /dev/null
+/*******************************************************************************
+ * 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);
+ }
+
+}
--- /dev/null
+<?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>
runTest("ConcreteAspect");
}
+ public void testConcretePrecedenceAspect() {
+ runTest("ConcretePrecedenceAspect");
+ }
+
public void testAspectOfWhenAspectNotInInclude() {
runTest("AspectOfWhenAspectNotInInclude");
}
<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"