From 49c3978146a3e1d303a5d7f520c906acbfebe9bd Mon Sep 17 00:00:00 2001 From: avasseur Date: Thu, 19 May 2005 13:39:20 +0000 Subject: [PATCH] deow @AJ + @AfterXX annotation warnings + test + JDWP sample for LTW tests + some AJ5 doc fix --- .../aspectj/lang/annotation/DeclareError.java | 8 +- .../lang/annotation/DeclareWarning.java | 8 +- docs/adk15ProgGuideDB/ataspectj.xml | 94 ++++------ docs/adk15ProgGuideDB/ltw.xml | 23 ++- tests/java5/ataspectj/ajc-ant.xml | 4 +- .../ataspectj/ataspectj/misuse/Test014.java | 35 +++- .../systemtest/ajc150/AllTestsAspectJ150.java | 3 +- .../systemtest/ajc150/ataspectj/misuse.xml | 8 +- .../weaver/ataspectj/Aj5Attributes.java | 175 +++++++++++++++++- 9 files changed, 277 insertions(+), 81 deletions(-) diff --git a/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareError.java b/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareError.java index 803118de1..9f3a045ee 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareError.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareError.java @@ -20,12 +20,14 @@ import java.lang.annotation.Target; * @author colyer * Annotation for declare error... * - * usage: - * @DeclareError("somePcut()") - * private static final String "a message"; + * usage: @DeclareError("somePcut()") + * private static final String "a message"; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface DeclareError { + /** + * The pointcut expression where to bind the error (don't use if, formal bindings, cflow etc) + */ String value(); } diff --git a/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareWarning.java b/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareWarning.java index ba3d11eb7..446ac786a 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareWarning.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareWarning.java @@ -20,12 +20,14 @@ import java.lang.annotation.Target; * @author colyer * Annotation for declare warning... * - * usage: - * @DeclareWarning("somePcut()") - * private static final String "a message"; + * usage: @DeclareWarning("somePcut()") + * private static final String "a message"; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface DeclareWarning { + /** + * The pointcut expression where to bind the error (don't use if, formal bindings, cflow etc) + */ String value(); } diff --git a/docs/adk15ProgGuideDB/ataspectj.xml b/docs/adk15ProgGuideDB/ataspectj.xml index 080199054..b3986ef90 100644 --- a/docs/adk15ProgGuideDB/ataspectj.xml +++ b/docs/adk15ProgGuideDB/ataspectj.xml @@ -51,8 +51,8 @@ public aspect Foo {} ]]> - Privileged aspects are declared as: - + Privileged aspects are not supported by the annotation style + To specify an aspect an aspect instantiation model (the default is - singleton), use the instantionModel and - perClausePattern attributes. For example: + singleton), provide the perclause as the @Aspect value. + For example: - - The full definitions of the Aspect annotation type and the - AspectInstantiationModel enumerated type are: - - @@ -286,9 +257,9 @@ thisJoinPointStaticPart, thisEnclosingJoinPointStaticPart then these need to be declared as additional method parameters when using the annotation - style. In AspectJ 1.5.0 we require that these parameters be declared + style. @@ -402,26 +373,28 @@ @@ -587,22 +560,32 @@ (This is the same behaviour as when using declare warning or error with the code style). Declare warning and error declarations are made by annotating a string constant whose value is the message to be issued. - + + Note that the String must be a constant and not the result of the invocation + of a static method for example. + @@ -646,10 +629,13 @@ public static boolean hasAspect(Object anAspect, Class forType) {...} } ]]> - + + + diff --git a/docs/adk15ProgGuideDB/ltw.xml b/docs/adk15ProgGuideDB/ltw.xml index 1f0bb9d8a..8b6f027bb 100644 --- a/docs/adk15ProgGuideDB/ltw.xml +++ b/docs/adk15ProgGuideDB/ltw.xml @@ -38,6 +38,8 @@ need to specify the -Xreweavable compiler option when building them. This causes AspectJ to save additional state in the class files that is used to support subsequent reweaving. + As per AspectJ 1.5.0 M3 aspects (code style or annotation style) are + reweavable by default, and weaved classes may be as well in 1.5.0 final. @@ -92,6 +94,7 @@ Command line + AspectJ includes a script "aj" that allows programs executed at the command line to take advantage of load-time weaving. The script is customized when AspectJ is installed depending on the chosen @@ -207,6 +210,7 @@ found on the search path (regular getResourceAsStream lookup) according to the following rules: + The set of available aspects is the set of all declared and defined aspects (aspect and concrete-aspect elements of the aspects @@ -284,6 +288,12 @@ Performance optimization for aspects making use of thisJoinPoint (non-static parts) + + + -Xlint, -Xlint:ignore, ... + + Configure lint messages + -nowarn, -warn:none @@ -311,7 +321,7 @@ - -Xnoinline + -XnoInline Don't inline around advice. @@ -323,9 +333,14 @@ - -XmessageHolderClass + -XmessageHolderClass:... - Provide alternative output destination to stderr for all weaver messages + Provide alternative output destination to stdout/stderr for all weaver messages. + The given value must be the full qualified class name of a class that implements + org.aspectj.weaver.loadtime + and that is visible from where the aop.xml is packed. + If more than one such options are used, + the first occurence only is taken into account. @@ -345,7 +360,7 @@ JVMTI When using JDK 1.5 the JVMTI agent can be used by starting the JVM with the - following option: + following option (adapt according to the path to aspectjweaver.jar): diff --git a/tests/java5/ataspectj/ajc-ant.xml b/tests/java5/ataspectj/ajc-ant.xml index ab0e52437..ce5351563 100644 --- a/tests/java5/ataspectj/ajc-ant.xml +++ b/tests/java5/ataspectj/ajc-ant.xml @@ -1,9 +1,10 @@ + + value="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/> @@ -35,6 +36,7 @@ + diff --git a/tests/java5/ataspectj/ataspectj/misuse/Test014.java b/tests/java5/ataspectj/ataspectj/misuse/Test014.java index 9e135a93c..d3d468fb7 100644 --- a/tests/java5/ataspectj/ataspectj/misuse/Test014.java +++ b/tests/java5/ataspectj/ataspectj/misuse/Test014.java @@ -5,7 +5,36 @@ import org.aspectj.lang.annotation.*; @Aspect public class Test014{ - @Pointcut("call%dddd\n\n\n\n\n\n\n\n\n\n\n%dwdwudwdwbuill817pe;][{\ngrgrgnjk78877&&<:{{{+=``\"") - void somecall(){ - } + @Pointcut("call%dddd\n\n\n\n\n\n\n\n\n\n\n%dwdwudwdwbuill817pe;][{\ngrgrgnjk78877&&<:{{{+=``\"") + public void somecall(){ + } + + @Before("fhfh()") + public void beforeA() {} + + @After("fhfh()") + public void afterA() {} + + @Around("fhfh()") + public Object aroundA() {return null;} + + @AfterThrowing(value = "fhfh()", pointcut = "wups()") + public void afterAT2() {} + + @AfterThrowing("fhfh()") + public void afterAT() {} + + @AfterReturning(value = "fhfh()", pointcut = "wups()") + public void afterAR2() {} + + @AfterReturning("fhfh()") + public void afterAR() {} + + @DeclareError("execution(* Foo.bar())") + private int X; + + @DeclareWarning("execution(* Foo.bar())") + private final static String X2 = getX2(); + + static String getX2() {return "not supported";} } diff --git a/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java b/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java index 691a77a19..6069f845a 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java +++ b/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java @@ -48,8 +48,7 @@ public class AllTestsAspectJ150 { suite.addTest(GenericsTests.suite()); suite.addTest(AtAjSyntaxTests.suite()); suite.addTest(AtAjMisuseTests.suite()); - //FIXME AV - #75442 - //suite.addTest(AtAjLTWTests.suite()); + suite.addTest(AtAjLTWTests.suite()); //$JUnit-END$ return suite; } diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml index 5427a4a2c..3b0731189 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml @@ -38,8 +38,14 @@ line is enclosing class - TBD - + + + + + + + diff --git a/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java b/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java index a9502994a..15896cbc6 100644 --- a/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java +++ b/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java @@ -54,6 +54,8 @@ 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; /** * Annotation defined aspect reader. @@ -127,6 +129,21 @@ public class Aj5Attributes { } } + /** + * A struct when we read @AJ on field + * + * @author Alexandre Vasseur + */ + private static class AjAttributeFieldStruct extends AjAttributeStruct { + + final Field field; + + public AjAttributeFieldStruct(Field field, ResolvedTypeX type, ISourceContext sourceContext, IMessageHandler messageHandler) { + super(type, sourceContext, messageHandler); + this.field = field; + } + } + /** * Annotations are RuntimeVisible only. This allow us to not visit RuntimeInvisible ones. * @@ -206,15 +223,15 @@ public class Aj5Attributes { // in order to be able to resolve the pointcut references later on //FIXME alex loop over class super class //FIXME alex can that be too slow ? - for (int m = 0; m < javaClass.getMethods().length; m++) { - Method method = javaClass.getMethods()[m]; + 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... //FIXME alex optimize, this method struct will gets recreated for advice extraction AjAttributeMethodStruct mstruct = new AjAttributeMethodStruct(method, type, context, msgHandler); Attribute[] mattributes = method.getAttributes(); - for (int i = 0; i < mattributes.length; i++) { - Attribute mattribute = mattributes[i]; + for (int j = 0; j < mattributes.length; j++) { + Attribute mattribute = mattributes[j]; if (acceptAttribute(mattribute)) { RuntimeAnnotations mrvs = (RuntimeAnnotations) mattribute; handlePointcutAnnotation(mrvs, mstruct); @@ -224,6 +241,40 @@ public class Aj5Attributes { } struct.ajAttributes.addAll(mstruct.ajAttributes); } + + + // 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... + //FIXME alex optimize, this method struct will gets recreated for advice extraction + AjAttributeFieldStruct fstruct = new AjAttributeFieldStruct(field, type, context, msgHandler); + Attribute[] fattributes = field.getAttributes(); + + for (int j = 0; j < fattributes.length; j++) { + Attribute fattribute = fattributes[j]; + if (acceptAttribute(fattribute)) { + RuntimeAnnotations frvs = (RuntimeAnnotations) fattribute; + if (handleDeclareErrorOrWarningAnnotation(frvs, fstruct)) { + // semantic check - must be in an @Aspect [remove if previous block bypassed in advance] + if (!type.isAnnotationStyleAspect()) { + msgHandler.handleMessage( + new Message( + "Found @AspectJ annotations in a non @Aspect type '" + type.getName() + "'", + IMessage.WARNING, + null, + type.getSourceLocation() + ) + ); + ;// go ahead + } + } + // there can only be one RuntimeVisible bytecode attribute + break; + } + } + struct.ajAttributes.addAll(fstruct.ajAttributes); + } return struct.ajAttributes; } @@ -315,8 +366,7 @@ public class Aj5Attributes { * @return list of AjAttributes, always empty for now */ public static List readAj5FieldAttributes(Field field, ResolvedTypeX type, ISourceContext context,IMessageHandler msgHandler) { - if (field.getName().startsWith(NameMangler.PREFIX)) return Collections.EMPTY_LIST; // already dealt with by ajc... - return EMPTY_LIST; + return Collections.EMPTY_LIST; } /** @@ -530,7 +580,14 @@ public class Aj5Attributes { String pointcut = null; String returned = null; if ((annValue!=null && annPointcut!=null) || (annValue==null && annPointcut==null)) { - throw new RuntimeException("AfterReturning at most value or pointcut must be filled"); + struct.handler.handleMessage( + new Message( + "@AfterReturning: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), + struct.enclosingType.getSourceLocation(), + true + ) + ); + return false; } if (annValue != null) { pointcut = annValue.getValue().stringifyValue(); @@ -538,7 +595,14 @@ public class Aj5Attributes { pointcut = annPointcut.getValue().stringifyValue(); } if (isNullOrEmpty(pointcut)) { - throw new RuntimeException("AfterReturning pointcut unspecified"); + struct.handler.handleMessage( + new Message( + "@AfterReturning: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), + struct.enclosingType.getSourceLocation(), + true + ) + ); + return false; } if (annReturned!=null) { returned = annReturned.getValue().stringifyValue(); @@ -608,7 +672,14 @@ public class Aj5Attributes { String pointcut = null; String throwned = null; if ((annValue!=null && annPointcut!=null) || (annValue==null && annPointcut==null)) { - throw new RuntimeException("AfterReturning at most value or pointcut must be filled"); + struct.handler.handleMessage( + new Message( + "@AfterThrowing: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), + struct.enclosingType.getSourceLocation(), + true + ) + ); + return false; } if (annValue != null) { pointcut = annValue.getValue().stringifyValue(); @@ -616,7 +687,14 @@ public class Aj5Attributes { pointcut = annPointcut.getValue().stringifyValue(); } if (isNullOrEmpty(pointcut)) { - throw new RuntimeException("AfterReturning pointcut unspecified"); + struct.handler.handleMessage( + new Message( + "@AfterThrowing: either 'value' or 'poincut' must be provided, not both: " + methodToString(struct.method), + struct.enclosingType.getSourceLocation(), + true + ) + ); + return false; } if (annThrowned!=null) { throwned = annThrowned.getValue().stringifyValue(); @@ -800,6 +878,69 @@ public class Aj5Attributes { } } + /** + * Read @DeclareError, @DeclareWarning + * + * @param runtimeAnnotations + * @param struct + * @return true if found + */ + private static boolean handleDeclareErrorOrWarningAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) { + Annotation error = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.DeclareError"); + boolean hasError = false; + if (error != null) { + 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 + )); + return false; + } + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + IScope binding = new BindingScope( + 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; + } + } + Annotation warning = getAnnotation(runtimeAnnotations, "org.aspectj.lang.annotation.DeclareWarning"); + boolean hasWarning = false; + if (warning != null) { + 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 + )); + return false; + } + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + IScope binding = new BindingScope( + 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; + } + } + return hasError || hasWarning; + } + /** * Returns a readable representation of a method. * Method.toString() is not suitable. @@ -814,6 +955,20 @@ public class Aj5Attributes { return sb.toString(); } + /** + * Returns a readable representation of a field. + * Field.toString() is not suitable. + * + * @param field + * @return + */ + private static String fieldToString(Field field) { + StringBuffer sb = new StringBuffer(); + sb.append(field.getName()).append(' '); + sb.append(field.getSignature()); + return sb.toString(); + } + /** * Build the bindings for a given method (pointcut / advice) * -- 2.39.5