From 4f46be7c62e76950028e5e8a7214f209d6343bda Mon Sep 17 00:00:00 2001 From: avasseur Date: Fri, 20 May 2005 12:27:59 +0000 Subject: [PATCH] moved bcel things to bcel package in weaver, deow test + fix for @AJ --- docs/adk15ProgGuideDB/ataspectj.xml | 4 +- tests/java5/ataspectj/ataspectj/DeowTest.java | 41 ++ .../ajc150/ataspectj/AtAjSyntaxTests.java | 4 + .../systemtest/ajc150/ataspectj/syntax.xml | 7 + .../org/aspectj/weaver/AjcMemberMaker.java | 21 + .../weaver/ataspectj/Ajc5MemberMaker.java | 59 -- .../AtAjAttributes.java} | 688 ++++++++++-------- .../org/aspectj/weaver/bcel/BcelAdvice.java | 5 +- .../org/aspectj/weaver/bcel/BcelField.java | 3 +- .../org/aspectj/weaver/bcel/BcelMethod.java | 3 +- .../aspectj/weaver/bcel/BcelObjectType.java | 7 +- .../org/aspectj/weaver/bcel/BcelShadow.java | 7 +- .../org/aspectj/weaver/patterns/PerCflow.java | 3 +- .../aspectj/weaver/patterns/PerObject.java | 3 +- .../aspectj/weaver/patterns/PerSingleton.java | 5 +- .../weaver/patterns/PerTypeWithin.java | 3 +- .../aspectj/weaver/tools/WeavingAdaptor.java | 3 +- 17 files changed, 465 insertions(+), 401 deletions(-) create mode 100644 tests/java5/ataspectj/ataspectj/DeowTest.java delete mode 100644 weaver/src/org/aspectj/weaver/ataspectj/Ajc5MemberMaker.java rename weaver/src/org/aspectj/weaver/{ataspectj/Aj5Attributes.java => bcel/AtAjAttributes.java} (66%) diff --git a/docs/adk15ProgGuideDB/ataspectj.xml b/docs/adk15ProgGuideDB/ataspectj.xml index b3986ef90..febf50033 100644 --- a/docs/adk15ProgGuideDB/ataspectj.xml +++ b/docs/adk15ProgGuideDB/ataspectj.xml @@ -323,13 +323,13 @@ System.out.println("phew"); } - @AfterReturning(value="call(Foo+.new(..))",returning="f") + @AfterReturning(pointcut="call(Foo+.new(..))",returning="f") public void itsAFoo(Foo f) { System.out.println("It's a Foo: " + f); } ]]> - (Note the need for the "value=" prefix in front of the pointcut + (Note the use of the "pointcut=" prefix in front of the pointcut expression in the returning case). After throwing advice works in a similar fashion, using the diff --git a/tests/java5/ataspectj/ataspectj/DeowTest.java b/tests/java5/ataspectj/ataspectj/DeowTest.java new file mode 100644 index 000000000..fc8a27015 --- /dev/null +++ b/tests/java5/ataspectj/ataspectj/DeowTest.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * 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 org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.DeclareWarning; +import org.aspectj.lang.annotation.DeclareError; + +/** + * @author Alexandre Vasseur + */ +public class DeowTest { + + public void hello() {} + + public void hi() {} + + public void target() { + hello(); + hi(); + } + + @Aspect + public static class DeowAspect { + + @DeclareWarning("call(* hello()) && within(ataspectj.DeowTest)") + final static String onHello = "call hello"; + + @DeclareError("call(* hi()) && within(ataspectj.DeowTest)") + final static String onHi = "call hi"; + } +} diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java index 264c46930..6c936ef4f 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java @@ -87,4 +87,8 @@ public class AtAjSyntaxTests extends XMLBasedAjcTestCase { public void testAroundInlineMunger2() { runTest("AroundInlineMunger2"); } + + public void testDeow() { + runTest("Deow"); + } } \ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml index 055567d30..2a4024617 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml @@ -100,4 +100,11 @@ + + + + + + + \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java index 83bab19e0..a80e7e3a7 100644 --- a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java +++ b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java @@ -13,6 +13,9 @@ package org.aspectj.weaver; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; + import java.lang.reflect.Modifier; //import org.aspectj.weaver.ResolvedTypeX.Name; @@ -692,4 +695,22 @@ public class AjcMemberMaker { "", "()V"); } + + //-- common types we use. Note: Java 5 dependand types are refered to as String + public final static TypeX ASPECT_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.Aspect"); + public final static TypeX BEFORE_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.Before"); + public final static TypeX AROUND_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.Around"); + public final static TypeX AFTERRETURNING_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.AfterReturning"); + public final static TypeX AFTERTHROWING_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.AfterThrowing"); + public final static TypeX AFTER_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.After"); + public final static TypeX POINTCUT_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.Pointcut"); + public final static TypeX DECLAREERROR_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.DeclareError"); + public final static TypeX DECLAREWARNING_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.DeclareWarning"); + public final static TypeX DECLAREPRECEDENCE_ANNOTATION = TypeX.forName("org.aspectj.lang.annotation.DeclarePrecedence"); + + public final static TypeX TYPEX_JOINPOINT = TypeX.forName(JoinPoint.class.getName().replace('/','.')); + public final static TypeX TYPEX_PROCEEDINGJOINPOINT = TypeX.forName(ProceedingJoinPoint.class.getName().replace('/','.')); + public final static TypeX TYPEX_STATICJOINPOINT = TypeX.forName(JoinPoint.StaticPart.class.getName().replace('/','.')); + public final static TypeX TYPEX_ENCLOSINGSTATICJOINPOINT = TypeX.forName(JoinPoint.EnclosingStaticPart.class.getName().replace('/','.')); + } diff --git a/weaver/src/org/aspectj/weaver/ataspectj/Ajc5MemberMaker.java b/weaver/src/org/aspectj/weaver/ataspectj/Ajc5MemberMaker.java deleted file mode 100644 index e6f68d7ff..000000000 --- a/weaver/src/org/aspectj/weaver/ataspectj/Ajc5MemberMaker.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * 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: - * initial implementation Alexandre Vasseur - *******************************************************************************/ -package org.aspectj.weaver.ataspectj; - -import org.aspectj.weaver.ResolvedMember; -import org.aspectj.weaver.TypeX; -import org.aspectj.weaver.Member; -import org.aspectj.weaver.ResolvedTypeX; - -import java.lang.reflect.Modifier; - -/** - * Addition to AjcMemberMaker for @Aj aspect - * Should end up there - * - * @author Alexandre Vasseur - */ -public class Ajc5MemberMaker { - - public final static TypeX ASPECT = TypeX.forName("org.aspectj.lang.annotation.Aspect"); - - /** - * Returns true if the given aspect is an @AJ aspect - * - * @param aspectType - * @return - */ - public static boolean isAnnotationStyleAspect(ResolvedTypeX aspectType) { - if (aspectType != null) { - if (aspectType.isAspect()) { - return aspectType.isAnnotationStyleAspect(); - } - } - return false; - } - - //temp proto code for aspectOf without pre-processing - public static ResolvedMember perSingletonAspectOfMethod(TypeX declaringType) { - return new ResolvedMember( - Member.METHOD, - TypeX.forName("alex.lang.Aspects"), - Modifier.PUBLIC | Modifier.STATIC, - "aspectOf$singleton", - "(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;" - ); - - - } - -} diff --git a/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java similarity index 66% rename from weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java rename to weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index 15896cbc6..154ec2748 100644 --- a/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -9,13 +9,7 @@ * Contributors: * initial implementation Alexandre Vasseur *******************************************************************************/ -package org.aspectj.weaver.ataspectj; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; +package org.aspectj.weaver.bcel; import org.aspectj.apache.bcel.classfile.Attribute; import org.aspectj.apache.bcel.classfile.Field; @@ -28,11 +22,9 @@ import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair; import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations; import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations; import org.aspectj.apache.bcel.generic.Type; +import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHandler; import org.aspectj.bridge.Message; -import org.aspectj.bridge.IMessage; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.weaver.Advice; import org.aspectj.weaver.AdviceKind; import org.aspectj.weaver.AjAttribute; @@ -42,9 +34,11 @@ import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.ResolvedPointcutDefinition; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.TypeX; +import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.DeclarePrecedence; import org.aspectj.weaver.patterns.FormalBinding; import org.aspectj.weaver.patterns.IScope; +import org.aspectj.weaver.patterns.ParserException; import org.aspectj.weaver.patterns.PatternParser; import org.aspectj.weaver.patterns.PerCflow; import org.aspectj.weaver.patterns.PerClause; @@ -53,9 +47,13 @@ import org.aspectj.weaver.patterns.PerSingleton; import org.aspectj.weaver.patterns.PerTypeWithin; import org.aspectj.weaver.patterns.Pointcut; import org.aspectj.weaver.patterns.SimpleScope; -import org.aspectj.weaver.patterns.ParserException; -import org.aspectj.weaver.patterns.Declare; -import org.aspectj.weaver.patterns.DeclareErrorOrWarning; +import org.aspectj.weaver.patterns.TypePattern; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; /** * Annotation defined aspect reader. @@ -64,15 +62,15 @@ import org.aspectj.weaver.patterns.DeclareErrorOrWarning; * * @author Alexandre Vasseur */ -public class Aj5Attributes { +public class AtAjAttributes { private final static List EMPTY_LIST = new ArrayList(); private final static String[] EMPTY_STRINGS = new String[0]; - - public final static TypeX TYPEX_JOINPOINT = TypeX.forName(JoinPoint.class.getName().replace('/','.')); - public final static TypeX TYPEX_PROCEEDINGJOINPOINT = TypeX.forName(ProceedingJoinPoint.class.getName().replace('/','.')); - public final static TypeX TYPEX_STATICJOINPOINT = TypeX.forName(JoinPoint.StaticPart.class.getName().replace('/','.')); - public final static TypeX TYPEX_ENCLOSINGSTATICJOINPOINT = TypeX.forName(JoinPoint.EnclosingStaticPart.class.getName().replace('/','.')); + private final static String VALUE = "value"; + private final static String POINTCUT = "pointcut"; + private final static String THROWING = "throwing"; + private final static String RETURNING = "returning"; + private final static String STRING_DESC = "Ljava/lang/String;"; /** * A struct that allows to add extra arguments without always breaking the API @@ -163,7 +161,7 @@ public class Aj5Attributes { * @param msgHandler * @return list of AjAttributes */ - public static List readAj5ClassAttributes(JavaClass javaClass, ResolvedTypeX type, ISourceContext context,IMessageHandler msgHandler, boolean isCodeStyleAspect) { + public static List readAj5ClassAttributes(JavaClass javaClass, ResolvedTypeX type, ISourceContext context, IMessageHandler msgHandler, boolean isCodeStyleAspect) { AjAttributeStruct struct = new AjAttributeStruct(type, context, msgHandler); Attribute[] attributes = javaClass.getAttributes(); boolean hasAtAspectAnnotation = false; @@ -225,7 +223,7 @@ public class Aj5Attributes { //FIXME alex can that be too slow ? for (int i = 0; i < javaClass.getMethods().length; i++) { Method method = javaClass.getMethods()[i]; - if (method.getName().startsWith(NameMangler.PREFIX)) continue; // already dealt with by ajc... + if (method.getName().startsWith(NameMangler.PREFIX)) continue; // already dealt with by ajc... //FIXME alex optimize, this method struct will gets recreated for advice extraction AjAttributeMethodStruct mstruct = new AjAttributeMethodStruct(method, type, context, msgHandler); Attribute[] mattributes = method.getAttributes(); @@ -246,7 +244,7 @@ public class Aj5Attributes { // code style declare error / warning are class attributes for (int i = 0; i < javaClass.getFields().length; i++) { Field field = javaClass.getFields()[i]; - if (field.getName().startsWith(NameMangler.PREFIX)) continue; // already dealt with by ajc... + if (field.getName().startsWith(NameMangler.PREFIX)) continue; // already dealt with by ajc... //FIXME alex optimize, this method struct will gets recreated for advice extraction AjAttributeFieldStruct fstruct = new AjAttributeFieldStruct(field, type, context, msgHandler); Attribute[] fattributes = field.getAttributes(); @@ -287,10 +285,10 @@ public class Aj5Attributes { * @param msgHandler * @return list of AjAttributes */ - public static List readAj5MethodAttributes(Method method, ResolvedTypeX type, ResolvedPointcutDefinition preResolvedPointcut, ISourceContext context,IMessageHandler msgHandler) { - if (method.getName().startsWith(NameMangler.PREFIX)) return Collections.EMPTY_LIST; // already dealt with by ajc... + public static List readAj5MethodAttributes(Method method, ResolvedTypeX type, ResolvedPointcutDefinition preResolvedPointcut, ISourceContext context, IMessageHandler msgHandler) { + if (method.getName().startsWith(NameMangler.PREFIX)) return Collections.EMPTY_LIST; // already dealt with by ajc... - AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, type, context, msgHandler); + AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, type, context, msgHandler); Attribute[] attributes = method.getAttributes(); // we remember if we found one @AJ annotation for minimal semantic error reporting @@ -304,11 +302,21 @@ public class Aj5Attributes { Attribute attribute = attributes[i]; if (acceptAttribute(attribute)) { RuntimeAnnotations rvs = (RuntimeAnnotations) attribute; - hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleBeforeAnnotation(rvs, struct, preResolvedPointcut); - hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleAfterAnnotation(rvs, struct, preResolvedPointcut); - hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleAfterReturningAnnotation(rvs, struct, preResolvedPointcut); - hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleAfterThrowingAnnotation(rvs, struct, preResolvedPointcut); - hasAtAspectJAnnotation = hasAtAspectJAnnotation || handleAroundAnnotation(rvs, struct, preResolvedPointcut); + hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleBeforeAnnotation( + rvs, struct, preResolvedPointcut + ); + hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleAfterAnnotation( + rvs, struct, preResolvedPointcut + ); + hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleAfterReturningAnnotation( + rvs, struct, preResolvedPointcut + ); + hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid || handleAfterThrowingAnnotation( + rvs, struct, preResolvedPointcut + ); + hasAtAspectJAnnotation = hasAtAspectJAnnotation || handleAroundAnnotation( + rvs, struct, preResolvedPointcut + ); // there can only be one RuntimeVisible bytecode attribute break; } @@ -343,7 +351,9 @@ public class Aj5Attributes { if (hasAtAspectJAnnotationMustReturnVoid && !Type.VOID.equals(struct.method.getReturnType())) { msgHandler.handleMessage( new Message( - "Found @AspectJ annotation on a non around advice not returning void '" + methodToString(struct.method) + "'", + "Found @AspectJ annotation on a non around advice not returning void '" + methodToString( + struct.method + ) + "'", IMessage.ERROR, null, type.getSourceLocation() @@ -365,7 +375,7 @@ public class Aj5Attributes { * @param msgHandler * @return list of AjAttributes, always empty for now */ - public static List readAj5FieldAttributes(Field field, ResolvedTypeX type, ISourceContext context,IMessageHandler msgHandler) { + public static List readAj5FieldAttributes(Field field, ResolvedTypeX type, ISourceContext context, IMessageHandler msgHandler) { return Collections.EMPTY_LIST; } @@ -377,25 +387,27 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleAspectAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeStruct struct) { - Annotation aspect = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.Aspect"); + Annotation aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.ASPECT_ANNOTATION); if (aspect != null) { - ElementNameValuePair aspectPerClause = getAnnotationElement(aspect, "value"); + ElementNameValuePair aspectPerClause = getAnnotationElement(aspect, VALUE); + final PerClause perClause; if (aspectPerClause == null) { // defaults to singleton - PerClause clause = new PerSingleton(); - clause.setLocation(struct.context, -1, -1); - struct.ajAttributes.add(new AjAttribute.Aspect(clause)); - return true; + perClause = new PerSingleton(); } else { String perX = aspectPerClause.getValue().stringifyValue(); - final PerClause clause; - if (perX == null || perX.length()<=0) { - clause = new PerSingleton(); + if (perX == null || perX.length() <= 0) { + perClause = new PerSingleton(); } else { - clause = parsePerClausePointcut(perX, struct); + perClause = parsePerClausePointcut(perX, struct); } - clause.setLocation(struct.context, -1, -1); - struct.ajAttributes.add(new AjAttribute.Aspect(clause)); + } + if (perClause == null) { + // could not parse it, ignore the aspect + return false; + } else { + perClause.setLocation(struct.context, -1, -1); + struct.ajAttributes.add(new AjAttribute.Aspect(perClause)); return true; } } @@ -403,41 +415,56 @@ public class Aj5Attributes { } /** - * Read a perClause + * Read a perClause, returns null on failure and issue messages * - * @param perClause like "pertarget(.....)" - * @param struct for which we are parsing the per clause + * @param perClauseString like "pertarget(.....)" + * @param struct for which we are parsing the per clause * @return a PerClause instance */ - private static PerClause parsePerClausePointcut(String perClause, AjAttributeStruct struct) { - final String pointcut; - if (perClause.startsWith(PerClause.KindAnnotationPrefix.PERCFLOW.getName())) { - pointcut = PerClause.KindAnnotationPrefix.PERCFLOW.extractPointcut(perClause); - return new PerCflow(Pointcut.fromString(pointcut), false); - } else if (perClause.startsWith(PerClause.KindAnnotationPrefix.PERCFLOWBELOW.getName())) { - pointcut = PerClause.KindAnnotationPrefix.PERCFLOWBELOW.extractPointcut(perClause); - return new PerCflow(Pointcut.fromString(pointcut), true); - } else if (perClause.startsWith(PerClause.KindAnnotationPrefix.PERTARGET.getName())) { - pointcut = PerClause.KindAnnotationPrefix.PERTARGET.extractPointcut(perClause); - return new PerObject(Pointcut.fromString(pointcut), false); - } else if (perClause.startsWith(PerClause.KindAnnotationPrefix.PERTHIS.getName())) { - pointcut = PerClause.KindAnnotationPrefix.PERTHIS.extractPointcut(perClause); - return new PerObject(Pointcut.fromString(pointcut), true); - } else if (perClause.startsWith(PerClause.KindAnnotationPrefix.PERTYPEWITHIN.getName())) { - pointcut = PerClause.KindAnnotationPrefix.PERTYPEWITHIN.extractPointcut(perClause); - return new PerTypeWithin(new PatternParser(pointcut).parseTypePattern()); - } else if (perClause.equalsIgnoreCase(PerClause.SINGLETON.getName() + "()")) { - return new PerSingleton(); + private static PerClause parsePerClausePointcut(String perClauseString, AjAttributeStruct struct) { + final String pointcutString; + Pointcut poincut = null; + TypePattern typePattern = null; + final PerClause perClause; + if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERCFLOW.getName())) { + pointcutString = PerClause.KindAnnotationPrefix.PERCFLOW.extractPointcut(perClauseString); + poincut = parsePointcut(pointcutString, struct); + perClause = new PerCflow(poincut, false); + } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERCFLOWBELOW.getName())) { + pointcutString = PerClause.KindAnnotationPrefix.PERCFLOWBELOW.extractPointcut(perClauseString); + poincut = parsePointcut(pointcutString, struct); + perClause = new PerCflow(poincut, true); + } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTARGET.getName())) { + pointcutString = PerClause.KindAnnotationPrefix.PERTARGET.extractPointcut(perClauseString); + poincut = parsePointcut(pointcutString, struct); + perClause = new PerObject(poincut, false); + } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTHIS.getName())) { + pointcutString = PerClause.KindAnnotationPrefix.PERTHIS.extractPointcut(perClauseString); + poincut = parsePointcut(pointcutString, struct); + perClause = new PerObject(poincut, true); + } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTYPEWITHIN.getName())) { + pointcutString = PerClause.KindAnnotationPrefix.PERTYPEWITHIN.extractPointcut(perClauseString); + typePattern = parseTypePattern(pointcutString, struct); + perClause = new PerTypeWithin(typePattern); + } else if (perClauseString.equalsIgnoreCase(PerClause.SINGLETON.getName() + "()")) { + perClause = new PerSingleton(); + } else { + // could not parse the @AJ perclause - fallback to singleton and issue an error + reportError("@Aspect per clause cannot be read '" + perClauseString + "'", struct); + return null; } - // could not parse the @AJ perclause - struct.handler.handleMessage( - new Message( - "cannot read per clause from @Aspect: " + perClause, - struct.enclosingType.getSourceLocation(), - true - ) - ); - throw new RuntimeException("cannot read perclause " + perClause); + + if (!PerClause.SINGLETON.equals(perClause.getKind()) + && !PerClause.PERTYPEWITHIN.equals(perClause.getKind()) + && poincut == null) { + // we could not parse the pointcut + return null; + } + if (PerClause.PERTYPEWITHIN.equals(perClause.getKind()) && typePattern == null) { + // we could not parse the type pattern + return null; + } + return perClause; } /** @@ -448,9 +475,9 @@ public class Aj5Attributes { * @return true if found */ private static boolean handlePrecedenceAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeStruct struct) { - Annotation aspect = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.DeclarePrecedence"); + Annotation aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPRECEDENCE_ANNOTATION); if (aspect != null) { - ElementNameValuePair precedence = getAnnotationElement(aspect, "value"); + ElementNameValuePair precedence = getAnnotationElement(aspect, VALUE); if (precedence != null) { String precedencePattern = precedence.getValue().stringifyValue(); PatternParser parser = new PatternParser(precedencePattern); @@ -470,15 +497,15 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleBeforeAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - Annotation before = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.Before"); + Annotation before = getAnnotation(runtimeAnnotations, AjcMemberMaker.BEFORE_ANNOTATION); if (before != null) { - ElementNameValuePair beforeAdvice = getAnnotationElement(before, "value"); + ElementNameValuePair beforeAdvice = getAnnotationElement(before, VALUE); if (beforeAdvice != null) { // this/target/args binding FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; try { bindings = extractBindings(struct); - } catch (UnreadableDebugInfo unreadableDebugInfo) { + } catch (UnreadableDebugInfoException unreadableDebugInfoException) { return false; } IScope binding = new BindingScope( @@ -489,21 +516,24 @@ public class Aj5Attributes { // joinpoint, staticJoinpoint binding int extraArgument = extractExtraArgument(struct.method); - Pointcut pc = null; - if (preResolvedPointcut != null) { - pc = preResolvedPointcut.getPointcut(); - } else { - pc = Pointcut.fromString(beforeAdvice.getValue().stringifyValue()).resolve(binding); - } + Pointcut pc = null; + if (preResolvedPointcut != null) { + pc = preResolvedPointcut.getPointcut(); + } else { + pc = parsePointcut(beforeAdvice.getValue().stringifyValue(), struct); + if (pc == null) return false;//parse error + pc.resolve(binding); + } setIgnoreUnboundBindingNames(pc, bindings); - struct.ajAttributes.add(new AjAttribute.AdviceAttribute( - AdviceKind.Before, - pc, - extraArgument, - -1, - -1, - struct.context + struct.ajAttributes.add( + new AjAttribute.AdviceAttribute( + AdviceKind.Before, + pc, + extraArgument, + -1, + -1, + struct.context ) ); return true; @@ -520,15 +550,15 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleAfterAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - Annotation after = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.After"); + Annotation after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTER_ANNOTATION); if (after != null) { - ElementNameValuePair afterAdvice = getAnnotationElement(after, "value"); + ElementNameValuePair afterAdvice = getAnnotationElement(after, VALUE); if (afterAdvice != null) { // this/target/args binding FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; try { bindings = extractBindings(struct); - } catch (UnreadableDebugInfo unreadableDebugInfo) { + } catch (UnreadableDebugInfoException unreadableDebugInfoException) { return false; } IScope binding = new BindingScope( @@ -539,21 +569,24 @@ public class Aj5Attributes { // joinpoint, staticJoinpoint binding int extraArgument = extractExtraArgument(struct.method); - Pointcut pc = null; - if (preResolvedPointcut != null) { - pc = preResolvedPointcut.getPointcut(); - } else { - pc = Pointcut.fromString(afterAdvice.getValue().stringifyValue()).resolve(binding); - } + Pointcut pc = null; + if (preResolvedPointcut != null) { + pc = preResolvedPointcut.getPointcut(); + } else { + pc = parsePointcut(afterAdvice.getValue().stringifyValue(), struct); + if (pc == null) return false;//parse error + pc.resolve(binding); + } setIgnoreUnboundBindingNames(pc, bindings); - struct.ajAttributes.add(new AjAttribute.AdviceAttribute( - AdviceKind.After, - pc, - extraArgument, - -1, - -1, - struct.context + struct.ajAttributes.add( + new AjAttribute.AdviceAttribute( + AdviceKind.After, + pc, + extraArgument, + -1, + -1, + struct.context ) ); return true; @@ -570,23 +603,17 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleAfterReturningAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - Annotation after = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.AfterReturning"); + Annotation after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERRETURNING_ANNOTATION); if (after != null) { - ElementNameValuePair annValue = getAnnotationElement(after, "value"); - ElementNameValuePair annPointcut = getAnnotationElement(after, "pointcut"); - ElementNameValuePair annReturned = getAnnotationElement(after, "returning"); + ElementNameValuePair annValue = getAnnotationElement(after, VALUE); + ElementNameValuePair annPointcut = getAnnotationElement(after, POINTCUT); + ElementNameValuePair annReturned = getAnnotationElement(after, RETURNING); // extract the pointcut and returned type/binding - do some checks String pointcut = null; String returned = null; - if ((annValue!=null && annPointcut!=null) || (annValue==null && annPointcut==null)) { - struct.handler.handleMessage( - new Message( - "@AfterReturning: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), - struct.enclosingType.getSourceLocation(), - true - ) - ); + if ((annValue != null && annPointcut != null) || (annValue == null && annPointcut == null)) { + reportError("@AfterReturning: either 'value' or 'poincut' must be provided, not both", struct); return false; } if (annValue != null) { @@ -595,16 +622,10 @@ public class Aj5Attributes { pointcut = annPointcut.getValue().stringifyValue(); } if (isNullOrEmpty(pointcut)) { - struct.handler.handleMessage( - new Message( - "@AfterReturning: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), - struct.enclosingType.getSourceLocation(), - true - ) - ); + reportError("@AfterReturning: either 'value' or 'poincut' must be provided, not both", struct); return false; } - if (annReturned!=null) { + if (annReturned != null) { returned = annReturned.getValue().stringifyValue(); if (isNullOrEmpty(returned)) returned = null; @@ -614,8 +635,8 @@ public class Aj5Attributes { // exclude the return binding from the pointcut binding since it is an extraArg binding FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; try { - bindings = (returned==null?extractBindings(struct):extractBindings(struct, returned)); - } catch (UnreadableDebugInfo unreadableDebugInfo) { + bindings = (returned == null ? extractBindings(struct) : extractBindings(struct, returned)); + } catch (UnreadableDebugInfoException unreadableDebugInfoException) { return false; } IScope binding = new BindingScope( @@ -631,22 +652,24 @@ public class Aj5Attributes { extraArgument |= Advice.ExtraArgument; } - Pointcut pc = null; - if (preResolvedPointcut != null) { - pc = preResolvedPointcut.getPointcut(); - } else { - pc = Pointcut.fromString(pointcut).resolve(binding); - } + Pointcut pc = null; + if (preResolvedPointcut != null) { + pc = preResolvedPointcut.getPointcut(); + } else { + pc = parsePointcut(pointcut, struct); + if (pc == null) return false;//parse error + pc.resolve(binding); + } setIgnoreUnboundBindingNames(pc, bindings); - pc.setLocation(struct.enclosingType.getSourceContext(), 0, 0);//TODO method location ? - - struct.ajAttributes.add(new AjAttribute.AdviceAttribute( - AdviceKind.AfterReturning, - pc, - extraArgument, - -1, - -1, - struct.context + + struct.ajAttributes.add( + new AjAttribute.AdviceAttribute( + AdviceKind.AfterReturning, + pc, + extraArgument, + -1, + -1, + struct.context ) ); return true; @@ -662,23 +685,17 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleAfterThrowingAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - Annotation after = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.AfterThrowing"); + Annotation after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERTHROWING_ANNOTATION); if (after != null) { - ElementNameValuePair annValue = getAnnotationElement(after, "value"); - ElementNameValuePair annPointcut = getAnnotationElement(after, "pointcut"); - ElementNameValuePair annThrowned = getAnnotationElement(after, "throwing"); + ElementNameValuePair annValue = getAnnotationElement(after, VALUE); + ElementNameValuePair annPointcut = getAnnotationElement(after, POINTCUT); + ElementNameValuePair annThrowned = getAnnotationElement(after, THROWING); // extract the pointcut and throwned type/binding - do some checks String pointcut = null; String throwned = null; - if ((annValue!=null && annPointcut!=null) || (annValue==null && annPointcut==null)) { - struct.handler.handleMessage( - new Message( - "@AfterThrowing: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), - struct.enclosingType.getSourceLocation(), - true - ) - ); + if ((annValue != null && annPointcut != null) || (annValue == null && annPointcut == null)) { + reportError("@AfterThrowing: either 'value' or 'poincut' must be provided, not both", struct); return false; } if (annValue != null) { @@ -687,16 +704,10 @@ public class Aj5Attributes { pointcut = annPointcut.getValue().stringifyValue(); } if (isNullOrEmpty(pointcut)) { - struct.handler.handleMessage( - new Message( - "@AfterThrowing: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), - struct.enclosingType.getSourceLocation(), - true - ) - ); + reportError("@AfterThrowing: either 'value' or 'poincut' must be provided, not both", struct); return false; } - if (annThrowned!=null) { + if (annThrowned != null) { throwned = annThrowned.getValue().stringifyValue(); if (isNullOrEmpty(throwned)) throwned = null; @@ -706,8 +717,8 @@ public class Aj5Attributes { // exclude the throwned binding from the pointcut binding since it is an extraArg binding FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; try { - bindings = (throwned==null?extractBindings(struct):extractBindings(struct, throwned)); - } catch (UnreadableDebugInfo unreadableDebugInfo) { + bindings = (throwned == null ? extractBindings(struct) : extractBindings(struct, throwned)); + } catch (UnreadableDebugInfoException unreadableDebugInfoException) { return false; } IScope binding = new BindingScope( @@ -723,21 +734,24 @@ public class Aj5Attributes { extraArgument |= Advice.ExtraArgument; } - Pointcut pc = null; - if (preResolvedPointcut != null) { - pc = preResolvedPointcut.getPointcut(); - } else { - pc = Pointcut.fromString(pointcut).resolve(binding); - } + Pointcut pc = null; + if (preResolvedPointcut != null) { + pc = preResolvedPointcut.getPointcut(); + } else { + pc = parsePointcut(pointcut, struct); + if (pc == null) return false;//parse error + pc.resolve(binding); + } setIgnoreUnboundBindingNames(pc, bindings); - struct.ajAttributes.add(new AjAttribute.AdviceAttribute( - AdviceKind.AfterThrowing, - pc, - extraArgument, - -1, - -1, - struct.context + struct.ajAttributes.add( + new AjAttribute.AdviceAttribute( + AdviceKind.AfterThrowing, + pc, + extraArgument, + -1, + -1, + struct.context ) ); return true; @@ -753,15 +767,15 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleAroundAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - Annotation around = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.Around"); + Annotation around = getAnnotation(runtimeAnnotations, AjcMemberMaker.AROUND_ANNOTATION); if (around != null) { - ElementNameValuePair aroundAdvice = getAnnotationElement(around, "value"); + ElementNameValuePair aroundAdvice = getAnnotationElement(around, VALUE); if (aroundAdvice != null) { // this/target/args binding FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; try { bindings = extractBindings(struct); - } catch (UnreadableDebugInfo unreadableDebugInfo) { + } catch (UnreadableDebugInfoException unreadableDebugInfoException) { return false; } IScope binding = new BindingScope( @@ -772,21 +786,24 @@ public class Aj5Attributes { // joinpoint, staticJoinpoint binding int extraArgument = extractExtraArgument(struct.method); - Pointcut pc = null; - if (preResolvedPointcut != null) { - pc = preResolvedPointcut.getPointcut(); - } else { - pc = Pointcut.fromString(aroundAdvice.getValue().stringifyValue()).resolve(binding); - } + Pointcut pc = null; + if (preResolvedPointcut != null) { + pc = preResolvedPointcut.getPointcut(); + } else { + pc = parsePointcut(aroundAdvice.getValue().stringifyValue(), struct); + if (pc == null) return false;//parse error + pc.resolve(binding); + } setIgnoreUnboundBindingNames(pc, bindings); - struct.ajAttributes.add(new AjAttribute.AdviceAttribute( - AdviceKind.Around, - pc, - extraArgument, - -1, - -1, - struct.context + struct.ajAttributes.add( + new AjAttribute.AdviceAttribute( + AdviceKind.Around, + pc, + extraArgument, + -1, + -1, + struct.context ) ); return true; @@ -802,36 +819,20 @@ public class Aj5Attributes { * @param struct */ private static void handlePointcutAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) { - Annotation pointcut = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.Pointcut"); + Annotation pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION); if (pointcut != null) { - ElementNameValuePair pointcutExpr = getAnnotationElement(pointcut, "value"); + ElementNameValuePair pointcutExpr = getAnnotationElement(pointcut, VALUE); if (pointcutExpr != null) { // semantic check: the method must return void if (!Type.VOID.equals(struct.method.getReturnType())) { - struct.handler.handleMessage( - new Message( - "Found @Pointcut on a method not returning void '" + methodToString(struct.method) + "'", - IMessage.WARNING, - null, - struct.enclosingType.getSourceLocation()//TODO method loc instead how ? - ) - ); - //TODO AV : Andy - should we stop ? - return; + reportWarning("Found @Pointcut on a method not returning void", struct); + ;//no need to stop } // semantic check: the method must not throw anything if (struct.method.getExceptionTable() != null) { - struct.handler.handleMessage( - new Message( - "Found @Pointcut on a method throwing exception '" + methodToString(struct.method) + "'", - IMessage.WARNING, - null, - struct.enclosingType.getSourceLocation()//TODO method loc instead how ? - ) - ); - //TODO AV : Andy - should we stop ? - return; + reportWarning("Found @Pointcut on a method throwing exception", struct); + ;// no need to stop } // this/target/args binding @@ -841,7 +842,7 @@ public class Aj5Attributes { struct.enclosingType, extractBindings(struct) ); - } catch(UnreadableDebugInfo e) { + } catch (UnreadableDebugInfoException e) { return; } @@ -852,28 +853,22 @@ public class Aj5Attributes { // use a LazyResolvedPointcutDefinition so that the pointcut is resolved lazily // since for it to be resolved, we will need other pointcuts to be registered as well - try { - struct.ajAttributes.add(new AjAttribute.PointcutDeclarationAttribute( - new LazyResolvedPointcutDefinition( - struct.enclosingType, - struct.method.getModifiers(), - struct.method.getName(), - argumentTypes, - Pointcut.fromString(pointcutExpr.getValue().stringifyValue()), - binding - ) - )); - } catch (ParserException e) { - struct.handler.handleMessage( - new Message( - "Cannot parse @Pointcut '" + pointcutExpr.getValue().stringifyValue() + "'", - IMessage.ERROR, - e, - struct.enclosingType.getSourceLocation()//TODO method loc instead how ? - ) - ); - return; - } + Pointcut pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct); + if (pc == null) return;//parse error + // do not resolve binding now but lazily + pc.setLocation(struct.context, -1, -1); + struct.ajAttributes.add( + new AjAttribute.PointcutDeclarationAttribute( + new LazyResolvedPointcutDefinition( + struct.enclosingType, + struct.method.getModifiers(), + struct.method.getName(), + argumentTypes, + pc, + binding + ) + ) + ); } } } @@ -886,18 +881,13 @@ public class Aj5Attributes { * @return true if found */ private static boolean handleDeclareErrorOrWarningAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) { - Annotation error = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.DeclareError"); + Annotation error = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREERROR_ANNOTATION); boolean hasError = false; if (error != null) { - ElementNameValuePair declareError = getAnnotationElement(error, "value"); + ElementNameValuePair declareError = getAnnotationElement(error, VALUE); if (declareError != null) { - if (!"Ljava/lang/String;".equals(struct.field.getSignature()) || struct.field.getConstantValue()==null) { - struct.handler.handleMessage( - new Message( - "@DeclareError used on a non String constant field " + fieldToString(struct.field), - struct.enclosingType.getSourceLocation(), - true - )); + if (!STRING_DESC.equals(struct.field.getSignature()) || struct.field.getConstantValue() == null) { + reportError("@DeclareError used on a non String constant field", struct); return false; } FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; @@ -905,25 +895,25 @@ public class Aj5Attributes { struct.enclosingType, bindings ); - Pointcut pc = Pointcut.fromString(declareError.getValue().stringifyValue()).resolve(binding); - struct.ajAttributes.add(new AjAttribute.DeclareAttribute( - new DeclareErrorOrWarning(true, pc, struct.field.getConstantValue().toString()) - )); - return hasError = true; + Pointcut pc = parsePointcut(declareError.getValue().stringifyValue(), struct); + if (pc == null) { + hasError = false;//cannot parse pointcut + } else { + pc .resolve(binding); + DeclareErrorOrWarning deow = new DeclareErrorOrWarning(true, pc, struct.field.getConstantValue().toString()); + deow.setLocation(struct.context, -1, -1); + struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow)); + hasError = true; + } } } - Annotation warning = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.DeclareWarning"); + Annotation warning = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREWARNING_ANNOTATION); boolean hasWarning = false; if (warning != null) { - ElementNameValuePair declareWarning = getAnnotationElement(warning, "value"); + ElementNameValuePair declareWarning = getAnnotationElement(warning, VALUE); if (declareWarning != null) { - if (!"Ljava/lang/String;".equals(struct.field.getSignature()) || struct.field.getConstantValue()==null) { - struct.handler.handleMessage( - new Message( - "@DeclareWarning used on a non String constant field " + fieldToString(struct.field), - struct.enclosingType.getSourceLocation(), - true - )); + if (!STRING_DESC.equals(struct.field.getSignature()) || struct.field.getConstantValue() == null) { + reportError("@DeclareWarning used on a non String constant field", struct); return false; } FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; @@ -931,11 +921,16 @@ public class Aj5Attributes { struct.enclosingType, bindings ); - Pointcut pc = Pointcut.fromString(declareWarning.getValue().stringifyValue()).resolve(binding); - struct.ajAttributes.add(new AjAttribute.DeclareAttribute( - new DeclareErrorOrWarning(false, pc, struct.field.getConstantValue().toString()) - )); - return hasWarning = true; + Pointcut pc = parsePointcut(declareWarning.getValue().stringifyValue(), struct); + if (pc == null) { + hasWarning = false;//cannot parse pointcut + } else { + pc.resolve(binding); + DeclareErrorOrWarning deow = new DeclareErrorOrWarning(false, pc, struct.field.getConstantValue().toString()); + deow.setLocation(struct.context, -1, -1); + struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow)); + return hasWarning = true; + } } } return hasError || hasWarning; @@ -976,22 +971,14 @@ public class Aj5Attributes { * @return null if no debug info is available */ private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct) - throws UnreadableDebugInfo { + throws UnreadableDebugInfoException { Method method = struct.method; String[] argumentNames = struct.getArgumentNames(); // assert debug info was here if (argumentNames.length != method.getArgumentTypes().length) { - struct.handler.handleMessage( - new Message( - "Cannot read debug info for @Aspect '" + struct.enclosingType.getName() + "'" - + " (please compile with 'javac -g' or '' in Ant)", - IMessage.FAIL, - null, - struct.enclosingType.getSourceLocation() - ) - ); - throw new UnreadableDebugInfo(); + reportError("Cannot read debug info for @Aspect to handle formal binding in pointcuts (please compile with 'javac -g' or '' in Ant)", struct); + throw new UnreadableDebugInfoException(); } List bindings = new ArrayList(); @@ -1002,11 +989,11 @@ public class Aj5Attributes { // do not bind JoinPoint / StaticJoinPoint / EnclosingStaticJoinPoint // TODO solve me : this means that the JP/SJP/ESJP cannot appear as binding // f.e. when applying advice on advice etc - if ((TYPEX_JOINPOINT.equals(argumentType) - || TYPEX_PROCEEDINGJOINPOINT.equals(argumentType) - || TYPEX_STATICJOINPOINT.equals(argumentType) - || TYPEX_ENCLOSINGSTATICJOINPOINT.equals(argumentType) - || AjcMemberMaker.AROUND_CLOSURE_TYPE.equals(argumentType))) { + if ((AjcMemberMaker.TYPEX_JOINPOINT.equals(argumentType) + || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.equals(argumentType) + || AjcMemberMaker.TYPEX_STATICJOINPOINT.equals(argumentType) + || AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.equals(argumentType) + || AjcMemberMaker.AROUND_CLOSURE_TYPE.equals(argumentType))) { //continue;// skip bindings.add(new FormalBinding.ImplicitFormalBinding(argumentType, argumentName, i)); } else { @@ -1019,14 +1006,16 @@ public class Aj5Attributes { //FIXME alex deal with exclude index private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct, String excludeFormal) - throws UnreadableDebugInfo { + throws UnreadableDebugInfoException { FormalBinding[] bindings = extractBindings(struct); int excludeIndex = -1; for (int i = 0; i < bindings.length; i++) { FormalBinding binding = bindings[i]; if (binding.getName().equals(excludeFormal)) { excludeIndex = i; - bindings[i] = new FormalBinding.ImplicitFormalBinding(binding.getType(), binding.getName(), binding.getIndex()); + bindings[i] = new FormalBinding.ImplicitFormalBinding( + binding.getType(), binding.getName(), binding.getIndex() + ); break; } } @@ -1061,13 +1050,13 @@ public class Aj5Attributes { Type[] methodArgs = method.getArgumentTypes(); for (int i = 0; i < methodArgs.length; i++) { String methodArg = methodArgs[i].getSignature(); - if (TYPEX_JOINPOINT.getSignature().equals(methodArg)) { + if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(methodArg)) { extraArgument |= Advice.ThisJoinPoint; - } else if (TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(methodArg)) { + } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(methodArg)) { extraArgument |= Advice.ThisJoinPoint; - } else if (TYPEX_STATICJOINPOINT.getSignature().equals(methodArg)) { + } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(methodArg)) { extraArgument |= Advice.ThisJoinPointStaticPart; - } else if (TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(methodArg)) { + } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(methodArg)) { extraArgument |= Advice.ThisEnclosingJoinPointStaticPart; } } @@ -1081,10 +1070,11 @@ public class Aj5Attributes { * @param annotationType * @return */ - private static Annotation getAnnotation(RuntimeAnnotations rvs, String annotationType) { + private static Annotation getAnnotation(RuntimeAnnotations rvs, TypeX annotationType) { + final String annotationTypeName = annotationType.getName(); for (Iterator iterator = rvs.getAnnotations().iterator(); iterator.hasNext();) { Annotation rv = (Annotation) iterator.next(); - if (annotationType.equals(rv.getTypeName())) { + if (annotationTypeName.equals(rv.getTypeName())) { return rv; } } @@ -1121,7 +1111,7 @@ public class Aj5Attributes { return EMPTY_STRINGS; } - final int startAtStackIndex = method.isStatic()?0:1; + final int startAtStackIndex = method.isStatic() ? 0 : 1; final List arguments = new ArrayList(); LocalVariableTable lt = (LocalVariableTable) method.getLocalVariableTable(); if (lt != null) { @@ -1136,24 +1126,25 @@ public class Aj5Attributes { } if (arguments.size() != method.getArgumentTypes().length) { - //throw new RuntimeException("cannot access debug info on " + method); return EMPTY_STRINGS; } // sort by index - Collections.sort(arguments, new Comparator() { - public int compare(Object o, Object o1) { - MethodArgument mo = (MethodArgument)o; - MethodArgument mo1 = (MethodArgument) o1; - if (mo.indexOnStack == mo1.indexOnStack) { - return 0; - } else if (mo.indexOnStack > mo1.indexOnStack) { - return 1; - } else { - return -1; + Collections.sort( + arguments, new Comparator() { + public int compare(Object o, Object o1) { + MethodArgument mo = (MethodArgument) o; + MethodArgument mo1 = (MethodArgument) o1; + if (mo.indexOnStack == mo1.indexOnStack) { + return 0; + } else if (mo.indexOnStack > mo1.indexOnStack) { + return 1; + } else { + return -1; + } + } } - } - }); + ); String[] argumentNames = new String[arguments.size()]; int i = 0; for (Iterator iterator = arguments.iterator(); iterator.hasNext(); i++) { @@ -1171,6 +1162,7 @@ public class Aj5Attributes { private static class MethodArgument { String name; int indexOnStack; + public MethodArgument(String name, int indexOnStack) { this.name = name; this.indexOnStack = indexOnStack; @@ -1212,7 +1204,6 @@ public class Aj5Attributes { super(declaringType, modifiers, name, parameterTypes, null); m_pointcutUnresolved = pointcut; m_binding = binding; - m_pointcutUnresolved.setLocation(declaringType.getSourceContext(), 0, 0); } public Pointcut getPointcut() { @@ -1226,11 +1217,12 @@ public class Aj5Attributes { /** * Helper to test empty strings + * * @param s * @return */ private static boolean isNullOrEmpty(String s) { - return (s==null || s.length()<=0); + return (s == null || s.length() <= 0); } /** @@ -1250,12 +1242,84 @@ public class Aj5Attributes { ignores.add(formalBinding.getName()); } } - pointcut.m_ignoreUnboundBindingForNames = (String[])ignores.toArray(new String[ignores.size()]); + pointcut.m_ignoreUnboundBindingForNames = (String[]) ignores.toArray(new String[ignores.size()]); } /** * A check exception when we cannot read debug info (needed for formal binding) */ - private static class UnreadableDebugInfo extends Exception { + private static class UnreadableDebugInfoException extends Exception { + } + + /** + * Report an error + * + * @param message + * @param location + */ + private static void reportError(String message, AjAttributeStruct location) { + if (!location.handler.isIgnoring(IMessage.ERROR)) { + location.handler.handleMessage( + new Message( + message, + location.enclosingType.getSourceLocation(), + true + ) + ); + } + } + + /** + * Report a warning + * + * @param message + * @param location + */ + private static void reportWarning(String message, AjAttributeStruct location) { + if (!location.handler.isIgnoring(IMessage.WARNING)) { + location.handler.handleMessage( + new Message( + message, + location.enclosingType.getSourceLocation(), + false + ) + ); + } + } + + /** + * Parse the given pointcut, return null on failure and issue an error + * + * @param pointcutString + * @param location + * @return + */ + private static Pointcut parsePointcut(String pointcutString, AjAttributeStruct location) { + try { + Pointcut pointcut = Pointcut.fromString(pointcutString); + pointcut.setLocation(location.context, -1, -1);//FIXME -1,-1 is not good enough + return pointcut; + } catch (ParserException e) { + reportError("Invalid pointcut '" + pointcutString + "' : " + e.getLocation(), location); + return null; + } + } + + /** + * Parse the given type pattern, return null on failure and issue an error + * + * @param patternString + * @param location + * @return + */ + private static TypePattern parseTypePattern(String patternString, AjAttributeStruct location) { + try { + TypePattern typePattern = new PatternParser(patternString).parseTypePattern(); + typePattern.setLocation(location.context, -1, -1);//FIXME -1,-1 is not good enough + return typePattern; + } catch (ParserException e) { + reportError("Invalid type pattern'" + patternString + "' : " + e.getLocation(), location); + return null; + } } } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java index 1fa87d1b0..3dc487853 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java @@ -37,7 +37,6 @@ import org.aspectj.weaver.TypeX; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.World; import org.aspectj.weaver.PerObjectInterfaceTypeMunger; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; import org.aspectj.weaver.ast.Literal; import org.aspectj.weaver.ast.Test; import org.aspectj.weaver.patterns.ExactTypePattern; @@ -362,7 +361,7 @@ public class BcelAdvice extends Advice { if (v == null) { // if not @AJ aspect, go on with the regular binding handling - if (!Ajc5MemberMaker.isAnnotationStyleAspect(getConcreteAspect())) { + if (!getConcreteAspect().isAnnotationStyleAspect()) { continue; } else { // ATAJ: for @AJ aspects, handle implicit binding of xxJoinPoint @@ -408,7 +407,7 @@ public class BcelAdvice extends Advice { // ATAJ: for code style aspect, handles the extraFlag as usual ie not // in the middle of the formal bindings but at the end, in a rock solid ordering - if (!Ajc5MemberMaker.isAnnotationStyleAspect(getConcreteAspect())) { + if (!getConcreteAspect().isAnnotationStyleAspect()) { if (getKind() == AdviceKind.Around) { il.append(closureInstantiation); } else if (hasExtraParameter()) { diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelField.java b/weaver/src/org/aspectj/weaver/bcel/BcelField.java index ee8d51bc5..98789df08 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelField.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelField.java @@ -27,7 +27,6 @@ import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.TypeX; import org.aspectj.weaver.World; -import org.aspectj.weaver.ataspectj.Aj5Attributes; final class BcelField extends ResolvedMember { @@ -56,7 +55,7 @@ final class BcelField extends ResolvedMember { private void unpackAttributes(World world) { Attribute[] attrs = field.getAttributes(); List as = BcelAttributes.readAjAttributes(getDeclaringType().getClassName(),attrs, getSourceContext(world),world.getMessageHandler()); - as.addAll(Aj5Attributes.readAj5FieldAttributes(field, world.resolve(getDeclaringType()), getSourceContext(world), world.getMessageHandler())); + as.addAll(AtAjAttributes.readAj5FieldAttributes(field, world.resolve(getDeclaringType()), getSourceContext(world), world.getMessageHandler())); for (Iterator iter = as.iterator(); iter.hasNext();) { AjAttribute a = (AjAttribute) iter.next(); diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java index a8c629992..ca4dfaaa4 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java @@ -34,7 +34,6 @@ import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.ShadowMunger; import org.aspectj.weaver.TypeX; import org.aspectj.weaver.World; -import org.aspectj.weaver.ataspectj.Aj5Attributes; final class BcelMethod extends ResolvedMember { @@ -101,7 +100,7 @@ final class BcelMethod extends ResolvedMember { associatedShadowMunger = null; List as = BcelAttributes.readAjAttributes(getDeclaringType().getClassName(),method.getAttributes(), getSourceContext(world),world.getMessageHandler()); processAttributes(world, as); - as = Aj5Attributes.readAj5MethodAttributes(method, world.resolve(getDeclaringType()), preResolvedPointcut,getSourceContext(world), world.getMessageHandler()); + as = AtAjAttributes.readAj5MethodAttributes(method, world.resolve(getDeclaringType()), preResolvedPointcut,getSourceContext(world), world.getMessageHandler()); processAttributes(world,as); } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java index 862b2a65b..75c46d5dd 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java @@ -36,9 +36,8 @@ import org.aspectj.weaver.ResolvedPointcutDefinition; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.TypeX; import org.aspectj.weaver.WeaverStateInfo; +import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.patterns.PerClause; -import org.aspectj.weaver.ataspectj.Aj5Attributes; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; // ??? exposed for testing @@ -186,7 +185,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { public boolean isAnnotationStyleAspect() { if (!discoveredWhetherAnnotationStyle) { discoveredWhetherAnnotationStyle = true; - isAnnotationStyleAspect = !isCodeStyleAspect && hasAnnotation(Ajc5MemberMaker.ASPECT); + isAnnotationStyleAspect = !isCodeStyleAspect && hasAnnotation(AjcMemberMaker.ASPECT_ANNOTATION); } return isAnnotationStyleAspect; } @@ -198,7 +197,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { // Pass in empty list that can store things for readAj5 to process List l = BcelAttributes.readAjAttributes(javaClass.getClassName(),javaClass.getAttributes(), getResolvedTypeX().getSourceContext(),getResolvedTypeX().getWorld().getMessageHandler()); processAttributes(l,pointcuts,false); - l = Aj5Attributes.readAj5ClassAttributes(javaClass, getResolvedTypeX(), getResolvedTypeX().getSourceContext(), getResolvedTypeX().getWorld().getMessageHandler(),isCodeStyleAspect); + l = AtAjAttributes.readAj5ClassAttributes(javaClass, getResolvedTypeX(), getResolvedTypeX().getSourceContext(), getResolvedTypeX().getWorld().getMessageHandler(),isCodeStyleAspect); processAttributes(l,pointcuts,true); this.pointcuts = (ResolvedPointcutDefinition[]) diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index f41cce965..4bc3daf92 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -74,7 +74,6 @@ import org.aspectj.weaver.TypeX; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.World; import org.aspectj.weaver.ast.Var; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; /* @@ -2549,8 +2548,7 @@ public class BcelShadow extends Shadow { } // ATAJ for @AJ aspect we need to link the closure with the joinpoint instance - if (Ajc5MemberMaker.isAnnotationStyleAspect(munger.getConcreteAspect())) { - //advice.append(new POP()); + if (munger.getConcreteAspect().isAnnotationStyleAspect()) { closureInstantiation.append(Utility.createInvoke( getFactory(), getWorld(), @@ -2563,12 +2561,9 @@ public class BcelShadow extends Shadow { ) )); } - //System.err.println(closureInstantiation); - InstructionList advice = new InstructionList(); advice.append(munger.getAdviceArgSetup(this, null, closureInstantiation)); -// advice.append(closureInstantiation); // invoke the advice advice.append(munger.getNonTestAdviceInstructions(this)); diff --git a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java index f9d97a936..73eef47d7 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java @@ -35,7 +35,6 @@ import org.aspectj.weaver.TypeX; import org.aspectj.weaver.VersionedDataInputStream; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; import org.aspectj.weaver.ast.Expr; import org.aspectj.weaver.ast.Test; @@ -106,7 +105,7 @@ public class PerCflow extends PerClause { } //ATAJ inline around advice support - don't use a late munger to allow around inling for itself - if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) { + if (inAspect.isAnnotationStyleAspect()) { inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerObject.java b/weaver/src/org/aspectj/weaver/patterns/PerObject.java index 3ec3addeb..31eef9ade 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerObject.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerObject.java @@ -30,7 +30,6 @@ import org.aspectj.weaver.Shadow; import org.aspectj.weaver.VersionedDataInputStream; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; import org.aspectj.weaver.ast.Expr; import org.aspectj.weaver.ast.Test; import org.aspectj.weaver.ast.Var; @@ -119,7 +118,7 @@ public class PerObject extends PerClause { } //ATAJ inline around advice support - don't use a late munger to allow around inling for itself - if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) { + if (inAspect.isAnnotationStyleAspect()) { inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java index bf390fa6e..385f9175c 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java @@ -27,7 +27,6 @@ import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; import org.aspectj.weaver.ast.Expr; import org.aspectj.weaver.ast.Literal; import org.aspectj.weaver.ast.Test; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; public class PerSingleton extends PerClause { public PerSingleton() { @@ -97,7 +96,7 @@ public class PerSingleton extends PerClause { ret.inAspect = inAspect; //ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects - if (!inAspect.isAbstract() && Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) { + if (!inAspect.isAbstract() && inAspect.isAnnotationStyleAspect()) { //TODO will those change be ok if we add a serializable aspect ? // dig: "can't be Serializable/Cloneable unless -XserializableAspects" inAspect.crosscuttingMembers.addLateTypeMunger( @@ -106,7 +105,7 @@ public class PerSingleton extends PerClause { } //ATAJ inline around advice support - if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) { + if (inAspect.isAnnotationStyleAspect()) { inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java index 59c4169b7..651d192a3 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java @@ -33,7 +33,6 @@ import org.aspectj.weaver.Shadow; import org.aspectj.weaver.VersionedDataInputStream; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; import org.aspectj.weaver.ast.Expr; import org.aspectj.weaver.ast.Literal; import org.aspectj.weaver.ast.Test; @@ -156,7 +155,7 @@ public class PerTypeWithin extends PerClause { } //ATAJ inline around advice support - don't use a late munger to allow around inling for itself - if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) { + if (inAspect.isAnnotationStyleAspect()) { inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); } diff --git a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java index a1bf961cd..67bd70f3c 100644 --- a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java +++ b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java @@ -37,7 +37,6 @@ import org.aspectj.util.FileUtil; import org.aspectj.weaver.IClassFileProvider; import org.aspectj.weaver.IWeaveRequestor; import org.aspectj.weaver.ResolvedTypeX; -import org.aspectj.weaver.ataspectj.Ajc5MemberMaker; import org.aspectj.weaver.bcel.BcelWeaver; import org.aspectj.weaver.bcel.BcelWorld; import org.aspectj.weaver.bcel.UnwovenClassFile; @@ -209,7 +208,7 @@ public class WeavingAdaptor { */ private boolean shouldWeaveAspect (String name) { ResolvedTypeX type = bcelWorld.resolve(name); - return (type == null || !type.isAspect() || Ajc5MemberMaker.isAnnotationStyleAspect(type)); + return (type == null || !type.isAspect() || type.isAnnotationStyleAspect()); } /** -- 2.39.5