diff options
author | Alexander Kriegisch <Alexander@Kriegisch.name> | 2021-04-10 19:19:39 +0700 |
---|---|---|
committer | Alexander Kriegisch <Alexander@Kriegisch.name> | 2021-04-10 19:19:39 +0700 |
commit | 92edca3ea7a482d59a9086b1cb61413ed8604b67 (patch) | |
tree | d709ab2fd24a563cf626fb5ff354a0972a1dc6a9 /docs/adk15ProgGuideDB | |
parent | 79c272eb9c158a976b7b3313c50759dd87b1b5fd (diff) | |
download | aspectj-92edca3ea7a482d59a9086b1cb61413ed8604b67.tar.gz aspectj-92edca3ea7a482d59a9086b1cb61413ed8604b67.zip |
Remove indentation from <programlisting> blocks in docs
Many dozens (hundreds?) of documentation code blocks were indented to
match the surrounding XML or just arbitrarily. The thing is: Inside
<programlisting> tags, similar to <pre> tags, line feeds and leading
whitespace are being preserved, which looked very awkward in the HTML
documentation. While a few files were mostly correct in this respect,
which shows that it was meant to be like that, many others were not.
This was tedious, stupid work to fix, but it had to be done.
Please note that the documentation was in no way updated content-wise.
This is also overdue, but not my focus here.
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'docs/adk15ProgGuideDB')
-rw-r--r-- | docs/adk15ProgGuideDB/annotations.xml | 993 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/ataspectj.xml | 821 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/autoboxing.xml | 66 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/covariance.xml | 84 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/enumeratedtypes.xml | 32 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/generics.xml | 1101 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/grammar.xml | 366 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/joinpointsignatures.xml | 327 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/miscellaneous.xml | 92 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/pertypewithin.xml | 110 | ||||
-rw-r--r-- | docs/adk15ProgGuideDB/varargs.xml | 143 |
11 files changed, 2031 insertions, 2104 deletions
diff --git a/docs/adk15ProgGuideDB/annotations.xml b/docs/adk15ProgGuideDB/annotations.xml index 588b40b20..f9be0d0da 100644 --- a/docs/adk15ProgGuideDB/annotations.xml +++ b/docs/adk15ProgGuideDB/annotations.xml @@ -1,7 +1,7 @@ <chapter id="annotations" xreflabel="Annotations"> <title>Annotations</title> - + <sect1 id="annotations-inJava5"> <title>Annotations in Java 5</title> @@ -14,28 +14,28 @@ <sect2 id="using-annotations" xreflabel="using-annotations"> <title>Using Annotations</title> - + <para> Java 5 introduces <emphasis>annotation types</emphasis> which can be used to express metadata relating to program members in the - form of <emphasis>annotations</emphasis>. Annotations in Java 5 + form of <emphasis>annotations</emphasis>. Annotations in Java 5 can be applied to package and type declarations (classes, - interfaces, enums, and annotations), constructors, methods, + interfaces, enums, and annotations), constructors, methods, fields, parameters, and variables. Annotations are specified in the program source by using the <literal>@</literal> symbol. For example, the following piece of code uses the <literal>@Deprecated</literal> annotation to indicate that the <literal>obsoleteMethod()</literal> has been deprecated: </para> - + <programlisting><![CDATA[ - @Deprecated - public void obsoleteMethod() { ... } - ]]></programlisting> - +@Deprecated +public void obsoleteMethod() { ... } +]]> </programlisting> + <para> Annotations may be <emphasis>marker annotations</emphasis>, - <emphasis>single-valued annotations</emphasis>, or + <emphasis>single-valued annotations</emphasis>, or <emphasis>multi-valued annotations</emphasis>. Annotation types with no members or that provide default values for all members may be used simply as marker annotations, as in @@ -43,53 +43,53 @@ a single member, and the annotation may be written in one of two equivalent forms: </para> - + <programlisting><![CDATA[ - @SuppressWarnings({"unchecked"}) - public void someMethod() {...} - ]]></programlisting> - +@SuppressWarnings({"unchecked"}) +public void someMethod() {...} +]]> </programlisting> + <para> or </para> - + <programlisting><![CDATA[ - @SuppressWarnings(value={"unchecked"}) - public void someMethod() {...} - ]]></programlisting> - +@SuppressWarnings(value={"unchecked"}) +public void someMethod() {...} +]]> </programlisting> + <para> Multi-value annotations must use the <literal>member-name=value </literal> syntax to specify annotation values. For example: </para> - + <programlisting><![CDATA[ - @Authenticated(role="supervisor",clearanceLevel=5) - public void someMethod() {...} - ]]></programlisting> - +@Authenticated(role="supervisor",clearanceLevel=5) +public void someMethod() {...} +]]> </programlisting> + </sect2> <sect2 id="retention-policies" xreflabel="retention-policies"> - <title>Retention Policies</title> - + <title>Retention Policies</title> + <para> Annotations can have one of three retention policies: </para> - + <variablelist> - + <varlistentry> <term>Source-file retention</term> <listitem> <para> - Annotations with source-file retention are read by the + Annotations with source-file retention are read by the compiler during the compilation process, but are not rendered in the generated <literal>.class</literal> files. </para> </listitem> </varlistentry> - + <varlistentry> <term>Class-file retention</term> <listitem> @@ -101,7 +101,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>Runtime retention</term> <listitem> @@ -114,145 +114,145 @@ </listitem> </varlistentry> </variablelist> - + <para>Local variable annotations are not retained in class files (or at runtime) regardless of the retention policy set on the annotation type. See JLS 9.6.1.2.</para> - </sect2> + </sect2> <sect2 id="accessing-annotations-at-runtime" xreflabel="accessing-annotations-at-runtime"> <title>Accessing Annotations at Runtime</title> - + <para> - Java 5 supports a new interface, + Java 5 supports a new interface, <literal>java.lang.reflect.AnnotatedElement</literal>, that is - implemented by the reflection classes in Java (<literal>Class</literal>, + implemented by the reflection classes in Java (<literal>Class</literal>, <literal>Constructor</literal>, - <literal>Field</literal>, <literal>Method</literal>, and + <literal>Field</literal>, <literal>Method</literal>, and <literal>Package</literal>). This interface gives you access to annotations <emphasis>that have runtime retention</emphasis> via - the <literal>getAnnotation</literal>, <literal>getAnnotations</literal>, + the <literal>getAnnotation</literal>, <literal>getAnnotations</literal>, and <literal>isAnnotationPresent</literal>. Because annotation types are just regular Java classes, the annotations returned by these methods can be queried just like any regular Java object. </para> - + </sect2> - + <sect2 id="annotation-inheritance" xreflabel="annotation-inheritance"> <title>Annotation Inheritance</title> - + <para> It is important to understand the rules relating to inheritance of annotations, as these have a bearing on join point matching based on the presence or absence of annotations. </para> - + <para> By default annotations are <emphasis>not</emphasis> inherited. Given the following program </para> <programlisting><![CDATA[ - @MyAnnotation - class Super { - @Oneway public void foo() {} - } - - class Sub extends Super { - public void foo() {} - } - ]]></programlisting> +@MyAnnotation +class Super { + @Oneway public void foo() {} +} + +class Sub extends Super { + public void foo() {} +} +]]> </programlisting> <para> Then <literal>Sub</literal> <emphasis>does not</emphasis> have - the <literal>MyAnnotation</literal> annotation, and + the <literal>MyAnnotation</literal> annotation, and <literal>Sub.foo()</literal> is not an <literal>@Oneway</literal> - method, despite the fact that it overrides + method, despite the fact that it overrides <literal>Super.foo()</literal> which is. </para> - + <para> If an annotation type has the meta-annotation <literal>@Inherited</literal> then an annotation of that type on a <emphasis>class</emphasis> will cause the annotation to be inherited by sub-classes. So, in the example above, if the <literal>MyAnnotation</literal> type had the <literal>@Inherited</literal> attribute, then <literal>Sub</literal> - would have the <literal>MyAnnotation</literal> annotation. + would have the <literal>MyAnnotation</literal> annotation. </para> - + <para> <literal>@Inherited</literal> annotations are not inherited when used to annotate anything other than a type. A type that implements one or more interfaces never inherits any annotations from the interfaces it implements. </para> - + </sect2> </sect1> - + <!-- ============================== --> - + <sect1 id="annotations-aspectmembers"> <title>Annotating Aspects</title> - + <para> AspectJ 5 supports annotations on aspects, and on method, field, - constructor, advice, and inter-type declarations within aspects. + constructor, advice, and inter-type declarations within aspects. Method and advice parameters may also be annotated. - Annotations are not permitted on pointcut declarations or on + Annotations are not permitted on pointcut declarations or on <literal>declare</literal> statements. </para> - + <para> The following example illustrates the use of annotations in aspects: </para> <programlisting><![CDATA[ - @AspectAnnotation - public abstract aspect ObserverProtocol { - - @InterfaceAnnotation - interface Observer {} - - @InterfaceAnnotation - interface Subject {} - - @ITDFieldAnnotation - private List<Observer> Subject.observers; - - @ITDMethodAnnotation - public void Subject.addObserver(Observer o) { - observers.add(o); - } - - @ITDMethodAnnotation - public void Subject.removeObserver(Observer o) { - observers.remove(o); - } - - @MethodAnnotation - private void notifyObservers(Subject subject) { - for(Observer o : subject.observers) - notifyObserver(o,subject); - } - - /** - * Delegate to concrete sub-aspect the actual form of - * notification for a given type of Observer. - */ - @MethodAnnotation - protected abstract void notifyObserver(Observer o, Subject s); - - /* no annotations on pointcuts */ - protected abstract pointcut observedEvent(Subject subject); - - @AdviceAnnotation - after(Subject subject) returning : observedEvent(subject) { - notifyObservers(subject); - } - } - ]]></programlisting> +@AspectAnnotation +public abstract aspect ObserverProtocol { + + @InterfaceAnnotation + interface Observer {} + + @InterfaceAnnotation + interface Subject {} + + @ITDFieldAnnotation + private List<Observer> Subject.observers; + + @ITDMethodAnnotation + public void Subject.addObserver(Observer o) { + observers.add(o); + } + + @ITDMethodAnnotation + public void Subject.removeObserver(Observer o) { + observers.remove(o); + } + + @MethodAnnotation + private void notifyObservers(Subject subject) { + for(Observer o : subject.observers) + notifyObserver(o,subject); + } + + /** + * Delegate to concrete sub-aspect the actual form of + * notification for a given type of Observer. + */ + @MethodAnnotation + protected abstract void notifyObserver(Observer o, Subject s); + + /* no annotations on pointcuts */ + protected abstract pointcut observedEvent(Subject subject); + + @AdviceAnnotation + after(Subject subject) returning : observedEvent(subject) { + notifyObservers(subject); + } +} +]]></programlisting> <para> An annotation on an aspect will be inherited by sub-aspects, iff it has @@ -262,39 +262,39 @@ <para> AspectJ 5 supports a new XLint warning, "the pointcut associated with this advice does not match any join points". The warning is enabled by default and - will be emitted by the compiler if the pointcut expression associated with an + will be emitted by the compiler if the pointcut expression associated with an advice statement can be statically determined to not match any join points. The - warning can be suppressed for an individual advice statement by using the + warning can be suppressed for an individual advice statement by using the <literal>@SuppressAjWarnings({"adviceDidNotMatch"})</literal> annotation. This works in the same way as the Java 5 SuppressWarnings annotation (See JLS 9.6.1.5), but has class file retention. </para> - + <programlisting><![CDATA[ - import org.aspectj.lang.annotation.SuppressAjWarnings; - - public aspect AnAspect { - - pointcut anInterfaceOperation() : execution(* AnInterface.*(..)); - - - @SuppressAjWarnings // may not match if there are no implementers of the interface... - before() : anInterfaceOperation() { - // do something... - } - - @SuppressAjWarnings("adviceDidNotMatch") // alternate form - after() returning : anInterfaceOperation() { - // do something... - } - } - ]]></programlisting> - - +import org.aspectj.lang.annotation.SuppressAjWarnings; + +public aspect AnAspect { + + pointcut anInterfaceOperation() : execution(* AnInterface.*(..)); + + + @SuppressAjWarnings // may not match if there are no implementers of the interface... + before() : anInterfaceOperation() { + // do something... + } + + @SuppressAjWarnings("adviceDidNotMatch") // alternate form + after() returning : anInterfaceOperation() { + // do something... + } +} +]]></programlisting> + + </sect1> <!-- ============================== --> - + <sect1 id="annotations-pointcuts-and-advice"> <title>Join Point Matching based on Annotations</title> @@ -304,19 +304,19 @@ annotations. We then discuss means of exposing annotation values within the body of advice. </para> - + <sect2 id="annotation-patterns" xreflabel="annotation-patterns"> <title>Annotation Patterns</title> - + <para> - For any kind of annotated element (type, method, constructor, package, etc.), + For any kind of annotated element (type, method, constructor, package, etc.), an annotation pattern can be used to match against the set of annotations on the annotated element.An annotation pattern element has one of two basic forms: - </para> - + </para> + <itemizedlist> - <listitem>@<qualified-name>, for example, @Foo, or + <listitem>@<qualified-name>, for example, @Foo, or @org.xyz.Foo.</listitem> <listitem>@(<type-pattern>), for example, @(org.xyz..*), or @(Foo || Boo)</listitem> @@ -326,8 +326,8 @@ combined by simple concatentation. The pattern <literal>@Foo @Boo</literal> matches an annotated element that has both an annotation of type <literal>Foo</literal> and an annotation of type <literal>Boo</literal>.</para> - - <para>Some examples of annotation patterns follow:</para> + + <para>Some examples of annotation patterns follow:</para> <variablelist> @@ -335,7 +335,7 @@ <term>@Immutable</term> <listitem> <para> - Matches any annotated element which has an annotation of + Matches any annotated element which has an annotation of type <literal>Immutable</literal>. </para> </listitem> @@ -345,7 +345,7 @@ <term>!@Persistent</term> <listitem> <para> - Matches any annotated element which does not have an annotation of + Matches any annotated element which does not have an annotation of type <literal>Persistent</literal>. </para> </listitem> @@ -366,7 +366,7 @@ <listitem> <para> Matches any annotated element which has either an annotation of a type matching - the type pattern <literal>(Foo || Goo)</literal>. + the type pattern <literal>(Foo || Goo)</literal>. In other words, an annotated element with either an annotation of type <literal>Foo</literal> or an annotation of type <literal>Goo</literal> (or both). (The parenthesis are required in this example). @@ -379,7 +379,7 @@ <listitem> <para> Matches any annotated element which has either an annotation of a type matching - the type pattern <literal>(org.xyz..*)</literal>. + the type pattern <literal>(org.xyz..*)</literal>. In other words, an annotated element with an annotation that is declared in the org.xyz package or a sub-package. (The parenthesis are required in this example). </para> @@ -387,35 +387,35 @@ </varlistentry> </variablelist> - + </sect2> - + <sect2 id="type-patterns" xreflabel="type-patterns"> <title>Type Patterns</title> - + <para>AspectJ 1.5 extends type patterns to allow an optional <literal>AnnotationPattern</literal> prefix.</para> <programlisting><![CDATA[ - TypePattern := SimpleTypePattern | - '!' TypePattern | - '(' AnnotationPattern? TypePattern ')' - TypePattern '&&' TypePattern | - TypePattern '||' TypePattern - - SimpleTypePattern := DottedNamePattern '+'? '[]'* - - DottedNamePattern := FullyQualifiedName RestOfNamePattern? | - '*' NotStarNamePattern? - - RestOfNamePattern := '..' DottedNamePattern | - '*' NotStarNamePattern? - - NotStarNamePattern := FullyQualifiedName RestOfNamePattern? | - '..' DottedNamePattern - - FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* - ]]></programlisting> +TypePattern := SimpleTypePattern | + '!' TypePattern | + '(' AnnotationPattern? TypePattern ')' + TypePattern '&&' TypePattern | + TypePattern '||' TypePattern + +SimpleTypePattern := DottedNamePattern '+'? '[]'* + +DottedNamePattern := FullyQualifiedName RestOfNamePattern? | + '*' NotStarNamePattern? + +RestOfNamePattern := '..' DottedNamePattern | + '*' NotStarNamePattern? + +NotStarNamePattern := FullyQualifiedName RestOfNamePattern? | + '..' DottedNamePattern + +FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* +]]></programlisting> <para>Note that in most cases when annotations are used as part of a type pattern, the parenthesis are required (as in <literal>(@Foo Hello+)</literal>). In @@ -424,9 +424,9 @@ pointcut expression), the parenthesis are optional:</para> <programlisting><![CDATA[ - OptionalParensTypePattern := AnnotationPattern? TypePattern - ]]></programlisting> - +OptionalParensTypePattern := AnnotationPattern? TypePattern +]]> </programlisting> + <para> The following examples illustrate the use of annotations in type patterns: @@ -478,7 +478,7 @@ <para> Matches any type in a package beginning with the prefix <literal>org.xyz</literal>, which has either the <literal>@Immutable</literal> annotation or the - <literal>@NonPersistent</literal> annotation. + <literal>@NonPersistent</literal> annotation. </para> </listitem> </varlistentry> @@ -499,7 +499,7 @@ <listitem> <para> Matches any type in a package beginning with the prefix <literal>org.xyz</literal>, - which has an inheritable annotation. The annotation pattern + which has an inheritable annotation. The annotation pattern <literal>@(@Inherited *)</literal> matches any annotation of a type matching the type pattern <literal>@Inherited *</literal>, which in turn matches any type with the <literal>@Inherited</literal> annotation. @@ -508,33 +508,33 @@ </varlistentry> </variablelist> - + </sect2> - + <sect2 id="signaturePatterns" xreflabel="Signature Patterns"> <title>Signature Patterns</title> - + <sect3 id="fieldPatterns" xreflabel="Field Patterns"> <title>Field Patterns</title> - + <para>A <literal>FieldPattern</literal> can optionally specify an annotation-matching pattern as the first element:</para> - - <programlisting><![CDATA[ - FieldPattern := - AnnotationPattern? FieldModifiersPattern? - TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern - - FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern* - - FieldModifier := 'public' | 'private' | 'protected' | 'static' | - 'transient' | 'final' - - DotOrDotDot := '.' | '..' - - SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)? - ]]></programlisting> - + + <programlisting><![CDATA[ +FieldPattern := + AnnotationPattern? FieldModifiersPattern? + TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern + +FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern* + +FieldModifier := 'public' | 'private' | 'protected' | 'static' | + 'transient' | 'final' + +DotOrDotDot := '.' | '..' + +SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)? +]]></programlisting> + <para> If present, the <literal>AnnotationPattern</literal> restricts matches to fields with annotations that match the pattern. For example: @@ -577,7 +577,7 @@ <term>@Foo (@Goo *) (@Hoo *).*</term> <listitem> <para> - Matches a field with an annotation <literal>@Foo</literal>, of a type with an + Matches a field with an annotation <literal>@Foo</literal>, of a type with an annotation <literal>@Goo</literal>, declared in a type with annotation <literal>@Hoo</literal>. </para> @@ -595,57 +595,54 @@ </varlistentry> </variablelist> - + </sect3> <sect3 id="methodPatterns" xreflabel="Method Patterns"> <title>Method and Constructor Patterns</title> - + <para>A <literal>MethodPattern</literal> can optionally specify an annotation-matching pattern as the first element.</para> - <programlisting><![CDATA[ - MethodPattern := - AnnotationPattern? MethodModifiersPattern? TypePattern - (TypePattern DotOrDotDot)? SimpleNamePattern - '(' FormalsPattern ')'ThrowsPattern? - - MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern* - - MethodModifier := 'public' | 'private' | 'protected' | 'static' | - 'synchronized' | 'final' - - FormalsPattern := '..' (',' FormalsPatternAfterDotDot)* | - OptionalParensTypePattern (',' FormalsPattern)* | - TypePattern '...' - - FormalsPatternAfterDotDot := - OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | - TypePattern '...' - - ThrowsPattern := 'throws' TypePatternList - - TypePatternList := TypePattern (',' TypePattern)* - - ]]></programlisting> - - +<programlisting><![CDATA[ +MethodPattern := + AnnotationPattern? MethodModifiersPattern? TypePattern + (TypePattern DotOrDotDot)? SimpleNamePattern + '(' FormalsPattern ')'ThrowsPattern? + +MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern* + +MethodModifier := 'public' | 'private' | 'protected' | 'static' | + 'synchronized' | 'final' + +FormalsPattern := '..' (',' FormalsPatternAfterDotDot)* | + OptionalParensTypePattern (',' FormalsPattern)* | + TypePattern '...' + +FormalsPatternAfterDotDot := + OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | + TypePattern '...' + +ThrowsPattern := 'throws' TypePatternList + +TypePatternList := TypePattern (',' TypePattern)* +]]></programlisting> + <para>A <literal>ConstructorPattern</literal> has the form</para> - <programlisting><![CDATA[ - ConstructorPattern := - AnnotationPattern? ConstructorModifiersPattern? - (TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')' - ThrowsPattern? - - ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern* - - ConstructorModifier := 'public' | 'private' | 'protected' - - ]]></programlisting> - + <programlisting><![CDATA[ +ConstructorPattern := + AnnotationPattern? ConstructorModifiersPattern? + (TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')' + ThrowsPattern? + +ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern* + +ConstructorModifier := 'public' | 'private' | 'protected' +]]></programlisting> + <para> - The optional <literal>AnnotationPattern</literal> at the beginning of a + The optional <literal>AnnotationPattern</literal> at the beginning of a method or constructor pattern restricts matches to methods/constructors with annotations that match the pattern. For example: </para> @@ -683,11 +680,11 @@ </listitem> </varlistentry> </variablelist> - + </sect3> </sect2> - + <sect2 id="example-pointcuts" xreflabel="example-pointcuts"> <title>Example Pointcuts</title> @@ -697,7 +694,7 @@ <term>within(@Secure *)</term> <listitem> <para> - Matches any join point where the code executing is declared in a + Matches any join point where the code executing is declared in a type with an <literal>@Secure</literal> annotation. The format of the <literal>within</literal> pointcut designator in AspectJ 5 is <literal>'within' '(' OptionalParensTypePattern ')'</literal>. @@ -710,7 +707,7 @@ <listitem> <para> Matches the staticinitialization join point of any type with the - <literal>@Persistent</literal> annotation. The format of the + <literal>@Persistent</literal> annotation. The format of the <literal>staticinitialization</literal> pointcut designator in AspectJ 5 is <literal>'staticinitialization' '(' OptionalParensTypePattern ')'</literal>. </para> @@ -730,8 +727,8 @@ <term>execution(public (@Immutable *) org.xyz..*.*(..))</term> <listitem> <para> - The execution of any public method in a package with prefix - <literal>org.xyz</literal>, where the method returns an + The execution of any public method in a package with prefix + <literal>org.xyz</literal>, where the method returns an immutable result. </para> </listitem> @@ -770,8 +767,8 @@ advice definition. These designators are <literal>@args, @this, @target, @within, @withincode</literal>, and <literal>@annotation</literal> </para> - - <para>It is a compilation error to attempt to match on an annotation type + + <para>It is a compilation error to attempt to match on an annotation type that does not have runtime retention using <literal>@this, @target</literal> or <literal>@args</literal>. It is a compilation error to attempt to use any of these designators to expose an annotation value that does not @@ -780,45 +777,44 @@ <para> The <literal>this()</literal>, <literal>target()</literal>, and <literal>args()</literal> pointcut designators allow matching based - on the runtime type of an object, as opposed to the statically + on the runtime type of an object, as opposed to the statically declared type. In AspectJ 5, these designators are supplemented with three new designators : <literal>@this()</literal> (read, "this - annotation"), <literal>@target()</literal>, and <literal>@args()</literal>. + annotation"), <literal>@target()</literal>, and <literal>@args()</literal>. </para> - + <para> - Like their counterparts, these pointcut designators can be used - both for join point matching, and to expose context. The format of + Like their counterparts, these pointcut designators can be used + both for join point matching, and to expose context. The format of these new designators is: </para> - - <programlisting><![CDATA[ - AtThis := '@this' '(' AnnotationOrIdentifer ')' - - AtTarget := '@target' '(' AnnotationOrIdentifier ')' - - AnnotationOrIdentifier := FullyQualifiedName | Identifier - - AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' - - AnnotationsOrIdentifiersPattern := - '..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? | - AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* | - '*' (',' AnnotationsOrIdentifiersPattern)* - - AnnotationsOrIdentifiersPatternAfterDotDot := - AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | - '*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)* - - ]]></programlisting> + + <programlisting><![CDATA[ +AtThis := '@this' '(' AnnotationOrIdentifer ')' + +AtTarget := '@target' '(' AnnotationOrIdentifier ')' + +AnnotationOrIdentifier := FullyQualifiedName | Identifier + +AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' + +AnnotationsOrIdentifiersPattern := + '..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? | + AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* | + '*' (',' AnnotationsOrIdentifiersPattern)* + +AnnotationsOrIdentifiersPatternAfterDotDot := + AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | + '*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)* +]]></programlisting> <para> The forms of <literal>@this()</literal> and <literal>@target()</literal> that take a single annotation name are analogous to their counterparts that take - a single type name. They match at join points where the object bound to + a single type name. They match at join points where the object bound to <literal>this</literal> (or <literal>target</literal>, respectively) has an - annotation of the specified type. For example: - </para> + annotation of the specified type. For example: + </para> <variablelist> @@ -843,26 +839,26 @@ </varlistentry> </variablelist> - + <para> - Annotations can be exposed as context in the body of advice by + Annotations can be exposed as context in the body of advice by using the forms of <literal>@this(), @target()</literal> and <literal>@args()</literal> that use bound variables in the place of annotation names. For example: </para> <programlisting><![CDATA[ - pointcut callToClassifiedObject(Classified classificationInfo) : - call(* *(..)) && @target(classificationInfo); +pointcut callToClassifiedObject(Classified classificationInfo) : + call(* *(..)) && @target(classificationInfo); - pointcut txRequiredMethod(Tx transactionAnnotation) : - execution(* *(..)) && @this(transactionAnnotation) - && if(transactionAnnotation.policy() == TxPolicy.REQUIRED); - ]]></programlisting> +pointcut txRequiredMethod(Tx transactionAnnotation) : + execution(* *(..)) && @this(transactionAnnotation) + && if(transactionAnnotation.policy() == TxPolicy.REQUIRED); +]]></programlisting> <para> The <literal>@args</literal> pointcut designator behaves as its <literal>args</literal> - counterpart, matching join points based on number and position of arguments, and + counterpart, matching join points based on number and position of arguments, and supporting the <literal>*</literal> wildcard and at most one <literal>..</literal> wildcard. An annotation at a given position in an <literal>@args</literal> expression indicates that the runtime type of the argument in that position at a join point must @@ -870,45 +866,45 @@ </para> <programlisting><![CDATA[ - /** - * matches any join point with at least one argument, and where the - * type of the first argument has the @Classified annotation - */ - pointcut classifiedArgument() : @args(Classified,..); - - /** - * matches any join point with three arguments, where the third - * argument has an annotation of type @Untrusted. - */ - pointcut untrustedData(Untrusted untrustedDataSource) : - @args(*,*,untrustedDataSource); - ]]></programlisting> +/** + * matches any join point with at least one argument, and where the + * type of the first argument has the @Classified annotation + */ +pointcut classifiedArgument() : @args(Classified,..); + +/** + * matches any join point with three arguments, where the third + * argument has an annotation of type @Untrusted. + */ +pointcut untrustedData(Untrusted untrustedDataSource) : + @args(*,*,untrustedDataSource); +]]></programlisting> <para>In addition to accessing annotation information at runtime through context binding, access to <literal>AnnotatedElement</literal> information is also available reflectively with the body of advice through the <literal>thisJoinPoint</literal>, - <literal>thisJoinPointStaticPart</literal>, and - <literal>thisEnclosingJoinPointStaticPart</literal> variables. To access + <literal>thisJoinPointStaticPart</literal>, and + <literal>thisEnclosingJoinPointStaticPart</literal> variables. To access annotations on the arguments, or object bound to this or target at a join point you can use the following code fragments:</para> <programlisting><![CDATA[ - Annotation[] thisAnnotations = thisJoinPoint.getThis().getClass().getAnnotations(); - Annotation[] targetAnnotations = thisJoinPoint.getTarget().getClass().getAnnotations(); - Annotation[] firstParamAnnotations = thisJoinPoint.getArgs()[0].getClass().getAnnotations(); - ]]></programlisting> +Annotation[] thisAnnotations = thisJoinPoint.getThis().getClass().getAnnotations(); +Annotation[] targetAnnotations = thisJoinPoint.getTarget().getClass().getAnnotations(); +Annotation[] firstParamAnnotations = thisJoinPoint.getArgs()[0].getClass().getAnnotations(); +]]></programlisting> <para> The <literal>@within</literal> and <literal>@withincode</literal> pointcut designators match any join point where the executing code is defined within a type (<literal>@within</literal>), - or a method/constructor (<literal>@withincode</literal>) that has an annotation of the specified + or a method/constructor (<literal>@withincode</literal>) that has an annotation of the specified type. The form of these designators is: </para> - - <programlisting><![CDATA[ - AtWithin := '@within' '(' AnnotationOrIdentifier ')' - AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')' - ]]></programlisting> + + <programlisting><![CDATA[ +AtWithin := '@within' '(' AnnotationOrIdentifier ')' +AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')' +]]></programlisting> <para>Some examples of using these designators follow:</para> @@ -918,73 +914,73 @@ <term>@within(Foo)</term> <listitem> <para> - Matches any join point where the executing code is defined + Matches any join point where the executing code is defined within a type which has an annotation of type <literal>Foo</literal>. </para> </listitem> </varlistentry> <varlistentry> - <term>pointcut insideCriticalMethod(Critical c) : + <term>pointcut insideCriticalMethod(Critical c) : @withincode(c);</term> <listitem> <para> Matches any join point where the executing code is defined in a method or constructor which has an annotation of type <literal>@Critical</literal>, - and exposes the value of the annotation in the parameter + and exposes the value of the annotation in the parameter <literal>c</literal>. </para> </listitem> </varlistentry> </variablelist> - + <para>The <literal>@annotation</literal> pointcut designator matches any - join point where the <emphasis>subject</emphasis> of the join point has + join point where the <emphasis>subject</emphasis> of the join point has an annotation of the given type. Like the other @pcds, it can also be used for context exposure.</para> - <programlisting><![CDATA[ - AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')' - ]]></programlisting> - + <programlisting><![CDATA[ +AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')' +]]></programlisting> + <para>The subject of a join point is defined in the table in chapter one of - this guide.</para> + this guide.</para> <para> Access to annotation information on members at a matched join point is also available through the <literal>getSignature</literal> method of the <literal>JoinPoint</literal> and <literal>JoinPoint.StaticPart</literal> interfaces. The <literal>Signature</literal> - interfaces are extended with additional operations that provide access to the - <literal>java.lang.reflect</literal> <literal>Method, Field</literal> and + interfaces are extended with additional operations that provide access to the + <literal>java.lang.reflect</literal> <literal>Method, Field</literal> and <literal>Constructor</literal> objects on which annnotations can be queried. The following fragment illustrates an example use of this interface to access annotation information. </para> <programlisting><![CDATA[ - Signature sig = thisJoinPointStaticPart.getSignature(); - AnnotatedElement declaringTypeAnnotationInfo = sig.getDeclaringType(); - if (sig instanceof MethodSignature) { - // this must be a call or execution join point - Method method = ((MethodSignature)sig).getMethod(); - } - ]]></programlisting> - +Signature sig = thisJoinPointStaticPart.getSignature(); +AnnotatedElement declaringTypeAnnotationInfo = sig.getDeclaringType(); +if (sig instanceof MethodSignature) { + // this must be a call or execution join point + Method method = ((MethodSignature)sig).getMethod(); +} +]]></programlisting> + <para> <emphasis>Note again that it would be nicer to add the method getAnnotationInfo directly to MemberSignature, but this would once more couple the runtime library to Java 5.</emphasis> </para> - + <para> - The <literal>@this,@target</literal> and <literal>@args</literal> - pointcut designators can only be used to match against annotations + The <literal>@this,@target</literal> and <literal>@args</literal> + pointcut designators can only be used to match against annotations that have runtime retention. The <literal>@within, @withincode</literal> and <literal>@annotation</literal> pointcut designators can only be used to match against annotations that have at least class-file retention, and - if used in the binding form the annotation must have runtime retention. + if used in the binding form the annotation must have runtime retention. </para> - + </sect2> @@ -994,37 +990,36 @@ <para> <emphasis>Matching on package annotations is not supported in AspectJ. Support for this capability may be considered in a future release.</emphasis> - + </para> - + <para> Parameter annotation matching is being added in AspectJ1.6. Initially only matching is supported but binding will be implemented at some point. Whether the annotation specified in a pointcut should be considered to be an annotation on the parameter type or an annotation on the parameter itself is determined through the use of parentheses around the parameter type. - + Consider the following: </para> - - + + <programlisting><![CDATA[ - @SomeAnnotation - class AnnotatedType {} - - class C { - public void foo(AnnotatedType a) {} - public void goo(@SomeAnnotation String s) {} - } - - ]]></programlisting> - +@SomeAnnotation +class AnnotatedType {} + +class C { + public void foo(AnnotatedType a) {} + public void goo(@SomeAnnotation String s) {} +} +]]></programlisting> + <para> The method foo has a parameter of an annotated type, and can be matched by this pointcut: </para> <programlisting><![CDATA[ - pointcut p(): execution(* *(@SomeAnnotation *)); - ]]></programlisting> +pointcut p(): execution(* *(@SomeAnnotation *)); +]]></programlisting> <para> When there is a single annotation specified like this, it is considered to be part of the type pattern in the match against the parameter: 'a parameter of any type that has the annotation @SomeAnnotation'. @@ -1033,8 +1028,8 @@ To match the parameter annotation case, the method goo, this is the pointcut: </para> <programlisting><![CDATA[ - pointcut p(): execution(* *(@SomeAnnotation (*))); - ]]></programlisting> +pointcut p(): execution(* *(@SomeAnnotation (*))); +]]></programlisting> <para> The use of parentheses around the wildcard is effectively indicating that the annotation should be considered separately to the type pattern for the parameter type: 'a parameter of any type that has a parameter annotation of @@ -1044,8 +1039,8 @@ To match when there is a parameter annotation and an annotation on the type as well: </para> <programlisting><![CDATA[ - pointcut p(): execution(* *(@SomeAnnotation (@SomeOtherAnnotation *))); - ]]></programlisting> +pointcut p(): execution(* *(@SomeAnnotation (@SomeOtherAnnotation *))); +]]></programlisting> <para> The parentheses are grouping @SomeOtherAnnotation with the * to form the type pattern for the parameter, then the type @SomeAnnotation will be treated as a parameter annotation pattern. @@ -1056,32 +1051,32 @@ <!-- <para> Java 5 allows both packages and parameters to be annotated. To allow matching on package and parameter annotations, - AspectJ 5 introduces the <literal>@package</literal> and <literal>@parameters</literal> pointcut designators. + AspectJ 5 introduces the <literal>@package</literal> and <literal>@parameters</literal> pointcut designators. </para> - - <programlisting><![CDATA[ - PackageAnnotationPointcut := '@package' '(' AnnotationPattern ')' - ]]></programlisting> - - <para>The <literal>@package</literal> pointcut matches any join point + + <programlisting><![CDATA[ +PackageAnnotationPointcut := '@package' '(' AnnotationPattern ')' +]]></programlisting> + + <para>The <literal>@package</literal> pointcut matches any join point occuring within the scope of a package with annotations matching the giving <literal>AnnotationPattern</literal>. For example: </para> - - <programlisting><![CDATA[ - @package(@Model) - ]]></programlisting> - + + <programlisting><![CDATA[ +@package(@Model) +]]></programlisting> + <para> Matches any join point occuring within the scope of a package with the <literal>@Model</literal> annotation. </para> - + <para> <emphasis> Note: we added @package as a result of a conscious decision not to allow the - specification of package annotation patterns within a general TypePattern. A + specification of package annotation patterns within a general TypePattern. A consequence of this decision is that we lose the ability to say the following things: "a call to a method defined in a type in a package with annotations matching..." ; "the set of a field defined in a type in a package with annotations @@ -1094,157 +1089,137 @@ to allow for the others in the future when we better understanding how users will really use both package annotations and these features. </emphasis> - </para> - + </para> + <para> The <literal>@parameter</literal> pointcut designator acts in a similar manner to <literal>args</literal> in that it matches based on number and position of arguments at a join point (and supports the same wildcard options of <literal>*</literal> and - <literal>..</literal>. + <literal>..</literal>. </para> - <programlisting><![CDATA[ - ParamsAnnotationPointcut := '@parameters' '(' ParamsAnnotationPattern ')' - - ParamsAnnotationPattern := AnnotationPattern (',' ParamsAnnotationPattern)? | - '*' (',' ParamsAnnotationPattern)? | - '..' (',' SingleParamsAnnotationPattern)* - - SingleParamsAnnotationPattern := AnnotationPattern (',' SingleParamsAnnotationPattern)? | - '*' (',' SingleParamsAnnotationPattern)? - ]]></programlisting> - - <para>The <literal>*</literal> wildcard matches a single parameter regardless of its annotations. - The <literal>..</literal> wildcard matches zero or more parameters with any annotations. An - annotation pattern in a given parameter position matches a parameter in that position with annotations - matching the given annotation pattern. For example, the method signature</para> - <programlisting><![CDATA[ - public void foo(@Immutable int i, String s, @Cached Object o); - ]]></programlisting> +ParamsAnnotationPointcut := '@parameters' '(' ParamsAnnotationPattern ')' - <para> - Is matched by: - </para> +ParamsAnnotationPattern := AnnotationPattern (',' ParamsAnnotationPattern)? | + '*' (',' ParamsAnnotationPattern)? | + '..' (',' SingleParamsAnnotationPattern)* - <programlisting><![CDATA[ - @parameters(@Immutable, *, @Cached); - - and, - - @parameters(..,@Cached); - - and, - - @parameters(@Immutable, *, *); - ]]></programlisting> +SingleParamsAnnotationPattern := AnnotationPattern (',' SingleParamsAnnotationPattern)? | + '*' (',' SingleParamsAnnotationPattern)? +]]></programlisting> - <para> - It is not matched by: - </para> + <para>The <literal>*</literal> wildcard matches a single parameter regardless of its annotations. + The <literal>..</literal> wildcard matches zero or more parameters with any annotations. An + annotation pattern in a given parameter position matches a parameter in that position with annotations + matching the given annotation pattern. For example, the method signature</para> <programlisting><![CDATA[ - @parameters(@Immutable, *); - - or, - - @parameters(*,@Immutable); - - or, - - @parameters(*, int, @Cached); - ]]></programlisting> - +public void foo(@Immutable int i, String s, @Cached Object o); +]]></programlisting> + + <para>Is matched by:</para> + <programlisting><![CDATA[@parameters(@Immutable, *, @Cached);]]></programlisting> + <para>and,</para> + <programlisting><![CDATA[@parameters(..,@Cached);]]></programlisting> + <para>and,</para> + <programlisting><![CDATA[@parameters(@Immutable, *, *);]]></programlisting> + + <para>It is not matched by:</para> + <programlisting><![CDATA[@parameters(@Immutable, *);]]></programlisting> + <para>or,</para> + <programlisting><![CDATA[@parameters(*,@Immutable);]]></programlisting> + <para>or,</para> + <programlisting><![CDATA[@parameters(*, int, @Cached);]]></programlisting> + <para> - This last example will result in a compilation error since <literal>int</literal> is not a + This last example will result in a compilation error since <literal>int</literal> is not a valid annotation pattern. </para> + --> - --> - </sect2> <sect2 id="annotation-inheritance-and-pointcut-matching" xreflabel="annotation-inheritance-and-pointcut-matching"> <title>Annotation Inheritance and pointcut matching</title> - + <para> According to the Java 5 specification, non-type annotations are not - inherited, and annotations on types are only inherited if they have the + inherited, and annotations on types are only inherited if they have the <literal>@Inherited</literal> meta-annotation. - + Given the following program: </para> <programlisting><![CDATA[ - class C1 { - @SomeAnnotation - public void aMethod() {...} - } - - class C2 extends C1 { - public void aMethod() {...} - } - - class Main { - public static void main(String[] args) { - C1 c1 = new C1(); - C2 c2 = new C2(); - c1.aMethod(); - c2.aMethod(); - } - } - - aspect X { - - pointcut annotatedC2MethodCall() : - call(@SomeAnnotation * C2.aMethod()); - - pointcut annotatedMethodCall() : - call(@SomeAnnotation * aMethod()); - } - ]]></programlisting> - +class C1 { + @SomeAnnotation + public void aMethod() {...} +} + +class C2 extends C1 { + public void aMethod() {...} +} + +class Main { + public static void main(String[] args) { + C1 c1 = new C1(); + C2 c2 = new C2(); + c1.aMethod(); + c2.aMethod(); + } +} + +aspect X { + pointcut annotatedC2MethodCall() : + call(@SomeAnnotation * C2.aMethod()); + + pointcut annotatedMethodCall() : + call(@SomeAnnotation * aMethod()); +} +]]></programlisting> + <para> The pointcut <literal>annotatedC2MethodCall</literal> will not match anything since the definition of <literal>aMethod</literal> in <literal>C2</literal> does not have the annotation. </para> - + <para> - The pointcut <literal>annotatedMethodCall</literal> matches + The pointcut <literal>annotatedMethodCall</literal> matches <literal>c1.aMethod()</literal> but not <literal>c2.aMethod()</literal>. The call to <literal>c2.aMethod</literal> is not matched because join point matching for modifiers (the visibility modifiers, annotations, and throws clause) is based on the subject of the join point (the method actually being called). </para> - + </sect2> - + <sect2 id="matchingOnAnnotationValues" xreflabel="matchingOnAnnotationValues"> <title>Matching based on annotation values</title> <para> The <literal>if</literal> pointcut designator can be used to write pointcuts - that match based on the values annotation members. For example: + that match based on the values annotation members. For example: </para> <programlisting><![CDATA[ - pointcut txRequiredMethod(Tx transactionAnnotation) : - execution(* *(..)) && @this(transactionAnnotation) - && if(transactionAnnotation.policy() == TxPolicy.REQUIRED); - ]]></programlisting> +pointcut txRequiredMethod(Tx transactionAnnotation) : + execution(* *(..)) && @this(transactionAnnotation) + && if(transactionAnnotation.policy() == TxPolicy.REQUIRED); +]]></programlisting> </sect2> - + </sect1> <!-- ============================== --> <sect1 id="annotations-decp"> <title>Using Annotations with declare statements</title> - + <sect2 id="declare-error-and-declare-warning" xreflabel="declare-error-and-declare-warning"> <title>Declare error and declare warning</title> - + <para> Since pointcut expressions in AspectJ 5 support join point matching based on annotations, this facility can be exploited when writing @@ -1253,32 +1228,32 @@ </para> <programlisting><![CDATA[ - declare warning : withincode(@PerformanceCritical * *(..)) && - call(@ExpensiveOperation * *(..)) - : "Expensive operation called from within performance critical section"; - ]]></programlisting> +declare warning : withincode(@PerformanceCritical * *(..)) && + call(@ExpensiveOperation * *(..)) + : "Expensive operation called from within performance critical section"; +]]></programlisting> <programlisting><![CDATA[ - declare error : call(* org.xyz.model.*.*(..)) && - !@within(Trusted) - : "Untrusted code should not call the model classes directly"; - ]]></programlisting> - +declare error : call(* org.xyz.model.*.*(..)) && + !@within(Trusted) + : "Untrusted code should not call the model classes directly"; +]]></programlisting> + </sect2> - - + + <sect2 id="declare-parents" xreflabel="declare-parents"> <title>declare parents</title> - + <para> The general form of a <literal>declare parents</literal> statement is: </para> - + <programlisting><![CDATA[ - declare parents : TypePattern extends Type; - declare parents : TypePattern implements TypeList; - ]]></programlisting> - +declare parents : TypePattern extends Type; +declare parents : TypePattern implements TypeList; +]]></programlisting> + <para> Since AspectJ 5 supports annotations as part of a type pattern specification, it is now possible to match types based on the presence @@ -1287,7 +1262,7 @@ </para> <variablelist> - + <varlistentry> <term>declare parents : (@Secured *) implements SecuredObject;</term> <listitem> @@ -1297,19 +1272,19 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>declare parents : (@Secured BankAccount+) implements SecuredObject;</term> <listitem> <para> The subset of types drawn from the <literal>BankAccount</literal> type and any subtype of - <literal>BankAccount</literal>, where the + <literal>BankAccount</literal>, where the <literal>@Secured</literal> annotation is present, implement the <literal>SecuredObject</literal> interface. </para> </listitem> </varlistentry> - + </variablelist> <para>An annotation type may not be used as the target of a declare parents @@ -1328,13 +1303,13 @@ </para> <programlisting><![CDATA[ - declare precedence : TypePatList; - ]]></programlisting> +declare precedence : TypePatList; +]]></programlisting> <para> AspectJ 5 allows the type patterns in the list to include annotation information as part of the pattern specification. For example: - </para> + </para> <variablelist> @@ -1348,48 +1323,48 @@ </para> </listitem> </varlistentry> - + </variablelist> - </sect2> + </sect2> </sect1> - + <!-- ============================== --> - + <sect1 id="annotations-declare"> <title>Declare Annotation</title> - + <para>AspectJ 5 supports a new kind of declare statement, <literal>declare annotation</literal>. - This takes different forms according to the recipient of the annotation: + This takes different forms according to the recipient of the annotation: <literal>declare @type</literal> for types, <literal>declare @method</literal> for methods, <literal>declare @constructor</literal> for constructors, and <literal>declare @field</literal> for fields. <literal>declare @package</literal> may be supported in a future release. </para> - + <para>The general form is:</para> <programlisting><![CDATA[ - declare @<kind> : ElementPattern : Annotation ; - ]]></programlisting> +declare @<kind> : ElementPattern : Annotation ; +]]></programlisting> - <para>Where annotation is a regular annotation expression as defined in the Java 5 language. If the annotation has + <para>Where annotation is a regular annotation expression as defined in the Java 5 language. If the annotation has the <literal>@Target</literal> meta-annotation, then the elements matched by <literal>ElementPattern</literal> must be of the kind specified by the <literal>@Target</literal> annotation.</para> - + <para><literal>ElementPattern</literal> is defined as follows:</para> - + <programlisting><![CDATA[ - ElementPattern := TypePattern | - MethodPattern | - ConstructorPattern | - FieldPattern - ]]></programlisting> - +ElementPattern := TypePattern | + MethodPattern | + ConstructorPattern | + FieldPattern +]]></programlisting> + <para>The following examples illustrate the use of <literal>declare annotation</literal>.</para> <variablelist> - + <varlistentry> <term>declare @type : org.xyz.model..* : @BusinessDomain ;</term> <listitem> @@ -1399,7 +1374,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>declare @method : public * BankAccount+.*(..) : @Secured(role="supervisor")</term> <listitem> @@ -1409,7 +1384,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>declare @constructor : BankAccount+.new(..) : @Secured(role="supervisor")</term> <listitem> @@ -1419,7 +1394,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>declare @field : * DAO+.* : @Persisted;</term> <listitem> @@ -1429,17 +1404,17 @@ </para> </listitem> </varlistentry> - + </variablelist> </sect1> - + <sect1 id="annotations-itds"> <title>Inter-type Declarations</title> - + <para>An annotation type may not be the target of an inter-type declaration.</para> - </sect1> - + </sect1> + </chapter> diff --git a/docs/adk15ProgGuideDB/ataspectj.xml b/docs/adk15ProgGuideDB/ataspectj.xml index 0ac475cc6..7f8152d9c 100644 --- a/docs/adk15ProgGuideDB/ataspectj.xml +++ b/docs/adk15ProgGuideDB/ataspectj.xml @@ -42,15 +42,15 @@ </para> <programlisting><![CDATA[ - @Aspect - public class Foo {} - ]]></programlisting> +@Aspect +public class Foo {} +]]></programlisting> <para>Is equivalent to:</para> <programlisting><![CDATA[ - public aspect Foo {} - ]]></programlisting> +public aspect Foo {} +]]></programlisting> <para>To specify an aspect an aspect instantiation model (the default is singleton), provide the perclause as the @@ -60,15 +60,15 @@ </para> <programlisting><![CDATA[ - @Aspect("perthis(execution(* abc..*(..)))") - public class Foo {} - ]]></programlisting> +@Aspect("perthis(execution(* abc..*(..)))") +public class Foo {} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - public aspect Foo perthis(execution(* abc..*(..))) {} - ]]></programlisting> +public aspect Foo perthis(execution(* abc..*(..))) {} +]]></programlisting> <sect2 id="limitations" xreflabel="limitations"> <title>Limitations</title> @@ -76,15 +76,15 @@ <para>Privileged aspects are not supported by the annotation style.</para> <!-- <programlisting><![CDATA[ - @Aspect(isPrivileged=true) - public class Foo {} - ]]></programlisting> +@Aspect(isPrivileged=true) +public class Foo {} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - public privileged aspect Foo {} - ]]></programlisting> +public privileged aspect Foo {} +]]></programlisting> --> </sect2> @@ -136,44 +136,44 @@ <para>Here is a simple example of a pointcut declaration in both code and @AspectJ styles:</para> <programlisting><![CDATA[ - @Pointcut("call(* *.*(..))") - void anyCall() {} - ]]></programlisting> +@Pointcut("call(* *.*(..))") +void anyCall() {} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - pointcut anyCall() : call(* *.*(..)); - ]]></programlisting> +pointcut anyCall() : call(* *.*(..)); +]]></programlisting> <para>When binding arguments, simply declare the arguments as normal in the annotated method:</para> <programlisting><![CDATA[ - @Pointcut("call(* *.*(int)) && args(i) && target(callee)") - void anyCall(int i, Foo callee) {} - ]]></programlisting> +@Pointcut("call(* *.*(int)) && args(i) && target(callee)") +void anyCall(int i, Foo callee) {} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - pointcut anyCall(int i, Foo callee) : call(* *.*(int)) && args(i) && target(callee); - ]]></programlisting> +pointcut anyCall(int i, Foo callee) : call(* *.*(int)) && args(i) && target(callee); +]]></programlisting> <para>An example with modifiers (Remember that Java 5 annotations are not inherited, so the <literal>@Pointcut</literal> annotation must be present on the extending aspect's pointcut declaration too):</para> <programlisting><![CDATA[ - @Pointcut("") - protected abstract void anyCall(); - ]]></programlisting> +@Pointcut("") +protected abstract void anyCall(); +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - protected abstract pointcut anyCall(); - ]]></programlisting> +protected abstract pointcut anyCall(); +]]></programlisting> <sect3> <title>Type references inside @AspectJ annotations</title> @@ -196,39 +196,34 @@ </para> <programlisting><![CDATA[ - package org.aspectprogrammer.examples; +package org.aspectprogrammer.examples; - import java.util.List; +import java.util.List; - public aspect Foo { - - pointcut listOperation() : call(* List.*(..)); - - pointcut anyUtilityCall() : call(* java.util..*(..)); - - } - ]]></programlisting> +public aspect Foo { + pointcut listOperation() : call(* List.*(..)); + pointcut anyUtilityCall() : call(* java.util..*(..)); +} +]]></programlisting> <para> Using the annotation style this would be written as: </para> <programlisting><![CDATA[ - package org.aspectprogrammer.examples; - - import java.util.List; // redundant but harmless +package org.aspectprogrammer.examples; - @Aspect - public class Foo { +import java.util.List; // redundant but harmless - @Pointcut("call(* java.util.List.*(..))") // must qualify - void listOperation() {} +@Aspect +public class Foo { + @Pointcut("call(* java.util.List.*(..))") // must qualify + void listOperation() {} - @Pointcut("call(* java.util..*(..))") - void anyUtilityCall() {} - - } - ]]></programlisting> + @Pointcut("call(* java.util..*(..))") + void anyUtilityCall() {} +} +]]></programlisting> </sect3> @@ -267,45 +262,45 @@ </para> <programlisting><![CDATA[ - @Pointcut("call(* *.*(int)) && args(i) && if()") - public static boolean someCallWithIfTest(int i) { - return i > 0; - } - ]]></programlisting> +@Pointcut("call(* *.*(int)) && args(i) && if()") +public static boolean someCallWithIfTest(int i) { + return i > 0; +} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0); - ]]></programlisting> +pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0); +]]></programlisting> <para>and the following is also a valid form:</para> <programlisting><![CDATA[ - static int COUNT = 0; - - @Pointcut("call(* *.*(int)) && args(i) && if()") - public static boolean someCallWithIfTest(int i, JoinPoint jp, JoinPoint.EnclosingStaticPart esjp) { - // any legal Java expression... - return i > 0 - && jp.getSignature().getName.startsWith("doo") - && esjp.getSignature().getName().startsWith("test") - && COUNT++ < 10; - } - - @Before("someCallWithIfTest(anInt, jp, enc)") - public void beforeAdviceWithRuntimeTest(int anInt, JoinPoint jp, JoinPoint.EnclosingStaticPart enc) { - //... - } - - // Note that the following is NOT valid - /* - @Before("call(* *.*(int)) && args(i) && if()") - public void advice(int i) { - // so you were writing an advice or an if body ? - } - */ - ]]></programlisting> +static int COUNT = 0; + +@Pointcut("call(* *.*(int)) && args(i) && if()") +public static boolean someCallWithIfTest(int i, JoinPoint jp, JoinPoint.EnclosingStaticPart esjp) { + // any legal Java expression... + return i > 0 + && jp.getSignature().getName.startsWith("doo") + && esjp.getSignature().getName().startsWith("test") + && COUNT++ < 10; +} + +@Before("someCallWithIfTest(anInt, jp, enc)") +public void beforeAdviceWithRuntimeTest(int anInt, JoinPoint jp, JoinPoint.EnclosingStaticPart enc) { + //... +} + +// Note that the following is NOT valid +/* +@Before("call(* *.*(int)) && args(i) && if()") +public void advice(int i) { + // so you were writing an advice or an if body ? +} +*/ +]]></programlisting> <para> It is thus possible with the annotation style to use the @@ -377,19 +372,19 @@ both styles:</para> <programlisting><![CDATA[ - @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") - public void callFromFoo() { - System.out.println("Call from Foo"); - } - ]]></programlisting> +@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") +public void callFromFoo() { + System.out.println("Call from Foo"); +} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { - System.out.println("Call from Foo"); - } - ]]></programlisting> +before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { + System.out.println("Call from Foo"); +} +]]></programlisting> <!-- @@ -405,19 +400,18 @@ </para> <programlisting><![CDATA[ - @AdviceName("callFromFoo") - before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { - System.out.println("Call from Foo"); - } - - is equivalent to... - - @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") - public void callFromFoo() { - System.out.println("Call from Foo"); - } - ]]></programlisting> - +@AdviceName("callFromFoo") +before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { + System.out.println("Call from Foo"); +} + +is equivalent to... + +@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") +public void callFromFoo() { + System.out.println("Call from Foo"); +} +]]></programlisting> --> <para>If the advice body needs to know which particular @@ -427,19 +421,19 @@ </para> <programlisting><![CDATA[ - before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { - System.out.println("Call from Foo: " + foo); - } - ]]></programlisting> +before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { + System.out.println("Call from Foo: " + foo); +} +]]></programlisting> <para>can be written as:</para> <programlisting><![CDATA[ - @Before("call(* org.aspectprogrammer..*(..)) && this(foo)") - public void callFromFoo(Foo foo) { - System.out.println("Call from Foo: " + foo); - } - ]]></programlisting> +@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") +public void callFromFoo(Foo foo) { + System.out.println("Call from Foo: " + foo); +} +]]></programlisting> <para>If the advice body needs access to <literal>thisJoinPoint</literal> @@ -453,32 +447,32 @@ </para> <programlisting><![CDATA[ - @Before("call(* org.aspectprogrammer..*(..)) && this(foo)") - public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) { - System.out.println("Call from Foo: " + foo + " at " - + thisJoinPoint); - } - ]]></programlisting> +@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") +public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) { + System.out.println("Call from Foo: " + foo + " at " + + thisJoinPoint); +} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { - System.out.println("Call from Foo: " + foo + " at " - + thisJoinPoint); - } - ]]></programlisting> +before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { + System.out.println("Call from Foo: " + foo + " at " + + thisJoinPoint); +} +]]></programlisting> <para>Advice that needs all three variables would be declared:</para> <programlisting><![CDATA[ - @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") - public void callFromFoo(JoinPoint thisJoinPoint, - JoinPoint.StaticPart thisJoinPointStaticPart, - JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) { - // ... - } - ]]></programlisting> +@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") +public void callFromFoo(JoinPoint thisJoinPoint, + JoinPoint.StaticPart thisJoinPointStaticPart, + JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) { + // ... +} +]]></programlisting> <para> <literal>JoinPoint.EnclosingStaticPart</literal> @@ -514,28 +508,28 @@ </para> <programlisting><![CDATA[ - @AfterReturning("criticalOperation()") - public void phew() { - System.out.println("phew"); - } +@AfterReturning("criticalOperation()") +public void phew() { + System.out.println("phew"); +} - @AfterReturning(pointcut="call(Foo+.new(..))",returning="f") - public void itsAFoo(Foo f) { - System.out.println("It's a Foo: " + f); - } - ]]></programlisting> +@AfterReturning(pointcut="call(Foo+.new(..))",returning="f") +public void itsAFoo(Foo f) { + System.out.println("It's a Foo: " + f); +} +]]></programlisting> <para>is equivalent to...</para> <programlisting><![CDATA[ - after() returning : criticalOperation() { - System.out.println("phew"); - } +after() returning : criticalOperation() { + System.out.println("phew"); +} - after() returning(Foo f) : call(Foo+.new(..)) { - System.out.println("It's a Foo: " + f); - } - ]]></programlisting> +after() returning(Foo f) : call(Foo+.new(..)) { + System.out.println("It's a Foo: " + f); +} +]]></programlisting> <para>(Note the use of the "pointcut=" prefix in front of the pointcut expression in the returning case).</para> @@ -557,11 +551,11 @@ </para> <programlisting><![CDATA[ - @Around("call(* org.aspectprogrammer..*(..))") - public Object doNothing() { - return proceed(); // CE on this line - } - ]]></programlisting> +@Around("call(* org.aspectprogrammer..*(..))") +public Object doNothing() { + return proceed(); // CE on this line +} +]]></programlisting> <para>will result in a "No such method" compilation error. For this @@ -573,50 +567,48 @@ </para> <programlisting><![CDATA[ - public interface ProceedingJoinPoint extends JoinPoint { - public Object proceed(Object[] args); - } - ]]></programlisting> +public interface ProceedingJoinPoint extends JoinPoint { + public Object proceed(Object[] args); +} +]]></programlisting> <para>The around advice given above can now be written as:</para> <programlisting><![CDATA[ - @Around("call(* org.aspectprogrammer..*(..))") - public Object doNothing(ProceedingJoinPoint thisJoinPoint) { - return thisJoinPoint.proceed(); - } - ]]></programlisting> +@Around("call(* org.aspectprogrammer..*(..))") +public Object doNothing(ProceedingJoinPoint thisJoinPoint) { + return thisJoinPoint.proceed(); +} +]]></programlisting> <para>Here's an example that uses parameters for the proceed call:</para> <programlisting><![CDATA[ - @Aspect - public class ProceedAspect { - - @Pointcut("call(* setAge(..)) && args(i)") - void setAge(int i) {} +@Aspect +public class ProceedAspect { - @Around("setAge(i)") - public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, int i) { - return thisJoinPoint.proceed(new Object[]{i*2}); //using Java 5 autoboxing - } + @Pointcut("call(* setAge(..)) && args(i)") + void setAge(int i) {} - } + @Around("setAge(i)") + public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, int i) { + return thisJoinPoint.proceed(new Object[]{i*2}); //using Java 5 autoboxing + } - ]]></programlisting> +} +]]></programlisting> <para>is equivalent to:</para> <programlisting><![CDATA[ - public aspect ProceedAspect { - pointcut setAge(int i): call(* setAge(..)) && args(i); - - Object around(int i): setAge(i) { - return proceed(i*2); - } - } - ]]></programlisting> +public aspect ProceedAspect { + pointcut setAge(int i): call(* setAge(..)) && args(i); + Object around(int i): setAge(i) { + return proceed(i*2); + } +} +]]></programlisting> <para>Note that the ProceedingJoinPoint does not need to be passed to the proceed(..) arguments. </para> @@ -626,15 +618,15 @@ <itemizedlist> <listitem>If 'this()' was used in the pointcut <emphasis>for binding</emphasis>, it must be passed first in proceed(..). </listitem> - <listitem>If 'target()' was used in the pointcut <emphasis>for binding</emphasis>, it must be passed next in proceed(..) - it will be the + <listitem>If 'target()' was used in the pointcut <emphasis>for binding</emphasis>, it must be passed next in proceed(..) - it will be the first argument to proceed(..) if this() was not used for binding. </listitem> - <listitem>Finally come <emphasis>all</emphasis> the arguments expected at the join point, in the order they - are supplied at the join point. Effectively the advice signature is ignored - it doesn't - matter if a subset of arguments were bound or the ordering was changed in the advice + <listitem>Finally come <emphasis>all</emphasis> the arguments expected at the join point, in the order they + are supplied at the join point. Effectively the advice signature is ignored - it doesn't + matter if a subset of arguments were bound or the ordering was changed in the advice signature, the proceed(..) calls takes all of them in the right order for the join point. </listitem> - </itemizedlist> + </itemizedlist> </para> <para>Since proceed(..) in this case takes an Object array, AspectJ cannot do as much compile time checking as it can for code style. If the rules above aren't obeyed then it will unfortunately @@ -650,11 +642,11 @@ <para> Inter-type declarations are challenging to support using an annotation style. For code style aspects compiled with the ajc compiler, the entire type system can be made aware of inter-type declarations (new - supertypes, new methods, new fields) and the completeness and correctness of it can be guaranteed. + supertypes, new methods, new fields) and the completeness and correctness of it can be guaranteed. Achieving this with an annotation style is hard because the source code may simply be compiled with javac where the type system cannot be influenced and what is compiled must be 'pure java'. </para> - <para> + <para> AspectJ 1.5.0 introduced @DeclareParents, an attempt to offer something like that which is achievable with code style declare parents and the other intertype declarations (fields, methods, constructors). However, it has proved too challenging to get close to the expressiveness and capabilities of code style in this area @@ -662,12 +654,12 @@ some interface I is mixed into some target type T then this means that all the methods from I are created in T and their implementations are simple forwarding methods that call a delegate which that provides an implementation of I. </para> - <para> - The next section covers @DeclareParents but AspectJ 1.6.4 introduces @DeclareMixin - an improved approach to defining - a mixin and the choice of a different name for the annotation will hopefully alleviate some of the confusion about - why @DeclareParents just doesn't offer the same semantics as the code style variant. Offering @DeclareMixin also gives - code style developers a new tool for a simple mixin whereas previously they would have avoided @DeclareParents - thinking what it could only do was already achievable with code style syntax. + <para> + The next section covers @DeclareParents but AspectJ 1.6.4 introduces @DeclareMixin - an improved approach to defining + a mixin and the choice of a different name for the annotation will hopefully alleviate some of the confusion about + why @DeclareParents just doesn't offer the same semantics as the code style variant. Offering @DeclareMixin also gives + code style developers a new tool for a simple mixin whereas previously they would have avoided @DeclareParents + thinking what it could only do was already achievable with code style syntax. </para> <para> The defaultImpl attribute of @DeclareParents may become deprecated if @DeclareMixin proves popular, leaving @@ -683,23 +675,23 @@ </para> <programlisting><![CDATA[ - public aspect MoodIndicator { +public aspect MoodIndicator { - public interface Moody {}; + public interface Moody {}; - private Mood Moody.mood = Mood.HAPPY; + private Mood Moody.mood = Mood.HAPPY; - public Mood Moody.getMood() { - return mood; - } + public Mood Moody.getMood() { + return mood; + } - declare parents : org.xyz..* implements Moody; + declare parents : org.xyz..* implements Moody; - before(Moody m) : execution(* *.*(..)) && this(m) { - System.out.println("I'm feeling " + m.getMood()); - } - } - ]]></programlisting> + before(Moody m) : execution(* *.*(..)) && this(m) { + System.out.println("I'm feeling " + m.getMood()); + } +} +]]></programlisting> <para> This declares an interface @@ -720,33 +712,33 @@ </para> <programlisting><![CDATA[ - @Aspect - public class MoodIndicator { - - // this interface can be outside of the aspect - public interface Moody { - Mood getMood(); - }; - - // this implementation can be outside of the aspect - public static class MoodyImpl implements Moody { - private Mood mood = Mood.HAPPY; - - public Mood getMood() { - return mood; - } - } - - // the field type must be the introduced interface. It can't be a class. - @DeclareParents(value="org.xzy..*",defaultImpl=MoodyImpl.class) - private Moody implementedInterface; - - @Before("execution(* *.*(..)) && this(m)") - void feelingMoody(Moody m) { - System.out.println("I'm feeling " + m.getMood()); - } - } - ]]></programlisting> +@Aspect +public class MoodIndicator { + + // this interface can be outside of the aspect + public interface Moody { + Mood getMood(); + }; + + // this implementation can be outside of the aspect + public static class MoodyImpl implements Moody { + private Mood mood = Mood.HAPPY; + + public Mood getMood() { + return mood; + } + } + + // the field type must be the introduced interface. It can't be a class. + @DeclareParents(value="org.xzy..*",defaultImpl=MoodyImpl.class) + private Moody implementedInterface; + + @Before("execution(* *.*(..)) && this(m)") + void feelingMoody(Moody m) { + System.out.println("I'm feeling " + m.getMood()); + } +} +]]></programlisting> <para> This is very similar to the mixin mechanism supported by AspectWerkz. The @@ -762,7 +754,7 @@ has access to the exact same set of members as in the code style example. </para> - + <para> Note that it is illegal to use the @DeclareParents annotation on an aspect' field of a non-interface type. The interface type is the inter-type declaration contract that dictates @@ -770,21 +762,21 @@ </para> <programlisting><![CDATA[ - // this type will be affected by the inter-type declaration as the type pattern matches - package org.xyz; - public class MoodTest { - - public void test() { - // see here the cast to the introduced interface (required) - Mood mood = ((Moody)this).getMood(); - ... - } - } - ]]></programlisting> +// this type will be affected by the inter-type declaration as the type pattern matches +package org.xyz; +public class MoodTest { + + public void test() { + // see here the cast to the introduced interface (required) + Mood mood = ((Moody)this).getMood(); + ... + } +} +]]></programlisting> <para>The <literal>@DeclareParents</literal> annotation can also be used without specifying - a <literal>defaultImpl</literal> value (for example, - <literal>@DeclareParents("org.xyz..*")</literal>). This is equivalent to a + a <literal>defaultImpl</literal> value (for example, + <literal>@DeclareParents("org.xyz..*")</literal>). This is equivalent to a <literal>declare parents ... implements</literal> clause, and does <emphasis>not</emphasis> make any inter-type declarations for default implementation of the interface methods. </para> @@ -794,32 +786,30 @@ </para> <programlisting><![CDATA[ - public aspect SerializableMarker { - - declare parents : org.xyz..* implements Serializable; - } - ]]></programlisting> +public aspect SerializableMarker { + declare parents : org.xyz..* implements Serializable; +} +]]></programlisting> <para>Using the annotation style this aspect can be written: </para> <programlisting><![CDATA[ - @Aspect - public class SerializableMarker { - - @DeclareParents("org.xyz..*") - Serializable implementedInterface; - } - ]]></programlisting> +@Aspect +public class SerializableMarker { + @DeclareParents("org.xyz..*") + Serializable implementedInterface; +} +]]></programlisting> <para> If the interface defines one or more operations, and these are not implemented by the target type, an error will be issued during weaving. </para> - + </sect2> - + <sect2 id="atDeclareMixin" xreflabel="atDeclareMixin"> <title>@DeclareMixin</title> <para> @@ -827,26 +817,26 @@ </para> <programlisting><![CDATA[ - public aspect MoodIndicator { +public aspect MoodIndicator { - public interface Moody {}; + public interface Moody {}; - private Mood Moody.mood = Mood.HAPPY; + private Mood Moody.mood = Mood.HAPPY; - public Mood Moody.getMood() { - return mood; - } + public Mood Moody.getMood() { + return mood; + } - declare parents : org.xyz..* implements Moody; + declare parents : org.xyz..* implements Moody; - before(Moody m) : execution(* *.*(..)) && this(m) { - System.out.println("I'm feeling " + m.getMood()); - } - } - ]]></programlisting> + before(Moody m) : execution(* *.*(..)) && this(m) { + System.out.println("I'm feeling " + m.getMood()); + } +} +]]></programlisting> <para> - This declares an interface <literal>Moody</literal>, and then makes two inter-type declarations on the interface + This declares an interface <literal>Moody</literal>, and then makes two inter-type declarations on the interface - a field that is private to the aspect, and a method that returns the mood. Within the body of the inter-type declared method <literal>getMoody</literal>, the type of <literal>this</literal> is <literal>Moody</literal> (the target type of the inter-type declaration). @@ -856,37 +846,37 @@ </para> <programlisting><![CDATA[ - @Aspect - public class MoodIndicator { - - // this interface can be outside of the aspect - public interface Moody { - Mood getMood(); - }; - - // this implementation can be outside of the aspect - public static class MoodyImpl implements Moody { - private Mood mood = Mood.HAPPY; - - public Mood getMood() { - return mood; - } - } - - // The DeclareMixin annotation is attached to a factory method that can return instances of the delegate - // which offers an implementation of the mixin interface. The interface that is mixed in is the - // return type of the method. - @DeclareMixin("org.xyz..*") - public static Moody createMoodyImplementation() { - return new MoodyImpl(); - } - - @Before("execution(* *.*(..)) && this(m)") - void feelingMoody(Moody m) { - System.out.println("I'm feeling " + m.getMood()); - } - } - ]]></programlisting> +@Aspect +public class MoodIndicator { + + // this interface can be outside of the aspect + public interface Moody { + Mood getMood(); + }; + + // this implementation can be outside of the aspect + public static class MoodyImpl implements Moody { + private Mood mood = Mood.HAPPY; + + public Mood getMood() { + return mood; + } + } + + // The DeclareMixin annotation is attached to a factory method that can return instances of the delegate + // which offers an implementation of the mixin interface. The interface that is mixed in is the + // return type of the method. + @DeclareMixin("org.xyz..*") + public static Moody createMoodyImplementation() { + return new MoodyImpl(); + } + + @Before("execution(* *.*(..)) && this(m)") + void feelingMoody(Moody m) { + System.out.println("I'm feeling " + m.getMood()); + } +} +]]></programlisting> <para> Basically, the <literal>@DeclareMixin</literal> annotation is attached to a factory method. The @@ -894,24 +884,24 @@ create an instance of a delegate that implements the interface. This is the interface which will be delegated to from any target matching the specified type pattern. </para> - + <para> Exploiting this syntax requires the user to obey the rules of pure Java. So references to any targeted type as if it were affected by the Mixin must be made through a cast, like this: </para> - + <programlisting><![CDATA[ - // this type will be affected by the inter-type declaration as the type pattern matches - package org.xyz; - public class MoodTest { - - public void test() { - // see here the cast to the introduced interface (required) - Mood mood = ((Moody)this).getMood(); - ... - } - } - ]]></programlisting> +// this type will be affected by the inter-type declaration as the type pattern matches +package org.xyz; +public class MoodTest { + + public void test() { + // see here the cast to the introduced interface (required) + Mood mood = ((Moody)this).getMood(); + ... + } +} +]]></programlisting> <para> Sometimes the delegate instance may want to perform differently depending upon the type/instance for @@ -920,54 +910,52 @@ which a delegate should be created: </para> <programlisting><![CDATA[ - - @Aspect - public class Foo { - - @DeclareMixin("org.xyz..*") - public static SomeInterface createDelegate(Object instance) { - return new SomeImplementation(instance); - } - } - ]]></programlisting> - +@Aspect +public class Foo { + + @DeclareMixin("org.xyz..*") + public static SomeInterface createDelegate(Object instance) { + return new SomeImplementation(instance); + } +} +]]></programlisting> + <para> - It is also possible to make the factory method non-static - and in this case it can then exploit + It is also possible to make the factory method non-static - and in this case it can then exploit the local state in the surrounding aspect instance, but this is only supported for singleton aspects: </para> <programlisting><![CDATA[ - - @Aspect - public class Foo { - public int maxLimit=35; - - @DeclareMixin("org.xyz..*") - public SomeInterface createDelegate(Object instance) { - return new SomeImplementation(instance,maxLimit); - } - } - ]]></programlisting> - +@Aspect +public class Foo { + public int maxLimit=35; + + @DeclareMixin("org.xyz..*") + public SomeInterface createDelegate(Object instance) { + return new SomeImplementation(instance,maxLimit); + } +} +]]></programlisting> + <para> Although the interface type is usually determined purely from the return type of the factory method, it can be specified in the annotation if necessary. In this example the return type of the method extends multiple other interfaces and only a couple of them (I and J) should be mixed into any matching targets: </para> <programlisting><![CDATA[ - // interfaces is an array of interface classes that should be mixed in - @DeclareMixin(value="org.xyz..*",interfaces={I.class,J.class}) - public static InterfaceExtendingLotsOfInterfaces createMoodyImplementation() { - return new MoodyImpl(); - } - ]]></programlisting> - +// interfaces is an array of interface classes that should be mixed in +@DeclareMixin(value="org.xyz..*",interfaces={I.class,J.class}) +public static InterfaceExtendingLotsOfInterfaces createMoodyImplementation() { + return new MoodyImpl(); +} +]]></programlisting> + <para> There are clearly similarities between <literal>@DeclareMixin</literal> and <literal>@DeclareParents</literal> but <literal>@DeclareMixin</literal> is not pretending to offer more than a simple mixin strategy. The flexibility in - being able to provide the factory method instead of requiring a no-arg constructor for the implementation also + being able to provide the factory method instead of requiring a no-arg constructor for the implementation also enables delegate instances to make decisions based upon the type for which they are the delegate. </para> - + <para> Any annotations defined on the interface methods are also put upon the delegate forwarding methods created in the matched target type. @@ -997,21 +985,24 @@ </para> <programlisting><![CDATA[ - public aspect SystemArchitecture { - declare precedence : Security*, TransactionSupport, Persistence; +public aspect SystemArchitecture { + declare precedence : Security*, TransactionSupport, Persistence; - // ... - } + // ... +} +]]></programlisting> - can be written as: - - @Aspect - @DeclarePrecedence("Security*,org.xyz.TransactionSupport,org.xyz.Persistence") - public class SystemArchitecture { + <para> + can be written as: + </para> - // ... - } - ]]></programlisting> + <programlisting><![CDATA[ +@Aspect +@DeclarePrecedence("Security*,org.xyz.TransactionSupport,org.xyz.Persistence") +public class SystemArchitecture { + // ... +} +]]></programlisting> <!-- note: below is not supported for now. @@ -1026,32 +1017,34 @@ </para> <programlisting><![CDATA[ - public aspect DeclareAnnotationExamples { - declare annotation : org.xyz.model..* : @BusinessDomain; +public aspect DeclareAnnotationExamples { + declare annotation : org.xyz.model..* : @BusinessDomain; - declare annotation : public * BankAccount+.*(..) : @Secured(role="supervisor"); + declare annotation : public * BankAccount+.*(..) : @Secured(role="supervisor"); - declare anotation : * DAO+.* : @Persisted; + declare anotation : * DAO+.* : @Persisted; - } +} +]]></programlisting> - can be written as... + <para>can be written as...</para> - @Aspect - public class DeclareAnnotationExamples { + <programlisting><![CDATA[ +@Aspect +public class DeclareAnnotationExamples { - @DeclareAnnotation("org.xyz.model..*) - @BusinessDomain Object modelClass; + @DeclareAnnotation("org.xyz.model..*) + @BusinessDomain Object modelClass; - // this example assumes that the @Secured annotation has a Target - // annotation with value ElementType.METHOD - @DeclareAnnotation("public * org.xyz.banking.BankAccount+.*(..)") - @Secured(role="supervisor) void bankAccountMethod(); + // this example assumes that the @Secured annotation has a Target + // annotation with value ElementType.METHOD + @DeclareAnnotation("public * org.xyz.banking.BankAccount+.*(..)") + @Secured(role="supervisor) void bankAccountMethod(); - @DeclareAnnotation("* DAO+.*") - @Persisted Object daoFields; - } - ]]></programlisting> + @DeclareAnnotation("* DAO+.*") + @Persisted Object daoFields; +} +]]></programlisting> <para> <emphasis>Note: Declare annotation is not available in AspectJ 1.5 M3 and syntax may change @@ -1069,29 +1062,29 @@ of a static method for example.</para> <programlisting><![CDATA[ - declare warning : call(* javax.sql..*(..)) && !within(org.xyz.daos..*) - : "Only DAOs should be calling JDBC."; - - declare error : execution(* IFoo+.*(..)) && !within(org.foo..*) - : "Only foo types can implement IFoo"; +declare warning : call(* javax.sql..*(..)) && !within(org.xyz.daos..*) + : "Only DAOs should be calling JDBC."; - can be written as... +declare error : execution(* IFoo+.*(..)) && !within(org.foo..*) + : "Only foo types can implement IFoo"; +]]></programlisting> - @DeclareWarning("call(* javax.sql..*(..)) && !within(org.xyz.daos..*)") - static final String aMessage = "Only DAOs should be calling JDBC."; + <para>can be written as...</para> - @DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)") - static final String badIFooImplementors = "Only foo types can implement IFoo"; - - // the following is not valid since the message is not a String literal - @DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)") - static final String badIFooImplementorsCorrupted = getMessage(); - static String getMessage() { - return "Only foo types can implement IFoo " + System.currentTimeMillis(); - } + <programlisting><![CDATA[ +@DeclareWarning("call(* javax.sql..*(..)) && !within(org.xyz.daos..*)") +static final String aMessage = "Only DAOs should be calling JDBC."; - ]]></programlisting> +@DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)") +static final String badIFooImplementors = "Only foo types can implement IFoo"; +// the following is not valid since the message is not a String literal +@DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)") +static final String badIFooImplementorsCorrupted = getMessage(); +static String getMessage() { + return "Only foo types can implement IFoo " + System.currentTimeMillis(); +} +]]></programlisting> </sect1> @@ -1117,27 +1110,27 @@ </para> <programlisting><![CDATA[ - public class Aspects { +public class Aspects { - /* variation used for singleton, percflow, percflowbelow */ - static<T> public static T aspectOf(T aspectType) {...} + /* variation used for singleton, percflow, percflowbelow */ + static<T> public static T aspectOf(T aspectType) {...} - /* variation used for perthis, pertarget */ - static<T> public static T aspectOf(T aspectType, Object forObject) {...} + /* variation used for perthis, pertarget */ + static<T> public static T aspectOf(T aspectType, Object forObject) {...} - /* variation used for pertypewithin */ - static<T> public static T aspectOf(T aspectType, Class forType) {...} + /* variation used for pertypewithin */ + static<T> public static T aspectOf(T aspectType, Class forType) {...} - /* variation used for singleton, percflow, percflowbelow */ - public static boolean hasAspect(Object anAspect) {...} + /* variation used for singleton, percflow, percflowbelow */ + public static boolean hasAspect(Object anAspect) {...} - /* variation used for perthis, pertarget */ - public static boolean hasAspect(Object anAspect, Object forObject) {...} + /* variation used for perthis, pertarget */ + public static boolean hasAspect(Object anAspect, Object forObject) {...} - /* variation used for pertypewithin */ - public static boolean hasAspect(Object anAspect, Class forType) {...} - } - ]]></programlisting> + /* variation used for pertypewithin */ + public static boolean hasAspect(Object anAspect, Class forType) {...} +} +]]></programlisting> <!-- TODO AV - stuff below is not done --> <!-- diff --git a/docs/adk15ProgGuideDB/autoboxing.xml b/docs/adk15ProgGuideDB/autoboxing.xml index ec19fb7fe..7a3cdaca1 100644 --- a/docs/adk15ProgGuideDB/autoboxing.xml +++ b/docs/adk15ProgGuideDB/autoboxing.xml @@ -1,54 +1,54 @@ <chapter id="autoboxing" xreflabel="Autoboxing and Unboxing"> <title>Autoboxing and Unboxing</title> - + <sect1 id="boxing-inJava5"> <title>Autoboxing and Unboxing in Java 5</title> - + <para> - Java 5 (and hence AspectJ 1.5) supports automatic conversion of + Java 5 (and hence AspectJ 1.5) supports automatic conversion of primitive types (int, float, double etc.) to their object equivalents (Integer, Float, Double,...) in assignments and method and constructor invocations. This conversion is know as autoboxing. </para> - + <para>Java 5 also supports automatic unboxing, where wrapper types are automatically converted into their primitive equivalents if needed for assignments or method or constructor invocations.</para> - + <para>For example:</para> <programlisting><![CDATA[ - int i = 0; - i = new Integer(5); // auto-unboxing - - Integer i2 = 5; // autoboxing - ]]></programlisting> - +int i = 0; +i = new Integer(5); // auto-unboxing + +Integer i2 = 5; // autoboxing +]]></programlisting> + </sect1> - + <sect1 id="autoboxing-in-aspectj5"> <title>Autoboxing and Join Point matching in AspectJ 5</title> - + <para>Most of the pointcut designators match based on signatures, and hence are unaffected by autoboxing. For example, a call to a method</para> <programlisting><![CDATA[ - public void foo(Integer i); - ]]></programlisting> - +public void foo(Integer i); +]]></programlisting> + <para>is <emphasis>not</emphasis> matched by a pointcut <literal>call(void foo(int))</literal> since the signature declares a single <literal>Integer</literal> parameter, not an <literal>int</literal>. </para> - + <para>The <literal>args</literal> pointcut designator is affected by autoboxing since it matches based on the runtime type of the arguments. AspectJ 5 applies autoboxing and unboxing in determining argument matching. In other words, <literal>args(Integer)</literal> will match any join point at which there is a single argument of type <literal>Integer</literal> or of type <literal>int</literal>.</para> - + <itemizedlist> <listitem>args(Integer) and args(int) are equivalent</listitem> <listitem>args(Float) and args(float) are equivalent</listitem> @@ -58,29 +58,29 @@ <listitem>args(Long) and args(long) are equivalent</listitem> <listitem>args(Boolean) and args(boolean) are equivalent</listitem> </itemizedlist> - + <para> - Autoboxing and unboxing are also applied when binding pointcut or - advice parameters, for example: + Autoboxing and unboxing are also applied when binding pointcut or + advice parameters, for example: </para> <programlisting><![CDATA[ - pointcut foo(int i) : args(i); - - before(Integer i) : foo(i) { - ... - } - ]]></programlisting> +pointcut foo(int i) : args(i); + +before(Integer i) : foo(i) { + ... +} +]]></programlisting> </sect1> - + <sect1 id="autoboxing-and-method-dispatch"> <title>Inter-type method declarations and method dispatch</title> - + <para>Autoboxing, unboxing, and also varargs all affect the method dispatch algorithm used in Java 5. In AspectJ 5, the target method of a call is selected according to the following algorithm:</para> - + <orderedlist> <listitem>Attempt to locate a matching method or inter-type declared method without considering @@ -90,11 +90,11 @@ <listitem>Finally try again considering both autoboxing, unboxing, and varargs.</listitem> </orderedlist> - + <para>One consequence is that a directly matching inter-type declared - method will take precedence over a method declared locally in the + method will take precedence over a method declared locally in the target class but that only matches via autoboxing.</para> </sect1> - + </chapter> diff --git a/docs/adk15ProgGuideDB/covariance.xml b/docs/adk15ProgGuideDB/covariance.xml index 2268258f3..e8845ddb8 100644 --- a/docs/adk15ProgGuideDB/covariance.xml +++ b/docs/adk15ProgGuideDB/covariance.xml @@ -1,64 +1,64 @@ <chapter id="covariance" xreflabel="Covariance"> <title>Covariance</title> - + <sect1 id="covariance-inJava5"> <title>Covariance in Java 5</title> - + <para> Java 5 (and hence AspectJ 5) allows you to narrow the return type in an overriding method. For example: </para> <programlisting><![CDATA[ - class A { - public A whoAreYou() {...} - } - - class B extends A { - // override A.whoAreYou *and* narrow the return type. - public B whoAreYou() {...} - } - ]]></programlisting> - +class A { + public A whoAreYou() {...} +} + +class B extends A { + // override A.whoAreYou *and* narrow the return type. + public B whoAreYou() {...} +} +]]></programlisting> + </sect1> - + <sect1 id="covariance-and-join-point-matching"> <title>Covariant methods and Join Point matching</title> - + <para>The join point matching rules for <literal>call</literal> and <literal>execution</literal> pointcut designators are extended to match against covariant methods.</para> - + <para> Given the classes <literal>A</literal> and <literal>B</literal> as defined in the previous section, and the program fragment </para> <programlisting><![CDATA[ - A a = new A(); - B b = new B(); - a.whoAreYou(); - b.whoAreYou(); - ]]></programlisting> - - <para>The signatures for the call join point <literal>a.whoAreYou()</literal> are - simply:</para> +A a = new A(); +B b = new B(); +a.whoAreYou(); +b.whoAreYou(); +]]></programlisting> - <programlisting><![CDATA[ - A A.whoAreYou() - ]]></programlisting> - - <para>The signatures for the call join point <literal>b.whoAreYou()</literal> are: - </para> +<para>The signatures for the call join point <literal>a.whoAreYou()</literal> are +simply:</para> + +<programlisting><![CDATA[ +A A.whoAreYou() +]]></programlisting> + +<para>The signatures for the call join point <literal>b.whoAreYou()</literal> are: +</para> + +<programlisting><![CDATA[ +A A.whoAreYou() +B B.whoAreYou() +]]></programlisting> - <programlisting><![CDATA[ - A A.whoAreYou() - B B.whoAreYou() - ]]></programlisting> - <para>Following the join point matching rules given in <xref linkend="jpsigs"/>,</para> - + <variablelist> <varlistentry> @@ -87,7 +87,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>call(A B.whoAreYou())</term> <listitem> @@ -98,22 +98,22 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>call(A+ B.whoAreYou())</term> <listitem> <para>Matches the call to <literal>b.whoAreYou()</literal> since - the signature pattern matches the signature <literal>B B.whoAreYou()</literal>. + the signature pattern matches the signature <literal>B B.whoAreYou()</literal>. A lint warning is given for the call <literal>a.whoAreYou()</literal> ("does not match because declaring type is A, if match required use target(B)"). </para> </listitem> </varlistentry> - + <varlistentry> <term>call(B A.whoAreYou())</term> <listitem> - <para>Does not match anything since neither join point has a + <para>Does not match anything since neither join point has a signature matched by this pattern. </para> </listitem> @@ -136,13 +136,13 @@ </varlistentry> </variablelist> - + <para>The rule for signature matching at call and execution join points is unchanged from AspectJ 1.2: a call or execution pointcut matches if the signature pattern matches at least one of the signatures of the join point, and if the modifiers of the method or constructor are matched by any modifier pattern or annotation pattern that may be present.</para> - + </sect1> </chapter> diff --git a/docs/adk15ProgGuideDB/enumeratedtypes.xml b/docs/adk15ProgGuideDB/enumeratedtypes.xml index 2fc2ec14e..717252435 100644 --- a/docs/adk15ProgGuideDB/enumeratedtypes.xml +++ b/docs/adk15ProgGuideDB/enumeratedtypes.xml @@ -1,38 +1,38 @@ <chapter id="enumeratedtypes" xreflabel="Enumerated Types"> <title>Enumerated Types</title> - + <sect1 id="enums-in-java5"> <title>Enumerated Types in Java 5</title> - + <para>Java 5 (and hence AspectJ 5) provides explicit support for enumerated types. In the simplest case, you can declare an enumerated type as follows:</para> - + <programlisting><![CDATA[ - public enum ProgrammingLanguages { - COBOL,C,JAVA,ASPECTJ - } - ]]></programlisting> - +public enum ProgrammingLanguages { + COBOL, C, JAVA, ASPECTJ +} +]]></programlisting> + <para>Enumerated types are just classes, and they can contain method and field declarations, and may implement interfaces. Enums may only have private constructors, and may not be extended.</para> - + <para>Enumerated types in Java 5 all implicitly extend the type <literal>java.lang.Enum</literal>. It is illegal to explicitly declare a subtype of this class.</para> </sect1> - + <sect1 id="enums-in-aspectj5"> <title>Enumerated Types in AspectJ 5</title> - + <para> AspectJ 5 supports the declaration of enumerated types just as Java 5 does. Because of the special restrictions Java 5 places around enumerated types, AspectJ makes the following additional restrictions: </para> - + <itemizedlist> <listitem>You cannot use declare parents to change the super type of an enum.</listitem> @@ -42,23 +42,23 @@ enum.</listitem> <listitem>You cannot extend the set of values in an enum via any ITD-like construct.</listitem> - <listitem>You cannot make inter-type method or field declarations on + <listitem>You cannot make inter-type method or field declarations on an enum.</listitem> <listitem>You cannot use declare parents to make an enum type implement an interface.</listitem> </itemizedlist> - + <para>In theory, the last of these two items <emphasis>could</emphasis> be supported. However, AspectJ 5 follows the simple rule that <emphasis> an enum type cannot be the target of an inter-type declaration or declare parents statement</emphasis>. This position may be relaxed in a future version of AspectJ.</para> - + <para>If an enum is named explicitly as the target of a declare parents statement, a compilation error will result. If an enumerated type is matched by a non-explicit type pattern used in a declare parents statement it will be ignored (and an XLint warning issued).</para> </sect1> - + </chapter> diff --git a/docs/adk15ProgGuideDB/generics.xml b/docs/adk15ProgGuideDB/generics.xml index 89370fee6..f780ff67d 100644 --- a/docs/adk15ProgGuideDB/generics.xml +++ b/docs/adk15ProgGuideDB/generics.xml @@ -3,7 +3,7 @@ <chapter id="generics" xreflabel="Generics"> <title>Generics</title> - + <sect1 id="generics-inJava5"> <title>Generics in Java 5</title> @@ -16,40 +16,40 @@ <sect2 id="declaring-generic-types" xreflabel="declaring-generic-types"> <title>Declaring Generic Types</title> - + <para> - A generic type is declared with one or more type parameters following the type name. - By convention formal type parameters are named using a single letter, though this is not required. + A generic type is declared with one or more type parameters following the type name. + By convention formal type parameters are named using a single letter, though this is not required. A simple generic list type (that can contain elements of any type <literal>E</literal>) could be declared: </para> - + <programlisting><![CDATA[ - interface List<E> { - Iterator<E> iterator(); - void add(E anItem); - E remove(E anItem); - } - ]]></programlisting> - - +interface List<E> { + Iterator<E> iterator(); + void add(E anItem); + E remove(E anItem); +} +]]></programlisting> + + <para> - It is important to understand that unlike template mechanisms there will only be one type, and one class file, corresponding to + It is important to understand that unlike template mechanisms there will only be one type, and one class file, corresponding to the <literal>List</literal> interface, regardless of how many different instantiations of the <literal>List</literal> interface a program has (each potentially providing a different value for the type parameter <literal>E</literal>). A consequence of this - is that you cannot refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or - initializer of a static variable. - </para> + is that you cannot refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or + initializer of a static variable. + </para> <para> - A <emphasis>parameterized type</emphasis> + A <emphasis>parameterized type</emphasis> is an invocation of a generic type with concrete values supplied for all of its type parameters (for example, <literal>List<String></literal> or <literal>List<Food></literal>). </para> - + <para>A generic type may be declared with multiple type parameters. In addition to simple type parameter names, type - parameter declarations can also constrain the set of types allowed by using the <literal>extends</literal> + parameter declarations can also constrain the set of types allowed by using the <literal>extends</literal> keyword. Some examples follow:</para> - + <variablelist> <varlistentry> @@ -67,7 +67,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>class Foo<T extends Number> {...}</term> <listitem> @@ -76,7 +76,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>class Foo<T, S extends T> {...}</term> <listitem> @@ -85,7 +85,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>class Foo<T extends Number & Comparable> {...}</term> <listitem> @@ -94,42 +94,42 @@ </para> </listitem> </varlistentry> - + </variablelist> - + </sect2> - + <sect2 id="using-generic-and-parameterized-types" xreflabel="using-generic-and-parameterized-types"> <title>Using Generic and Parameterized Types</title> - + <para>You declare a variable (or a method/constructor argument) of a parameterized type by specifying a concrete type specfication for each type parameter in the generic type. The following example declares a list of strings and a list of numbers:</para> - + <programlisting><![CDATA[ - List<String> strings; - List<Number> numbers; - ]]></programlisting> - +List<String> strings; +List<Number> numbers; +]]></programlisting> + <para>It is also possible to declare a variable of a generic type without specifying any values for the type - parameters (a <emphasis>raw</emphasis> type). For example, <literal>List strings</literal>. + parameters (a <emphasis>raw</emphasis> type). For example, <literal>List strings</literal>. In this case, unchecked warnings may be issued by the compiler - when the referenced object is passed as a parameter to a method expecting a parameterized type such as a + when the referenced object is passed as a parameter to a method expecting a parameterized type such as a <literal>List<String></literal>. New code written in the Java 5 language would not be expected to use raw types.</para> - + <para>Parameterized types are instantiated by specifying type parameter values in the constructor call expression as in - the following examples:</para> + the following examples:</para> <programlisting><![CDATA[ - List<String> strings = new MyListImpl<String>(); - List<Number> numbers = new MyListImpl<Number>(); - ]]></programlisting> +List<String> strings = new MyListImpl<String>(); +List<Number> numbers = new MyListImpl<Number>(); +]]></programlisting> <para> When declaring parameterized types, the <literal>?</literal> wildcard may be used, which stands for "some type". The <literal>extends</literal> and <literal>super</literal> keywords may be used in conjunction with the wildcard to provide upper and lower bounds on the types that may satisfy the type constraints. For example: - </para> + </para> <variablelist> @@ -158,11 +158,11 @@ </varlistentry> </variablelist> - + <para> A generic type may be extended as any other type. Given a generic type <literal>Foo<T></literal> then - a subtype <literal>Goo</literal> may be declared in one of the following ways: - </para> + a subtype <literal>Goo</literal> may be declared in one of the following ways: + </para> <variablelist> @@ -180,7 +180,7 @@ <listitem> <para><literal>Goo</literal> is a generic type, but the super-type <literal>Foo</literal> is used as a raw type and the appropriate warning messages will be - issued by the compiler on attempting to invoke methods defined by <literal>Foo</literal>. + issued by the compiler on attempting to invoke methods defined by <literal>Foo</literal>. </para> </listitem> </varlistentry> @@ -189,7 +189,7 @@ <term>class Goo<E> extends Foo<E></term> <listitem> <para>This is the most usual form. <literal>Goo</literal> is a generic type with one parameter that extends - the generic type <literal>Foo</literal> with that same parameter. So <literal>Goo<String<</literal> is + the generic type <literal>Foo</literal> with that same parameter. So <literal>Goo<String<</literal> is a subclass of <literal>Foo<String></literal>. </para> </listitem> @@ -200,7 +200,7 @@ <listitem> <para><literal>Goo</literal> is a generic type with two parameters that extends the generic type <literal>Foo</literal> with the first type parameter of <literal>Goo</literal> being used - to parameterize <literal>Foo</literal>. So <literal>Goo<String,Integer<</literal> is + to parameterize <literal>Foo</literal>. So <literal>Goo<String,Integer<</literal> is a subclass of <literal>Foo<String></literal>. </para> </listitem> @@ -216,29 +216,29 @@ </varlistentry> </variablelist> - + <para>A generic type may implement one or more generic interfaces, following the type binding rules given above. A type may also implement one or more parameterized interfaces (for example, <literal>class X implements List<String></literal>, however a type may not at the same time be a subtype of two interface types which are different parameterizations of the same interface.</para> </sect2> - + <sect2 id="subtypes-supertypes-and-assignability" xreflabel="subtypes-supertypes-and-assignability"> <title>Subtypes, Supertypes, and Assignability</title> - + <para> The supertype of a generic type <literal>C</literal> is the type given in the extends clause of <literal>C</literal>, or <literal>Object</literal> if no extends clause is present. Given the type declaration </para> <programlisting><![CDATA[ - public interface List<E> extends Collection<E> {... } - ]]></programlisting> - +public interface List<E> extends Collection<E> {... } +]]></programlisting> + <para> then the supertype of <literal>List<E></literal> is <literal>Collection<E></literal>. </para> - + <para> The supertype of a parameterized type <literal>P</literal> is the type given in the extends clause of <literal>P</literal>, or <literal>Object</literal> if no extends clause is present. Any type parameters in @@ -248,21 +248,21 @@ <literal>Collection<Double></literal>. <literal>List<Double></literal> is <emphasis>not</emphasis> considered to be a subtype of <literal>List<Number></literal>. </para> - + <para> - An instance of a parameterized type <literal>P<T1,T2,...Tn></literal>may be assigned to a variable of + An instance of a parameterized type <literal>P<T1,T2,...Tn></literal>may be assigned to a variable of the same type or a supertype without casting. In addition it may be assigned to a variable <literal>R<S1,S2,...Sm></literal> where - <literal>R</literal> is a supertype of <literal>P</literal> (the supertype relationship is reflexive), + <literal>R</literal> is a supertype of <literal>P</literal> (the supertype relationship is reflexive), <literal>m <= n</literal>, and for all type parameters <literal>S1..m</literal>, <literal>Tm</literal> equals - <literal>Sm</literal> <emphasis>or</emphasis> <literal>Sm</literal> is a wildcard type specification and + <literal>Sm</literal> <emphasis>or</emphasis> <literal>Sm</literal> is a wildcard type specification and <literal>Tm</literal> falls within the bounds of the wildcard. For example, <literal>List<String></literal> can be assigned to a variable of type <literal>Collection<?></literal>, and <literal>List<Double></literal> - can be assigned to a variable of type <literal>List<? extends Number></literal>. + can be assigned to a variable of type <literal>List<? extends Number></literal>. </para> - + </sect2> - + <sect2 id="generic-methods-and-constructors" xreflabel="generic-methods-and-constructors"> <title>Generic Methods and Constructors</title> <para> @@ -270,26 +270,26 @@ </para> <programlisting><![CDATA[ - static <T> T first(List<T> ts) { ... } - ]]></programlisting> - +static <T> T first(List<T> ts) { ... } +]]></programlisting> + <para> Such a definition can appear in any type, the type parameter <literal>T</literal> does not need to be declared as a type parameter of the enclosing type. </para> - + <para> Non-static methods may also be declared with one or more type parameters in a similar fashion: </para> - + <programlisting><![CDATA[ - <T extends Number> T max(T t1, T t2) { ... } - ]]></programlisting> - +<T extends Number> T max(T t1, T t2) { ... } +]]></programlisting> + <para>The same technique can be used to declare a generic constructor.</para> - + </sect2> - + <sect2 id="erasure" xreflabel="erasure"> <title>Erasure</title> <para>Generics in Java are implemented using a technique called <emphasis>erasure</emphasis>. All @@ -301,181 +301,177 @@ </sect1> <!-- ===================================================================== --> - + <sect1 id="generics-inAspectJ5"> <title>Generics in AspectJ 5</title> - + <para> - AspectJ 5 provides full support for all of the Java 5 language features, including generics. Any legal Java 5 program is a + AspectJ 5 provides full support for all of the Java 5 language features, including generics. Any legal Java 5 program is a legal AspectJ 5 progam. In addition, AspectJ 5 provides support for generic and parameterized types in pointcuts, inter-type - declarations, and declare statements. Parameterized types may freely be used within aspect members, and support is + declarations, and declare statements. Parameterized types may freely be used within aspect members, and support is also provided for generic <emphasis>abstract</emphasis> aspects. </para> - + <sect2 id="matching-generic-and-parameterized-types-in-pointcut-expressions" xreflabel="matching-generic-and-parameterized-types-in-pointcut-expressions"> <title>Matching generic and parameterized types in pointcut expressions</title> - + <para> The simplest way to work with generic and parameterized types in pointcut expressions and type patterns is simply to use the raw type name. For example, the type pattern <literal>List</literal> will match - the generic type <literal>List<E></literal> and any parameterization of that type - (<literal>List<String>, List<?>, List<? extends Number></literal> and so on. This + the generic type <literal>List<E></literal> and any parameterization of that type + (<literal>List<String>, List<?>, List<? extends Number></literal> and so on. This ensures that pointcuts written in existing code that is not generics-aware will continue to work as expected in AspectJ 5. It is also the recommended way to match against generic and parameterized types in AspectJ 5 unless you explicitly wish to narrow matches to certain parameterizations of a generic type. </para> - + <para>Generic methods and constructors, and members defined in generic types, may use type variables as part of their signature. For example:</para> <programlisting><![CDATA[ - public class Utils { - - /** static generic method */ - static <T> T first(List<T> ts) { ... } - - /** instance generic method */ - <T extends Number> T max(T t1, T t2) { ... } - - } - - public class G<T> { - - // field with parameterized type - T myData; - - // method with parameterized return type - public List<T> getAllDataItems() {...} - - } - ]]></programlisting> - +public class Utils { + + /** static generic method */ + static <T> T first(List<T> ts) { ... } + + /** instance generic method */ + <T extends Number> T max(T t1, T t2) { ... } + +} + +public class G<T> { + + // field with parameterized type + T myData; + + // method with parameterized return type + public List<T> getAllDataItems() {...} + +} +]]></programlisting> + <para> AspectJ 5 does not allow the use of type variables in pointcut expressions and type patterns. Instead, members that use type parameters as part of their signature are matched by their <emphasis>erasure</emphasis>. Java 5 defines the rules for determing the erasure of a type as follows. </para> - + <para>Let <literal>|T|</literal> represent the erasure of some type <literal>T</literal>. Then:</para> - + <simplelist> <member>The erasure of a parameterized type <literal>T<T1,...,Tn></literal> is <literal>|T|</literal>. For example, the erasure of <literal>List<String></literal> is <literal>List</literal>.</member> - + <member>The erasure of a nested type <literal>T.C</literal> is <literal>|T|.C</literal>. For example, the erasure of the nested type <literal>Foo<T>.Bar</literal> is <literal>Foo.Bar</literal>.</member> - + <member>The erasure of an array type <literal>T[]</literal> is <literal>|T|[]</literal>. For example, the erasure of <literal>List<String>[]</literal> is <literal>List[]</literal>.</member> - - <member>The erasure of a type variable is its leftmost bound. For example, the erasure of a + + <member>The erasure of a type variable is its leftmost bound. For example, the erasure of a type variable <literal>P</literal> is <literal>Object</literal>, and the erasure of a type variable <literal>N extends Number</literal> is <literal>Number</literal>.</member> - + <member>The erasure of every other type is the type itself</member> </simplelist> - + <!-- see tests/java5/generics/ajdk/ErasureMatching.aj --> <para>Applying these rules to the earlier examples, we find that the methods defined in <literal>Utils</literal> can be matched by a signature pattern matching <literal>static Object Utils.first(List)</literal> and <literal>Number Utils.max(Number, Number)</literal> respectively. The members of the generic type <literal>G</literal> can be matched by a signature pattern matching <literal>Object G.myData</literal> and <literal>public List G.getAllDataItems()</literal> respectively.</para> - + <sect3> <title>Restricting matching using parameterized types</title> - + <para>Pointcut matching can be further restricted to match only given parameterizations of parameter types (methods and constructors), return - types (methods) and field types (fields). This is achieved by specifying a parameterized type pattern at the appropriate point + types (methods) and field types (fields). This is achieved by specifying a parameterized type pattern at the appropriate point in the signature pattern. For example, given the class <literal>Foo</literal>:</para> <programlisting><![CDATA[ - public class Foo { - - List<String> myStrings; - List<Float> myFloats; - - public List<String> getStrings() { return myStrings; } - public List<Float> getFloats() { return myFloats; } - - public void addStrings(List<String> evenMoreStrings) { - myStrings.addAll(evenMoreStrings); - } - - } - ]]></programlisting> +public class Foo { + + List<String> myStrings; + List<Float> myFloats; + + public List<String> getStrings() { return myStrings; } + public List<Float> getFloats() { return myFloats; } + + public void addStrings(List<String> evenMoreStrings) { + myStrings.addAll(evenMoreStrings); + } + +} +]]></programlisting> <!-- see tests/java5/generics/ajdk/SimpleParameterizedTypeExamples.aj --> - + <para>Then a <literal>get</literal> join point for the field <literal>myStrings</literal> can be matched by the pointcut <literal>get(List Foo.myStrings)</literal> and by the pointcut <literal>get(List<String> Foo.myStrings)</literal>, but <emphasis>not</emphasis> by the pointcut <literal>get(List<Number> *)</literal>.</para> - + <para>A <literal>get</literal> join point for the field <literal>myFloats</literal> can be matched by the pointcut <literal>get(List Foo.myFloats)</literal>, the pointcut <literal>get(List<Float> *)</literal>, and the pointcut <literal>get(List<Number+> *)</literal>. This last example shows how AspectJ type patterns can be used to match type parameters types just like any other type. The pointcut <literal>get(List<Double> *)</literal> does <emphasis>not</emphasis> match.</para> - + <para>The execution of the methods <literal>getStrings</literal> and <literal>getFloats</literal> can be matched by the pointcut expression <literal>execution(List get*(..))</literal>, and the pointcut expression <literal>execution(List<*> get*(..))</literal>, but only <literal>getStrings</literal> is matched by <literal>execution(List<String> get*(..))</literal> and only <literal>getFloats</literal> is matched by <literal>execution(List<Number+> get*(..))</literal></para> - + <para>A call to the method <literal>addStrings</literal> can be matched by the pointcut expression <literal>call(* addStrings(List))</literal> and by the expression <literal>call(* addStrings(List<String>))</literal>, but <emphasis>not</emphasis> by the expression <literal>call(* addStrings(List<Number>))</literal>. </para> - + <para>Remember that any type variable reference in a generic member is <emphasis>always</emphasis> matched by its erasure. Thus given the following example:</para> - + <programlisting><![CDATA[ - class G<T> { - - List<T> foo(List<String> ls) { return null; } - - } - ]]></programlisting> - +class G<T> { + List<T> foo(List<String> ls) { return null; } +} +]]></programlisting> + <!-- see tests/java5/generics/ajdk/MixedParameterizedAndTypeVariables.aj --> <para>The execution of <literal>foo</literal> can be matched by - <literal>execution(List foo(List))</literal>, - <literal>execution(List foo(List<String>>))</literal>, and - <literal>execution(* foo(List<String<))</literal>but + <literal>execution(List foo(List))</literal>, + <literal>execution(List foo(List<String>>))</literal>, and + <literal>execution(* foo(List<String<))</literal>but <emphasis>not</emphasis> by <literal>execution(List<Object> foo(List<String>>)</literal> since the erasure of <literal>List<T></literal> is <literal>List</literal> and not <literal>List<Object></literal>. </para> - + </sect3> - + <sect3> <title>Generic wildcards and signature matching</title> - + <para> When it comes to signature matching, a type parameterized using a generic wildcard is a distinct type. For example, <literal>List<?></literal> is a very different type to <literal>List<String></literal>, even though a variable of type <literal>List<String></literal> can be assigned to a variable of type <literal>List<?></literal>. Given the methods: </para> - + <programlisting><![CDATA[ - class C { - - public void foo(List<? extends Number> listOfSomeNumberType) {} - - public void bar(List<?> listOfSomeType) {} - - public void goo(List<Double> listOfDoubles) {} - - } - ]]></programlisting> - +class C { + public void foo(List<? extends Number> listOfSomeNumberType) {} + + public void bar(List<?> listOfSomeType) {} + + public void goo(List<Double> listOfDoubles) {} +} +]]></programlisting> + <!-- see java5/generics/ajdk/SignatureWildcards.aj --> - + <variablelist> <varlistentry> @@ -491,57 +487,53 @@ <listitem> <para>matches only the execution of <literal>foo</literal>, and <emphasis>not</emphasis> the execution - of <literal>goo</literal> since <literal>List<? extends Number></literal> and + of <literal>goo</literal> since <literal>List<? extends Number></literal> and <literal>List<Double></literal> are distinct types. </para> </listitem> </varlistentry> - + <varlistentry> <term>execution(* C.*(List<?>))</term> <listitem> <para>matches only the execution of <literal>bar</literal>. </para> </listitem> - </varlistentry> - + </varlistentry> + <varlistentry> <term>execution(* C.*(List<? extends Object+>))</term> <listitem> - <para>matches both the execution of <literal>foo</literal> and the execution of <literal>bar</literal> + <para>matches both the execution of <literal>foo</literal> and the execution of <literal>bar</literal> since the upper bound of <literal>List<?></literal> is implicitly <literal>Object</literal>. </para> </listitem> - </varlistentry> - + </varlistentry> + </variablelist> - + </sect3> <sect3> <title>Treatment of bridge methods</title> - + <para>Under certain circumstances a Java 5 compiler is required to create <emphasis>bridge methods</emphasis> that support the compilation of programs using raw types. Consider the types</para> - + <programlisting><![CDATA[ - class Generic<T> { - - public T foo(T someObject) { - return someObject; - } - - } - - class SubGeneric<N extends Number> extends Generic<N> { - - public N foo(N someNumber) { - return someNumber; - } - - } - ]]></programlisting> - +class Generic<T> { + public T foo(T someObject) { + return someObject; + } +} + +class SubGeneric<N extends Number> extends Generic<N> { + public N foo(N someNumber) { + return someNumber; + } +} +]]></programlisting> + <para>The class <literal>SubGeneric</literal> extends <literal>Generic</literal> and overrides the method <literal>foo</literal>. Since the upper bound of the type variable <literal>N</literal> in <literal>SubGeneric</literal> is different to the upper bound of @@ -550,14 +542,14 @@ in <literal>Generic</literal>. This is an example of a case where a Java 5 compiler will create a <emphasis>bridge method</emphasis> in <literal>SubGeneric</literal>. Although you never see it, the bridge method will look something like this:</para> - + <programlisting><![CDATA[ - public Object foo(Object arg) { - Number n = (Number) arg; // "bridge" to the signature defined in this type - return foo(n); - } - ]]></programlisting> - +public Object foo(Object arg) { + Number n = (Number) arg; // "bridge" to the signature defined in this type +return foo(n); +} +]]></programlisting> + <!-- see java5/generics/ajdk/BridgeMethodExamples.aj --> <para>Bridge methods are synthetic artefacts generated as a result of a particular compilation strategy and have no execution join points in AspectJ 5. So the pointcut <literal>execution(Object SubGeneric.foo(Object))</literal> @@ -565,24 +557,24 @@ execution of <literal>foo</literal> in both <literal>Generic</literal> and <literal>SubGeneric</literal> since both are implementations of <literal>Generic.foo</literal>). </para> - + <para>It <emphasis>is</emphasis> possible to <emphasis>call</emphasis> a bridge method as the following short code snippet demonstrates. Such a call <emphasis>does</emphasis> result in a call join point for the call to - the method. + the method. </para> <programlisting><![CDATA[ - SubGeneric rawType = new SubGeneric(); - rawType.foo("hi"); // call to bridge method (will result in a runtime failure in this case) - Object n = new Integer(5); - rawType.foo(n); // call to bridge method that would succeed at runtime - ]]></programlisting> - +SubGeneric rawType = new SubGeneric(); +rawType.foo("hi"); // call to bridge method (will result in a runtime failure in this case) +Object n = new Integer(5); +rawType.foo(n); // call to bridge method that would succeed at runtime +]]></programlisting> + </sect3> <sect3> <title>Runtime type matching with this(), target() and args()</title> - + <para>The <literal>this()</literal>, <literal>target()</literal>, and <literal>args()</literal> pointcut expressions all match based on the runtime type of their arguments. Because Java 5 implements generics using erasure, it is not @@ -594,19 +586,17 @@ </para> <programlisting><![CDATA[ - public class C { - - public void foo(List<String> listOfStrings) {} - - public void bar(List<Double> listOfDoubles) {} - - public void goo(List<? extends Number> listOfSomeNumberType) {} - - } - ]]></programlisting> - +public class C { + public void foo(List<String> listOfStrings) {} + + public void bar(List<Double> listOfDoubles) {} + + public void goo(List<? extends Number> listOfSomeNumberType) {} +} +]]></programlisting> + <!-- see java5/generics/ajdk/ArgsExamples.aj --> - + <variablelist> <varlistentry> @@ -617,7 +607,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>args(List<String>)</term> <listitem> @@ -638,27 +628,25 @@ In this situation a runtime test would normally be applied to ascertain whether or not the argument was indeed an instance of the required type. However, in the case of parameterized types such a test is not possible and therefore AspectJ 5 considers this a match, but issues an <emphasis>unchecked</emphasis> warning. - For example, compiling the aspect <literal>A</literal> below with the class <literal>C</literal> produces the - compilation warning: "unchecked match of List<Double> with List<? extends Number> when argument is + For example, compiling the aspect <literal>A</literal> below with the class <literal>C</literal> produces the + compilation warning: "unchecked match of List<Double> with List<? extends Number> when argument is an instance of List at join point method-execution(void C.goo(List<? extends Number>)) [Xlint:uncheckedArgument]"; </para> </listitem> </varlistentry> - + </variablelist> - + <programlisting><![CDATA[ - public aspect A { - - before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { - for (Double d : listOfDoubles) { - // do something - } - } - - } - ]]></programlisting> - +public aspect A { + before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { + for (Double d : listOfDoubles) { + // do something + } + } +} +]]></programlisting> + <para>Like all Lint messages, the <literal>uncheckedArgument</literal> warning can be configured in severity from the default warning level to error or even ignore if preferred. In addition, AspectJ 5 offers the annotation <literal>@SuppressAjWarnings</literal> which is @@ -666,246 +654,231 @@ advice is annotated with <literal>@SuppressWarnings</literal> then <emphasis>all</emphasis> lint warnings issued during matching of pointcut associated with the advice will be suppressed. To suppress just an <literal>uncheckedArgument</literal> warning, use the - annotation <literal>@SuppressWarnings("uncheckedArgument")</literal> as in the following + annotation <literal>@SuppressWarnings("uncheckedArgument")</literal> as in the following examples: </para> <programlisting><![CDATA[ - import org.aspectj.lang.annotation.SuppressAjWarnings - public aspect A { - - @SuppressAjWarnings // will not see *any* lint warnings for this advice - before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { - for (Double d : listOfDoubles) { - // do something - } - } - - @SuppressAjWarnings("uncheckedArgument") // will not see *any* lint warnings for this advice - before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { - for (Double d : listOfDoubles) { - // do something - } - } - - } - ]]></programlisting> - +import org.aspectj.lang.annotation.SuppressAjWarnings +public aspect A { + @SuppressAjWarnings // will not see *any* lint warnings for this advice + before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { + for (Double d : listOfDoubles) { + // do something + } + } + + @SuppressAjWarnings("uncheckedArgument") // will not see *any* lint warnings for this advice + before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { + for (Double d : listOfDoubles) { + // do something + } + } +} +]]></programlisting> + <para> The safest way to deal with <literal>uncheckedArgument</literal> warnings however is to restrict the pointcut to match only at those join points where the argument is guaranteed to match. This is achieved by combining - <literal>args</literal> with a <literal>call</literal> or <literal>execution</literal> signature matching + <literal>args</literal> with a <literal>call</literal> or <literal>execution</literal> signature matching pointcut. In the following example the advice will match the execution of <literal>bar</literal> but not of <literal>goo</literal> since the signature of <literal>goo</literal> is not matched by the execution pointcut expression. </para> - + <programlisting><![CDATA[ - public aspect A { - - before(List<Double> listOfDoubles) : execution(* C.*(List<Double>)) && args(listOfDoubles) { - for (Double d : listOfDoubles) { - // do something - } - } - - } - ]]></programlisting> - +public aspect A { + before(List<Double> listOfDoubles) : execution(* C.*(List<Double>)) && args(listOfDoubles) { + for (Double d : listOfDoubles) { + // do something + } + } +} +]]></programlisting> + <para>Generic wildcards can be used in args type patterns, and matching follows regular Java 5 assignability rules. For - example, <literal>args(List<?>)</literal> will match a list argument of any type, and + example, <literal>args(List<?>)</literal> will match a list argument of any type, and <literal>args(List<? extends Number>)</literal> will match an argument of type - <literal>List<Number>, List<Double>, List<Float></literal> and so on. Where a match cannot be + <literal>List<Number>, List<Double>, List<Float></literal> and so on. Where a match cannot be fully statically determined, the compiler will once more issue an <literal>uncheckedArgument</literal> warning. </para> <para>Consider the following program:</para> - + <programlisting><![CDATA[ - public class C { - - public static void main(String[] args) { - C c = new C(); - List<String> ls = new ArrayList<String>(); - List<Double> ld = new ArrayList<Double>(); - c.foo("hi"); - c.foo(ls); - c.foo(ld); - } - - public void foo(Object anObject) {} - } - - aspect A { - before(List<? extends Number> aListOfSomeNumberType) - : call(* foo(..)) && args(aListOfSomeNumberType) { - // process list... - } - } - ]]></programlisting> - +public class C { + public static void main(String[] args) { + C c = new C(); + List<String> ls = new ArrayList<String>(); + List<Double> ld = new ArrayList<Double>(); + c.foo("hi"); + c.foo(ls); + c.foo(ld); + } + + public void foo(Object anObject) {} +} + +aspect A { + before(List<? extends Number> aListOfSomeNumberType) + : call(* foo(..)) && args(aListOfSomeNumberType) { + // process list... + } +} +]]></programlisting> + <!-- see java5/generics/ajdk/WildcardArgsExamples.aj --> - - <para>From the signature of <literal>foo</literal> all we know is that the runtime argument will be an instance of - <literal>Object</literal>.Compiling this program gives the unchecked argument warning: - "unchecked match of List<? extends Number> with List when argument is + + <para>From the signature of <literal>foo</literal> all we know is that the runtime argument will be an instance of + <literal>Object</literal>.Compiling this program gives the unchecked argument warning: + "unchecked match of List<? extends Number> with List when argument is an instance of List at join point method-execution(void C.foo(Object)) [Xlint:uncheckedArgument]". The advice will not execute at the call join point for <literal>c.foo("hi")</literal> since <literal>String</literal> is not an instance of <literal>List</literal>. The advice <emphasis>will</emphasis> execute at the call join points for <literal>c.foo(ls)</literal> and <literal>c.foo(ld)</literal> since in both cases the argument is an instance of <literal>List</literal>. </para> - + <para>Combine a wildcard argument type with a signature pattern to avoid unchecked argument matches. In the example below we use the signature pattern <literal>List<Number+></literal> to match a call to any method taking - a <literal>List<Number>, List<Double>, List<Float></literal> and so on. In addition the + a <literal>List<Number>, List<Double>, List<Float></literal> and so on. In addition the signature pattern <literal>List<? extends Number+></literal> can be used to match a call to a method declared to take a <literal>List<? extends Number></literal>, <literal>List<? extends Double></literal> and so on. Taken together, these restrict matching to only those join points at which the argument is guaranteed to be an instance of <literal>List<? extends Number></literal>.</para> - - + + <programlisting><![CDATA[ - aspect A { - before(List<? extends Number> aListOfSomeNumberType) - : (call(* foo(List<Number+>)) || call(* foo(List<? extends Number+>))) - && args(aListOfSomeNumberType) { - // process list... - } - } - ]]></programlisting> - +aspect A { + before(List<? extends Number> aListOfSomeNumberType) + : (call(* foo(List<Number+>)) || call(* foo(List<? extends Number+>))) + && args(aListOfSomeNumberType) { + // process list... + } +} +]]></programlisting> + </sect3> <sect3> <title>Binding return values in after returning advice</title> - + <para> After returning advice can be used to bind the return value from a matched join point. AspectJ 5 supports the use of a parameterized type in the returning clause, with matching following the same rules as described for args. For example, the following aspect matches the execution of any method returning a <literal>List</literal>, and makes - the returned list available to the body of the advice. + the returned list available to the body of the advice. </para> <programlisting><![CDATA[ - public aspect A { - - pointcut executionOfAnyMethodReturningAList() : execution(List *(..)); - - after() returning(List<?> listOfSomeType) : executionOfAnyMethodReturningAList() { - for (Object element : listOfSomeType) { - // process element... - } - } - - } - ]]></programlisting> - +public aspect A { + pointcut executionOfAnyMethodReturningAList() : execution(List *(..)); + + after() returning(List<?> listOfSomeType) : executionOfAnyMethodReturningAList() { + for (Object element : listOfSomeType) { + // process element... + } + } +} +]]></programlisting> + <!-- see java5/generics/ajdk/AfterReturningExamples.aj --> <para>The pointcut uses the raw type pattern <literal>List</literal>, and hence it - matches methods returning any kind of list (<literal>List<String>, List<Double></literal>, - and so on). We've chosen to bind the returned list as the parameterized type + matches methods returning any kind of list (<literal>List<String>, List<Double></literal>, + and so on). We've chosen to bind the returned list as the parameterized type <literal>List<?></literal> in the advice since Java's type checking will now ensure that we only perform safe operations on the list.</para> - + <para>Given the class</para> - + <programlisting><![CDATA[ - public class C { - - public List<String> foo(List<String> listOfStrings) {...} - - public List<Double> bar(List<Double> listOfDoubles) {...} - - public List<? extends Number> goo(List<? extends Number> listOfSomeNumberType) {...} - - } - ]]></programlisting> +public class C { + public List<String> foo(List<String> listOfStrings) {...} + + public List<Double> bar(List<Double> listOfDoubles) {...} + + public List<? extends Number> goo(List<? extends Number> listOfSomeNumberType) {...} +} +]]></programlisting> <para>The advice in the aspect below will run after the execution of <literal>bar</literal> and bind the return value. It will also run after the execution of <literal>goo</literal> and bind the return value, but gives an <literal>uncheckedArgument</literal> warning during compilation. It does <emphasis>not</emphasis> run after the execution of <literal>foo</literal>. - </para> + </para> <programlisting><![CDATA[ - public aspect Returning { - - after() returning(List<Double> listOfDoubles) : execution(* C.*(..)) { - for(Double d : listOfDoubles) { - // process double... - } - } - - } - ]]></programlisting> - +public aspect Returning { + after() returning(List<Double> listOfDoubles) : execution(* C.*(..)) { + for(Double d : listOfDoubles) { + // process double... + } + } +} +]]></programlisting> + <para>As with <literal>args</literal> you can guarantee that after returning advice only executes on lists <emphasis>statically determinable</emphasis> to be of the right - type by specifying a return type pattern in the associated pointcut. The + type by specifying a return type pattern in the associated pointcut. The <literal>@SuppressAjWarnings</literal> annotation can also be used if desired.</para> - + </sect3> <sect3> <title>Declaring pointcuts inside generic types</title> - + <para>Pointcuts can be declared in both classes and aspects. A pointcut declared in a generic type may use the type variables of the type in which it is declared. All references to - a pointcut declared in a generic type from outside of that type must be via a parameterized type reference, + a pointcut declared in a generic type from outside of that type must be via a parameterized type reference, and not a raw type reference.</para> <para>Consider the generic type <literal>Generic</literal> with a pointcut <literal>foo</literal>: </para> - + <programlisting><![CDATA[ - public class Generic<T> { - - /** - * matches the execution of any implementation of a method defined for T - */ - public pointcut foo() : execution(* T.*(..)); - - } - ]]></programlisting> - - <!-- see java5/generics/ajdk/PointcutInGenericClassExample.aj --> - +public class Generic<T> { + /** + * matches the execution of any implementation of a method defined for T + */ + public pointcut foo() : execution(* T.*(..)); +} +]]></programlisting> + + <!-- see java5/generics/ajdk/PointcutInGenericClassExample.aj --> + <para>Such a pointcut must be refered to using a parameterized reference as shown below.</para> - + <programlisting><![CDATA[ - public aspect A { - - // runs before the execution of any implementation of a method defined for MyClass - before() : Generic<MyClass>.foo() { - // ... - } - - // runs before the execution of any implementation of a method defined for YourClass - before() : Generic<YourClass>.foo() { - // ... - } - - // results in a compilation error - raw type reference - before() : Generic.foo() { } - - } - ]]></programlisting> - +public aspect A { + // runs before the execution of any implementation of a method defined for MyClass + before() : Generic<MyClass>.foo() { + // ... + } + + // runs before the execution of any implementation of a method defined for YourClass + before() : Generic<YourClass>.foo() { + // ... + } + + // results in a compilation error - raw type reference + before() : Generic.foo() { } +} +]]></programlisting> + </sect3> - + </sect2> - + <sect2 id="inter-type-declarations" xreflabel="inter-type-declarations"> <title>Inter-type Declarations</title> - + <para> AspectJ 5 supports the inter-type declaration of generic methods, and of members on generic types. For generic methods, the syntax is exactly as for a regular method declaration, with the addition of the target type specification: </para> - + <variablelist> <varlistentry> @@ -940,15 +913,15 @@ </varlistentry> </variablelist> - + <para> A generic type may be the target of an inter-type declaration, used either in its raw form or with type parameters specified. If type parameters are specified, then the number of type parameters given must match the number of type parameters in the generic type declaration. Type parameter <emphasis>names</emphasis> do not have to match. - For example, given the generic type <literal>Foo<T,S extends Number></literal> then: - </para> - + For example, given the generic type <literal>Foo<T,S extends Number></literal> then: + </para> + <variablelist> <varlistentry> @@ -965,9 +938,9 @@ <listitem> <para>Declares a method <literal>getMagnitude</literal> on the generic class <literal>Foo</literal>. The method returns an instance of the type substituted for the second type parameter in an invocation - of <literal>Foo</literal> If <literal>Foo</literal> is declared as + of <literal>Foo</literal> If <literal>Foo</literal> is declared as <literal>Foo<T,N extends Number> {...}</literal> then this inter-type declaration is - equivalent to the declaration of a method <literal>public N getMagnitude()</literal> + equivalent to the declaration of a method <literal>public N getMagnitude()</literal> within the body of <literal>Foo</literal>. </para> </listitem> @@ -984,19 +957,19 @@ </varlistentry> </variablelist> - + <para>A parameterized type may not be the target of an inter-type declaration. This is because there is only one type (the generic type) regardless of how many different invocations (parameterizations) of that generic type are made in a program. Therefore it does not make sense to try and declare a member on behalf of (say) <literal>Bar<String></literal>, you can only declare members on the generic - type <literal>Bar<T></literal>. + type <literal>Bar<T></literal>. </para> - + </sect2> - + <sect2 id="declare-parents-java5" xreflabel="declare-parents-java5"> <title>Declare Parents</title> - + <para>Both generic and parameterized types can be used as the parent type in a <literal>declare parents</literal> statement (as long as the resulting type hierarchy would be well-formed in accordance with Java's sub-typing rules). Generic types may also be used as the target type of a <literal>declare parents</literal> statement.</para> @@ -1008,8 +981,8 @@ <listitem> <para>The <literal>Foo</literal> type implements the <literal>List<String></literal> interface. If <literal>Foo</literal> already implements some other parameterization of the <literal>List</literal> - interface (for example, <literal>List<Integer></literal> then a compilation error will result since a - type cannot implement multiple parameterizations of the same generic interface type. + interface (for example, <literal>List<Integer></literal> then a compilation error will result since a + type cannot implement multiple parameterizations of the same generic interface type. </para> </listitem> </varlistentry> @@ -1017,7 +990,7 @@ </variablelist> </sect2> - + <sect2 id="declare-soft" xreflabel="declare-soft"> <title>Declare Soft</title> <para>It is an error to use a generic or parameterized type as the softened exception type in a declare soft statement. Java 5 does @@ -1026,21 +999,21 @@ <sect2 id="generic-aspects" xreflabel="generic-aspects"> <title>Generic Aspects</title> - + <para> AspectJ 5 allows an <emphasis>abstract</emphasis> aspect to be declared as a generic type. Any concrete aspect extending a generic abstract aspect must extend a parameterized version of the abstract aspect. - Wildcards are not permitted in this parameterization. + Wildcards are not permitted in this parameterization. </para> - + <para>Given the aspect declaration:</para> - + <programlisting><![CDATA[ - public abstract aspect ParentChildRelationship<P,C> { - ... - } - ]]></programlisting> - +public abstract aspect ParentChildRelationship<P,C> { + ... +} +]]></programlisting> + <para>then</para> <variablelist> @@ -1081,105 +1054,104 @@ </varlistentry> </variablelist> - + <para>The type parameter variables from a generic aspect declaration may be used in place of a type within any - member of the aspect, <emphasis>except for within inter-type declarations</emphasis>. + member of the aspect, <emphasis>except for within inter-type declarations</emphasis>. For example, we can declare a <literal>ParentChildRelationship</literal> aspect to manage the bi-directional relationship between parent and child nodes as follows: </para> <programlisting><![CDATA[ - /** - * a generic aspect, we've used descriptive role names for the type variables - * (Parent and Child) but you could use anything of course - */ - public abstract aspect ParentChildRelationship<Parent,Child> { - - /** generic interface implemented by parents */ - interface ParentHasChildren<C extends ChildHasParent>{ - List<C> getChildren(); - void addChild(C child); - void removeChild(C child); - } - - /** generic interface implemented by children */ - interface ChildHasParent<P extends ParentHasChildren>{ - P getParent(); - void setParent(P parent); - } - - /** ensure the parent type implements ParentHasChildren<child type> */ - declare parents: Parent implements ParentHasChildren<Child>; - - /** ensure the child type implements ChildHasParent<parent type> */ - declare parents: Child implements ChildHasParent<Parent>; - - // Inter-type declarations made on the *generic* interface types to provide - // default implementations. - - /** list of children maintained by parent */ - private List<C> ParentHasChildren<C>.children = new ArrayList<C>(); - - /** reference to parent maintained by child */ - private P ChildHasParent<P>.parent; - - /** Default implementation of getChildren for the generic type ParentHasChildren */ - public List<C> ParentHasChildren<C>.getChildren() { - return Collections.unmodifiableList(children); - } - - /** Default implementation of getParent for the generic type ChildHasParent */ - public P ChildHasParent<P>.getParent() { - return parent; - } - - /** - * Default implementation of addChild, ensures that parent of child is - * also updated. - */ - public void ParentHasChildren<C>.addChild(C child) { - if (child.parent != null) { - child.parent.removeChild(child); - } - children.add(child); - child.parent = this; - } - - /** - * Default implementation of removeChild, ensures that parent of - * child is also updated. - */ - public void ParentHasChildren<C>.removeChild(C child) { - if (children.remove(child)) { - child.parent = null; - } - } - - /** - * Default implementation of setParent for the generic type ChildHasParent. - * Ensures that this child is added to the children of the parent too. - */ - public void ChildHasParent<P>.setParent(P parent) { - parent.addChild(this); - } - - /** - * Matches at an addChild join point for the parent type P and child type C - */ - public pointcut addingChild(Parent p, Child c) : - execution(* ParentHasChildren.addChild(ChildHasParent)) && this(p) && args(c); - - /** - * Matches at a removeChild join point for the parent type P and child type C - */ - public pointcut removingChild(Parent p, Child c) : - execution(* ParentHasChildren.removeChild(ChildHasParent)) && this(p) && args(c); - - } - - ]]></programlisting> - - +/** + * a generic aspect, we've used descriptive role names for the type variables + * (Parent and Child) but you could use anything of course + */ +public abstract aspect ParentChildRelationship<Parent,Child> { + + /** generic interface implemented by parents */ + interface ParentHasChildren<C extends ChildHasParent>{ + List<C> getChildren(); + void addChild(C child); + void removeChild(C child); + } + + /** generic interface implemented by children */ + interface ChildHasParent<P extends ParentHasChildren>{ + P getParent(); + void setParent(P parent); + } + + /** ensure the parent type implements ParentHasChildren<child type> */ + declare parents: Parent implements ParentHasChildren<Child>; + + /** ensure the child type implements ChildHasParent<parent type> */ + declare parents: Child implements ChildHasParent<Parent>; + + // Inter-type declarations made on the *generic* interface types to provide + // default implementations. + + /** list of children maintained by parent */ + private List<C> ParentHasChildren<C>.children = new ArrayList<C>(); + + /** reference to parent maintained by child */ + private P ChildHasParent<P>.parent; + + /** Default implementation of getChildren for the generic type ParentHasChildren */ + public List<C> ParentHasChildren<C>.getChildren() { + return Collections.unmodifiableList(children); + } + + /** Default implementation of getParent for the generic type ChildHasParent */ + public P ChildHasParent<P>.getParent() { + return parent; + } + + /** + * Default implementation of addChild, ensures that parent of child is + * also updated. + */ + public void ParentHasChildren<C>.addChild(C child) { + if (child.parent != null) { + child.parent.removeChild(child); + } + children.add(child); + child.parent = this; + } + + /** + * Default implementation of removeChild, ensures that parent of + * child is also updated. + */ + public void ParentHasChildren<C>.removeChild(C child) { + if (children.remove(child)) { + child.parent = null; + } + } + + /** + * Default implementation of setParent for the generic type ChildHasParent. + * Ensures that this child is added to the children of the parent too. + */ + public void ChildHasParent<P>.setParent(P parent) { + parent.addChild(this); + } + + /** + * Matches at an addChild join point for the parent type P and child type C + */ + public pointcut addingChild(Parent p, Child c) : + execution(* ParentHasChildren.addChild(ChildHasParent)) && this(p) && args(c); + + /** + * Matches at a removeChild join point for the parent type P and child type C + */ + public pointcut removingChild(Parent p, Child c) : + execution(* ParentHasChildren.removeChild(ChildHasParent)) && this(p) && args(c); + +} +]]></programlisting> + + <para> The example aspect captures the protocol for managing a bi-directional parent-child relationship between any two types playing the role of parent and child. In a compiler implementation managing an abstract syntax @@ -1187,15 +1159,13 @@ </para> <programlisting><![CDATA[ - public aspect ASTNodeContainment extends ParentChildRelationship<ASTNode,ASTNode> { - - before(ASTNode parent, ASTNode child) : addingChild(parent, child) { - ... - } - - } - ]]></programlisting> - +public aspect ASTNodeContainment extends ParentChildRelationship<ASTNode,ASTNode> { + before(ASTNode parent, ASTNode child) : addingChild(parent, child) { + ... + } +} +]]></programlisting> + <para> As a result of this declaration, <literal>ASTNode</literal> gains members: </para> @@ -1208,17 +1178,16 @@ <member><literal>void addChild(ASTNode child)</literal></member> <member><literal>void removeChild(ASTNode child)</literal></member> <member><literal>void setParent(ASTNode parent)</literal></member> - </simplelist> - + </simplelist> + <para> In a system managing orders, we could declare the concrete aspect: </para> <programlisting><![CDATA[ - public aspect OrderItemsInOrders extends ParentChildRelationship<Order,OrderItem> { - - } - ]]></programlisting> +public aspect OrderItemsInOrders extends ParentChildRelationship<Order, OrderItem> { +} +]]></programlisting> <para> As a result of this declaration, <literal>Order</literal> gains members: @@ -1229,73 +1198,73 @@ <member><literal>List<OrderItem> getChildren()</literal></member> <member><literal>void addChild(OrderItem child)</literal></member> <member><literal>void removeChild(OrderItem child)</literal></member> - </simplelist> + </simplelist> <para>and <literal>OrderItem</literal> gains members:</para> - + <simplelist> <member><literal>Order parent</literal></member> <member><literal>Order getParent()</literal></member> <member><literal>void setParent(Order parent)</literal></member> - </simplelist> - - + </simplelist> + + <para>A second example of an abstract aspect, this time for handling exceptions in a uniform manner, is shown below:</para> - + <programlisting><![CDATA[ - abstract aspect ExceptionHandling<T extends Throwable> { - - /** - * method to be implemented by sub-aspects to handle thrown exceptions - */ - protected abstract void onException(T anException); - - /** - * to be defined by sub-aspects to specify the scope of exception handling - */ - protected abstract pointcut inExceptionHandlingScope(); - - /** - * soften T within the scope of the aspect - */ - declare soft: T : inExceptionHandlingScope(); - - /** - * bind an exception thrown in scope and pass it to the handler - */ - after() throwing (T anException) : inExceptionHandlingScope() { - onException(anException); - } - - } - ]]></programlisting> +abstract aspect ExceptionHandling<T extends Throwable> { + + /** + * method to be implemented by sub-aspects to handle thrown exceptions + */ + protected abstract void onException(T anException); + + /** + * to be defined by sub-aspects to specify the scope of exception handling + */ + protected abstract pointcut inExceptionHandlingScope(); + + /** + * soften T within the scope of the aspect + */ + declare soft: T : inExceptionHandlingScope(); + + /** + * bind an exception thrown in scope and pass it to the handler + */ + after() throwing (T anException) : inExceptionHandlingScope() { + onException(anException); + } + +} +]]></programlisting> <para>Notice how the type variable <literal>T extends Throwable</literal> allows the components of the aspect to be designed to work together in a type-safe manner. The - following concrete sub-aspect shows how the abstract aspect might be extended to + following concrete sub-aspect shows how the abstract aspect might be extended to handle <literal>IOExceptions</literal>.</para> <programlisting><![CDATA[ - public aspect IOExceptionHandling extends ExceptionHandling<IOException>{ - - protected pointcut inExceptionHandlingScope() : - call(* doIO*(..)) && within(org.xyz..*); - - /** - * called whenever an IOException is thrown in scope. - */ - protected void onException(IOException ex) { - System.err.println("handled exception: " + ex.getMessage()); - throw new MyDomainException(ex); - } - } - ]]></programlisting> +public aspect IOExceptionHandling extends ExceptionHandling<IOException>{ + + protected pointcut inExceptionHandlingScope() : + call(* doIO*(..)) && within(org.xyz..*); + + /** + * called whenever an IOException is thrown in scope. + */ + protected void onException(IOException ex) { + System.err.println("handled exception: " + ex.getMessage()); + throw new MyDomainException(ex); + } +} +]]></programlisting> </sect2> - + </sect1> - + </chapter> diff --git a/docs/adk15ProgGuideDB/grammar.xml b/docs/adk15ProgGuideDB/grammar.xml index 1de50b7bf..048118c34 100644 --- a/docs/adk15ProgGuideDB/grammar.xml +++ b/docs/adk15ProgGuideDB/grammar.xml @@ -1,192 +1,190 @@ <appendix id="grammar" xreflabel="AspectJ 5 Grammar"> <title>A Grammar for the AspectJ 5 Language</title> - + <programlisting><![CDATA[ - === type patterns === - - TypePattern := SimpleTypePattern | - '!' TypePattern | - '(' AnnotationPattern? TypePattern ')' - TypePattern '&&' TypePattern | - TypePattern '||' TypePattern - - SimpleTypePattern := DottedNamePattern '+'? '[]'* - - DottedNamePattern := FullyQualifiedName RestOfNamePattern? | - '*' NotStarNamePattern? - - RestOfNamePattern := '..' DottedNamePattern | - '*' NotStarNamePattern? - - NotStarNamePattern := FullyQualifiedName RestOfNamePattern? | - '..' DottedNamePattern - - FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* - - === annotation patterns === - - AnnotationPattern := '!'? '@' AnnotationTypePattern AnnotationPattern* - - - AnnotationTypePattern := FullyQualifiedName | - '(' TypePattern ')' - - === signature patterns === - - -- field -- - - FieldPattern := - AnnotationPattern? FieldModifiersPattern? - TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern - - FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern* - - FieldModifier := 'public' | 'private' | 'protected' | 'static' | - 'transient' | 'final' - - DotOrDotDot := '.' | '..' - - SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)? - - -- method -- - - MethodPattern := - AnnotationPattern? MethodModifiersPattern? TypePattern - (TypePattern DotOrDotDot)? SimpleNamePattern - '(' FormalsPattern ')' ThrowsPattern? - - MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern* - - MethodModifier := 'public' | 'private' | 'protected' | 'static' | - 'synchronized' | 'final' - - FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | - OptionalParensTypePattern (',' FormalsPattern)* | - TypePattern '...' - - FormalsPatternAfterDotDot := - OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | - TypePattern '...' - - ThrowsPattern := 'throws' TypePatternList - - TypePatternList := TypePattern (',' TypePattern)* - - -- constructor -- - - ConstructorPattern := - AnnotationPattern? ConstructorModifiersPattern? - (TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')' - ThrowsPattern? - - ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern* - - ConstructorModifier := 'public' | 'private' | 'protected' - - === Pointcuts === - - PointcutPrimitive := - Call | Execution | Get | Set | Handler | - Initialization | PreInitialization | - StaticInitialization | AdviceExecution | - This | Target | Args | CFlow | CFlowBelow | - Within | WithinCode | If | - AnnotationPointcut - - AnnotationPointcut := AtAnnotation | AtThis | AtTarget | - AtWithin | AtWithinCode | AtArgs - - - Call := 'call' '(' MethodOrConstructorPattern ')' - - MethodOrConstructorPattern := MethodPattern | ConstructorPattern - - Execution := 'execution' '(' MethodOrConstructorPattern ')' - - Get := 'get' '(' FieldPattern ')' - Set := 'set' '(' FieldPattern ')' - Handler := 'handler' '(' OptionalParensTypePattern ')' - Initialization := 'initialization' '(' ConstructorPattern ')' - PreInitialization := 'preinitialization' '(' ConstructorPattern ')' - StaticInitialization := 'staticinitialization' '(' OptionalParensTypePattern ')' - AdviceExecution := 'adviceexecution' '(' ')' - This := 'this' '(' TypeOrIdentifier ')' - Target := 'target' '(' TypeOrIdentifier ')' - Args := 'args' '(' FormalsOrIdentifiersPattern ')' - CFlow := 'cflow' '(' Pointcut ')' - CFlowBelow := 'cflowbelow' '(' Pointcut ')' - Within := 'within' '(' OptionalParensTypePattern ')' - WithinCode := 'withincode' '(' OptionalParensTypePattern ')' - If := 'if' '(' BooleanJavaExpression ')' - - TypeOrIdentifier := FullyQualifiedName ('[' ']')* | Identifier - Identifier := JavaIdentifierChar+ - - FormalsOrIdentifiersPattern := - '..' (',' FormalsOrIdentifiersPatternAfterDotDot)? | - TypeOrIdentifier (',' FormalsOrIdentifiersPattern)* | - '*' (',' FormalsOrIdentifiersPattern)* - - FormalsOrIdentifiersPatternAfterDotDot := - TypeOrIdentifier (',' FormalsOrIdentifiersPatternAfterDotDot)* | - '*' (',' FormalsOrIdentifiersPatternAfterDotDot)* - - AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')' - AtThis := '@this' '(' AnnotationOrIdentifer ')' - AtTarget := '@target' '(' AnnotationOrIdentifier ')' - AtWithin := '@within' '(' AnnotationOrIdentifier ')' - AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')' - - AnnotationOrIdentifier := FullyQualifiedName | Identifier - - AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' - - AnnotationsOrIdentifiersPattern := - '..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? | - AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* | - '*' (',' AnnotationsOrIdentifiersPattern)* - - AnnotationsOrIdentifiersPatternAfterDotDot := - AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | - '*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)* - - PointcutDeclaration := PointcutModifiers? 'pointcut' Identifier Formals - ':' PointcutExpression - - PointcutModifiers := PointcutModifier* - - PointcutModifier := 'public' | 'private' | 'protected' | 'abstract' - - Formals := '(' ParamList? ')' - ParamList := FullyQualifiedName Identifier (',' ParamList)* - - ReferencePointcut := (FullyQualifiedName '.')? Identifier Formals - - PointcutExpression := (PointcutPrimitive | ReferencePointcut) | - '!' PointcutExpression | - '(' PointcutExpression ')' | - PointcutExpression '&&' PointcutExpression | - PointcutExpression '||' PointcutExpression - - === Advice === - - to be written... - - === Inter-type Declarations === - - to be written... - - === Declare Statements === - - to be written... - - === Aspects === - - to be written... - - ]]></programlisting> +=== type patterns === + +TypePattern := SimpleTypePattern | + '!' TypePattern | + '(' AnnotationPattern? TypePattern ')' + TypePattern '&&' TypePattern | + TypePattern '||' TypePattern + +SimpleTypePattern := DottedNamePattern '+'? '[]'* + +DottedNamePattern := FullyQualifiedName RestOfNamePattern? | + '*' NotStarNamePattern? + +RestOfNamePattern := '..' DottedNamePattern | + '*' NotStarNamePattern? + +NotStarNamePattern := FullyQualifiedName RestOfNamePattern? | + '..' DottedNamePattern + +FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* + +=== annotation patterns === + +AnnotationPattern := '!'? '@' AnnotationTypePattern AnnotationPattern* + + +AnnotationTypePattern := FullyQualifiedName | + '(' TypePattern ')' + +=== signature patterns === + +-- field -- + +FieldPattern := + AnnotationPattern? FieldModifiersPattern? + TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern + +FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern* + +FieldModifier := 'public' | 'private' | 'protected' | 'static' | + 'transient' | 'final' + +DotOrDotDot := '.' | '..' + +SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)? + +-- method -- + +MethodPattern := + AnnotationPattern? MethodModifiersPattern? TypePattern + (TypePattern DotOrDotDot)? SimpleNamePattern + '(' FormalsPattern ')' ThrowsPattern? + +MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern* + +MethodModifier := 'public' | 'private' | 'protected' | 'static' | + 'synchronized' | 'final' + +FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | + OptionalParensTypePattern (',' FormalsPattern)* | + TypePattern '...' + +FormalsPatternAfterDotDot := + OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | + TypePattern '...' + +ThrowsPattern := 'throws' TypePatternList + +TypePatternList := TypePattern (',' TypePattern)* + +-- constructor -- + +ConstructorPattern := + AnnotationPattern? ConstructorModifiersPattern? + (TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')' + ThrowsPattern? + +ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern* + +ConstructorModifier := 'public' | 'private' | 'protected' + +=== Pointcuts === + +PointcutPrimitive := + Call | Execution | Get | Set | Handler | + Initialization | PreInitialization | + StaticInitialization | AdviceExecution | + This | Target | Args | CFlow | CFlowBelow | + Within | WithinCode | If | + AnnotationPointcut + +AnnotationPointcut := AtAnnotation | AtThis | AtTarget | + AtWithin | AtWithinCode | AtArgs + + +Call := 'call' '(' MethodOrConstructorPattern ')' + +MethodOrConstructorPattern := MethodPattern | ConstructorPattern + +Execution := 'execution' '(' MethodOrConstructorPattern ')' + +Get := 'get' '(' FieldPattern ')' +Set := 'set' '(' FieldPattern ')' +Handler := 'handler' '(' OptionalParensTypePattern ')' +Initialization := 'initialization' '(' ConstructorPattern ')' +PreInitialization := 'preinitialization' '(' ConstructorPattern ')' +StaticInitialization := 'staticinitialization' '(' OptionalParensTypePattern ')' +AdviceExecution := 'adviceexecution' '(' ')' +This := 'this' '(' TypeOrIdentifier ')' +Target := 'target' '(' TypeOrIdentifier ')' +Args := 'args' '(' FormalsOrIdentifiersPattern ')' +CFlow := 'cflow' '(' Pointcut ')' +CFlowBelow := 'cflowbelow' '(' Pointcut ')' +Within := 'within' '(' OptionalParensTypePattern ')' +WithinCode := 'withincode' '(' OptionalParensTypePattern ')' +If := 'if' '(' BooleanJavaExpression ')' + +TypeOrIdentifier := FullyQualifiedName ('[' ']')* | Identifier +Identifier := JavaIdentifierChar+ + +FormalsOrIdentifiersPattern := + '..' (',' FormalsOrIdentifiersPatternAfterDotDot)? | + TypeOrIdentifier (',' FormalsOrIdentifiersPattern)* | + '*' (',' FormalsOrIdentifiersPattern)* + +FormalsOrIdentifiersPatternAfterDotDot := + TypeOrIdentifier (',' FormalsOrIdentifiersPatternAfterDotDot)* | + '*' (',' FormalsOrIdentifiersPatternAfterDotDot)* + +AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')' +AtThis := '@this' '(' AnnotationOrIdentifer ')' +AtTarget := '@target' '(' AnnotationOrIdentifier ')' +AtWithin := '@within' '(' AnnotationOrIdentifier ')' +AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')' + +AnnotationOrIdentifier := FullyQualifiedName | Identifier + +AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' + +AnnotationsOrIdentifiersPattern := + '..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? | + AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* | + '*' (',' AnnotationsOrIdentifiersPattern)* + +AnnotationsOrIdentifiersPatternAfterDotDot := + AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | + '*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)* + +PointcutDeclaration := PointcutModifiers? 'pointcut' Identifier Formals + ':' PointcutExpression + +PointcutModifiers := PointcutModifier* + +PointcutModifier := 'public' | 'private' | 'protected' | 'abstract' + +Formals := '(' ParamList? ')' +ParamList := FullyQualifiedName Identifier (',' ParamList)* + +ReferencePointcut := (FullyQualifiedName '.')? Identifier Formals + +PointcutExpression := (PointcutPrimitive | ReferencePointcut) | + '!' PointcutExpression | + '(' PointcutExpression ')' | + PointcutExpression '&&' PointcutExpression | + PointcutExpression '||' PointcutExpression + +=== Advice === + +to be written... + +=== Inter-type Declarations === + +to be written... + +=== Declare Statements === + +to be written... + +=== Aspects === +to be written... +]]></programlisting> </appendix> diff --git a/docs/adk15ProgGuideDB/joinpointsignatures.xml b/docs/adk15ProgGuideDB/joinpointsignatures.xml index 013b9003b..e803b9cfd 100644 --- a/docs/adk15ProgGuideDB/joinpointsignatures.xml +++ b/docs/adk15ProgGuideDB/joinpointsignatures.xml @@ -9,76 +9,76 @@ for understanding the matching rules in the presence of annotations, generics, covariance, varargs, and autoboxing. </para> - + <sect1 id="join-point-matching"> <title>Join Point Matching</title> - + <para>AspectJ supports 11 different kinds of join points. These are the <literal>method call, method execution, constructor call, constructor execution, field get, field set, pre-initialization, initialization, static initialization, handler,</literal> and <literal>advice execution</literal> join points.</para> - + <para>The <emphasis>kinded</emphasis> pointcut designators match based on the kind of a join point. These are the <literal>call, - execution, get, set, preinitialization, initialization, + execution, get, set, preinitialization, initialization, staticinitialization, handler,</literal> and <literal>adviceexecution</literal> designators.</para> - - <para>A kinded pointcut is written using patterns, some of which + + <para>A kinded pointcut is written using patterns, some of which match based on <emphasis>signature</emphasis>, and some of which - match based on <emphasis>modifiers</emphasis>. For example, in + match based on <emphasis>modifiers</emphasis>. For example, in the <literal>call</literal> pointcut designator:</para> - + <programlisting><![CDATA[ - call(ModifierPattern TypePattern TypePattern.IdPattern(TypePatternList) ThrowsPattern) - ]]></programlisting> - +call(ModifierPattern TypePattern TypePattern.IdPattern(TypePatternList) ThrowsPattern) +]]></programlisting> + <para>the modifiers matching patterns are <literal>ModifierPattern</literal> and <literal>ThrowsPattern</literal>, and the signature matching patterns are <literal>TypePattern TypePattern.IdPattern(TypePatternList)</literal>. </para> - + <para> A join point has potentially multiple signatures, but only one set of - modifiers. <emphasis>A kinded primitive pointcut matches a particular join point + modifiers. <emphasis>A kinded primitive pointcut matches a particular join point if and only if</emphasis>: </para> - + <orderedlist> <listitem>They are of the same kind</listitem> - <listitem>The signature pattern (exactly) matches at least one + <listitem>The signature pattern (exactly) matches at least one signature of the join point</listitem> <listitem>The modifiers pattern matches the modifiers of the subject of the join point</listitem> </orderedlist> - - <para>These rules make it very easily to quickly determine whether a + + <para>These rules make it very easily to quickly determine whether a given pointcut matches a given join point. In the next two sections, we describe what the signature(s) of a join point are, and what the subjects of join points are.</para> - + </sect1> - + <sect1 id="join-point-signatures"> <title>Join Point Signatures</title> - + <para>Call, execution, get, and set join points may potentially have multiple signatures. All other join points have exactly one signature. The following table summarizes the constituent parts of a join point signature for the different kinds of join point.</para> - + <informaltable> <tgroup cols="7"> <thead> <row> <entry>Join Point Kind</entry> - <entry>Return Type</entry> - <entry>Declaring Type</entry> - <entry>Id</entry> - <entry>Parameter Types</entry> - <entry>Field Type</entry> - <entry>Exception Type</entry> + <entry>Return Type</entry> + <entry>Declaring Type</entry> + <entry>Id</entry> + <entry>Parameter Types</entry> + <entry>Field Type</entry> + <entry>Exception Type</entry> </row> </thead> <tbody> @@ -184,25 +184,25 @@ </tbody> </tgroup> </informaltable> - + <para>Note that whilst an advice execution join point has a signature comprising the declaring type of the advice and the advice parameter types, the <literal>adviceexecution</literal> pointcut designator does not support matching based on this signature.</para> - + <para>The signatures for most of the join point kinds should be self-explanatory, except for field get and set, and method call and execution - join points, which can have multiple signatures. Each signature of + join points, which can have multiple signatures. Each signature of a method call or execution join point has the same id and parameter types, but the declaring type and return type (with covariance) may vary. Each signature of a field get or set join point has the same id and field type, but the declaring type may vary. </para> - - <para>The following sections examine signatures for these join points + + <para>The following sections examine signatures for these join points in more detail.</para> - + <sect2 id="method-call-join-point-signatures" xreflabel="method-call-join-point-signatures"> <title>Method call join point signatures</title> @@ -213,72 +213,71 @@ </para> <programlisting><![CDATA[ - T t = new T(); - t.m("hello"); <= call join point occurs when this line is executed - ]]></programlisting> - +T t = new T(); +t.m("hello"); <= call join point occurs when this line is executed +]]></programlisting> + <para> Then the signature <literal>R(T) T.m(parameter_types)</literal> is a signature of the call join point, where <literal>R(T)</literal> is the return - type of <literal>m</literal> in <literal>T</literal>, and + type of <literal>m</literal> in <literal>T</literal>, and <literal>parameter_types</literal> are the parameter types of <literal>m</literal>. If <literal>T</literal> itself does not - declare a definition of <literal>m(parameter_types)</literal>, then - <literal>R(T)</literal> is the return type in the definition of + declare a definition of <literal>m(parameter_types)</literal>, then + <literal>R(T)</literal> is the return type in the definition of <literal>m</literal> that <literal>T</literal> inherits. Given the - call above, and the definition of <literal>T.m</literal>: + call above, and the definition of <literal>T.m</literal>: </para> - + <programlisting><![CDATA[ - interface Q { - R m(String s); - } - - class P implements Q { - R m(String s) {...} - } - - class S extends P { - R' m(String s) {...} - } - - class T extends S {} - - ]]></programlisting> - +interface Q { + R m(String s); +} + +class P implements Q { + R m(String s) {...} +} + +class S extends P { + R' m(String s) {...} +} + +class T extends S {} +]]></programlisting> + <para>Then <literal>R' T.m(String)</literal> is a signature of the call join point for <literal>t.m("hello")</literal>.</para> - + <para> - For each ancestor (super-type) <literal>A</literal> of <literal>T</literal>, + For each ancestor (super-type) <literal>A</literal> of <literal>T</literal>, if <literal>m(parameter_types)</literal> is defined for that super-type, then <literal>R(A) A.m(parameter_types)</literal> is a signature of the call join point, where <literal>R(A)</literal> is the return type of <literal> m(parameter_types)</literal> as defined in <literal>A</literal>, or as inherited by <literal>A</literal> if <literal>A</literal> itself does not - provide a definition of <literal>m(parameter_types)</literal>. + provide a definition of <literal>m(parameter_types)</literal>. </para> - + <para> Continuing the example from above,we can deduce that </para> <programlisting><![CDATA[ - R' S.m(String) - R P.m(String) - R Q.m(String) - ]]></programlisting> - +R' S.m(String) +R P.m(String) +R Q.m(String) +]]></programlisting> + <para>are all additional signatures for the call join point arising from the call <literal>t.m("hello")</literal>. Thus this call join point has four signatures in total. Every signature has the same id and parameter types, and a different declaring type.</para> - + </sect2> - + <sect2 id="method-execution-join-point-signatures" xreflabel="method-execution-join-point-signatures"> <title>Method execution join point signatures</title> - + <para>Join point signatures for execution join points are defined in a similar manner to signatures for call join points. Given the hierarchy: @@ -286,39 +285,38 @@ <programlisting><![CDATA[ - interface Q { - R m(String s); - } - - class P implements Q { - R m(String s) {...} - } - - class S extends P { - R' m(String s) {...} - } - - class T extends S { } - - class U extends T { - R' m(String s) {...} - } - - ]]></programlisting> - +interface Q { + R m(String s); +} + +class P implements Q { + R m(String s) {...} +} + +class S extends P { + R' m(String s) {...} +} + +class T extends S { } + +class U extends T { + R' m(String s) {...} +} +]]></programlisting> + <para>Then the execution join point signatures arising as a result of the call to <literal>u.m("hello")</literal> are: </para> <programlisting><![CDATA[ - R' U.m(String) - R' S.m(String) - R P.m(String) - R Q.m(String) - ]]></programlisting> +R' U.m(String) +R' S.m(String) +R P.m(String) +R Q.m(String) +]]></programlisting> - <para>Each signature has the same id and parameter types, and a + <para>Each signature has the same id and parameter types, and a different declaring type. There is one signature for each type - that provides its own declaration of the method. Hence in this + that provides its own declaration of the method. Hence in this example there is no signature <literal>R' T.m(String)</literal> as <literal>T</literal> does not provide its own declaration of the method.</para> @@ -330,11 +328,11 @@ <para> For a field get join point where an access is made to a field - <literal>f</literal> of type <literal>F</literal> + <literal>f</literal> of type <literal>F</literal> on a object with declared type <literal>T</literal>, then - <literal>F T.f</literal> is a signature of the get join point. + <literal>F T.f</literal> is a signature of the get join point. </para> - + <para> If <literal>T</literal> does not directly declare a member <literal>f</literal>, then for each super type <literal>S</literal> @@ -344,18 +342,18 @@ of the join point. For example, given the hierarchy: </para> - <programlisting><![CDATA[ - class P { - F f; - } - - class S extends P { - F f; - } - - class T extends S { } - ]]></programlisting> - + <programlisting><![CDATA[ +class P { + F f; +} + +class S extends P { + F f; +} + +class T extends S { } +]]></programlisting> + <para> Then the join point signatures for a field get join point of the field <literal>f</literal> on an object with declared type @@ -363,26 +361,26 @@ </para> <programlisting><![CDATA[ - F S.f - F T.f - ]]></programlisting> +F S.f +F T.f +]]></programlisting> <para>The signatures for a field set join point are derived in an identical manner.</para> - + </sect2> - + </sect1> - + <sect1 id="join-point-modifiers"> <title>Join Point Modifiers</title> - + <para>Every join point has a single set of modifiers - these include the standard Java modifiers such as <literal>public, private, static, abstract</literal> etc., any annotations, and the throws clauses of methods and constructors. These modifiers are the modifiers of the <emphasis>subject</emphasis> of the join point.</para> - + <para> The following table defines the join point subject for each kind of join point. @@ -447,40 +445,40 @@ </row> </tbody> </tgroup> - </informaltable> + </informaltable> <para>For example, given the following types</para> <programlisting><![CDATA[ - public class X { - @Foo - protected void doIt() {...} - } - - public class Y extends X { - public void doIt() {...} - } - ]]></programlisting> - +public class X { + @Foo + protected void doIt() {...} +} + +public class Y extends X { + public void doIt() {...} +} +]]></programlisting> + <para>Then the modifiers for a call to <literal>(Y y) y.doIt()</literal> are simply <literal>{public}</literal>. The modifiers for a call to <literal>(X x) x.doIt()</literal> are <literal>{@Foo,protected}</literal>. </para> - + </sect1> - + <sect1 id="join-point-matching-summary"> <title>Summary of Join Point Matching</title> <para> A join point has potentially multiple signatures, but only one set of - modifiers. <emphasis>A kinded primitive pointcut matches a particular join point + modifiers. <emphasis>A kinded primitive pointcut matches a particular join point if and only if</emphasis>: </para> - + <orderedlist> <listitem>They are of the same kind</listitem> - <listitem>The signature pattern (exactly) matches at least one + <listitem>The signature pattern (exactly) matches at least one signature of the join point</listitem> <listitem>The modifiers pattern matches the modifiers of the subject of the join point</listitem> @@ -489,39 +487,38 @@ <para>Given the hierarchy</para> <programlisting><![CDATA[ - interface Q { - R m(String s); - } - - class P implements Q { - @Foo - public R m(String s) {...} - } - - class S extends P { - @Bar - public R' m(String s) {...} - } - - class T extends S {} - - ]]></programlisting> +interface Q { + R m(String s); +} + +class P implements Q { + @Foo + public R m(String s) {...} +} + +class S extends P { + @Bar + public R' m(String s) {...} +} + +class T extends S {} +]]></programlisting> <para>and the program fragment:</para> - + <programlisting><![CDATA[ - P p = new P(); - S s = new S(); - T t = new T(); - ... - p.m("hello"); - s.m("hello"); - t.m("hello"); - ]]></programlisting> - +P p = new P(); +S s = new S(); +T t = new T(); +... +p.m("hello"); +s.m("hello"); +t.m("hello"); +]]></programlisting> + <para> The the pointcut <literal>call(@Foo R P.m(String))</literal> matches the - call <literal>p.m("hello")</literal> since both the signature and the + call <literal>p.m("hello")</literal> since both the signature and the modifiers match. It does not match the call <literal>s.m("hello")</literal> because even though the signature pattern matches one of the signatures of the join point, the modifiers pattern does not match the modifiers of @@ -534,6 +531,6 @@ signature pattern does not match any signature for the call join point of m in P.</para> </sect1> - + </chapter> diff --git a/docs/adk15ProgGuideDB/miscellaneous.xml b/docs/adk15ProgGuideDB/miscellaneous.xml index d7aceb851..df9aa3f87 100644 --- a/docs/adk15ProgGuideDB/miscellaneous.xml +++ b/docs/adk15ProgGuideDB/miscellaneous.xml @@ -1,10 +1,10 @@ <chapter id="miscellaneous" xreflabel="Miscellaneous Changes"> <title>Other Changes in AspectJ 5</title> - + <sect1 id="pointcuts-change"> <title>Pointcuts</title> - + <para> AspectJ 5 is more liberal than AspectJ 1.2.1 in accepting pointcut expressions that bind context variables in more than one location. For example, AspectJ @@ -12,10 +12,10 @@ </para> <programlisting><![CDATA[ - pointcut foo(Foo foo) : (execution(* *(..)) && this(foo) ) || - (set(* *) && target(foo)); - ]]></programlisting> - +pointcut foo(Foo foo) : (execution(* *(..)) && this(foo) ) || + (set(* *) && target(foo)); +]]></programlisting> + <para> whereas this expression is permitted in AspectJ 5. Each context variable must be bound exactly once in each branch of a disjunction, and the disjunctive branches @@ -23,63 +23,59 @@ can be both an execution join point and a set join point so the two branches are mutually exclusive. </para> - + </sect1> - + <sect1 id="declare-soft-change"> <title>Declare Soft</title> <para> - The semantics of the <literal>declare soft</literal> statement have been - refined in AspectJ 5 to only soften exceptions that are not already runtime + The semantics of the <literal>declare soft</literal> statement have been + refined in AspectJ 5 to only soften exceptions that are not already runtime exceptions. If the exception type specified in a declare soft statement is <literal>RuntimeException</literal> or a subtype of <literal>RuntimeException</literal> then a new XLint warning will be issued:</para> - + <programlisting><![CDATA[ - declare soft : SomeRuntimeException : execution(* *(..)); - - >> "SomeRuntimeException will not be softened as it is already a RuntimeException" [XLint:runtimeExceptionNotSoftened] - ]]></programlisting> - +declare soft : SomeRuntimeException : execution(* *(..)); + +>> "SomeRuntimeException will not be softened as it is already a RuntimeException" [XLint:runtimeExceptionNotSoftened] +]]></programlisting> + <para> This XLint message can be controlled by setting the <literal>runtimeExceptionNotSoftened</literal> XLint parameter. </para> - + <para> If the exception type specified in a declare soft statement is a super type of <literal>RuntimeException</literal> - (such as <literal>Exception</literal> for example) then any <emphasis>checked</emphasis> exception thrown at a matched join point, - where the exception is an instance of the softened exception, will be softened to an - <literal>org.aspectj.lang.SoftException</literal>. + (such as <literal>Exception</literal> for example) then any <emphasis>checked</emphasis> exception thrown at a matched join point, + where the exception is an instance of the softened exception, will be softened to an + <literal>org.aspectj.lang.SoftException</literal>. </para> - + <programlisting><![CDATA[ - public aspect SoftenExample { - - declare soft : Exception : execution(* Foo.*(..)); - - } - - class Foo { - - public static void main(String[] args) { - Foo foo = new Foo(); - foo.foo(); - foo.bar(); - } - - void foo() throws Exception { - throw new Exception(); // this will be converted to a SoftException - } - - void bar() throws Exception { - throw new RuntimeException(); // this will remain a RuntimeException - } - - } - ]]></programlisting> - - +public aspect SoftenExample { + declare soft : Exception : execution(* Foo.*(..)); +} + +class Foo { + public static void main(String[] args) { + Foo foo = new Foo(); + foo.foo(); + foo.bar(); + } + + void foo() throws Exception { + throw new Exception(); // this will be converted to a SoftException + } + + void bar() throws Exception { + throw new RuntimeException(); // this will remain a RuntimeException + } +} +]]></programlisting> + + </sect1> - + </chapter> diff --git a/docs/adk15ProgGuideDB/pertypewithin.xml b/docs/adk15ProgGuideDB/pertypewithin.xml index 4a5e9bbab..3d901a2f7 100644 --- a/docs/adk15ProgGuideDB/pertypewithin.xml +++ b/docs/adk15ProgGuideDB/pertypewithin.xml @@ -3,61 +3,61 @@ <title>The pertypewithin Aspect Instantiation Model</title> <para> - AspectJ 5 defines a new per-clause type for aspect instantiation: + AspectJ 5 defines a new per-clause type for aspect instantiation: <literal>pertypewithin</literal>. Unlike the other per-clauses, - <literal>pertypewithin</literal> takes a type pattern: + <literal>pertypewithin</literal> takes a type pattern: </para> - + <programlisting><![CDATA[ - PerTypeWithin := 'pertypewithin' '(' OptionalParensTypePattern ')' - ]]></programlisting> - +PerTypeWithin := 'pertypewithin' '(' OptionalParensTypePattern ')' +]]></programlisting> + <para> When an aspect is declared using the <literal>pertypewithin</literal> instantiation model, one new aspect instance will be created for each type matched by the associated type pattern. </para> - + <para> - Pertypewithin aspects have <literal>aspectOf</literal> and + Pertypewithin aspects have <literal>aspectOf</literal> and <literal>hasAspect</literal> methods with the following signatures: </para> - + <programlisting><![CDATA[ - /** - * return true if this aspect has an instance associated with - * the given type. - */ - public static boolean hasAspect(Class clazz) - - /** - * return the instance associated with the given type. - * Throws NoAspectBoundException if there is no such - * aspect. - */ - public static P aspectOf(Class clazz) - ]]></programlisting> - +/** + * return true if this aspect has an instance associated with + * the given type. + */ +public static boolean hasAspect(Class clazz) + +/** + * return the instance associated with the given type. + * Throws NoAspectBoundException if there is no such + * aspect. + */ +public static P aspectOf(Class clazz) +]]></programlisting> + <para> Where <literal>P</literal> is the type of the <literal>pertypewithin</literal> aspect. </para> - + <para> - In addition, <literal>pertypewithin</literal> aspects have a + In addition, <literal>pertypewithin</literal> aspects have a <literal>getWithinTypeName</literal> method that can be called to return the package qualified name of the type for which the aspect instance has been created. </para> - + <programlisting><![CDATA[ - /** - * return the package qualified name (eg. com.foo.MyClass) of the type - * for which the aspect instance has been instantiated. - */ - public String getWithinTypeName() - ]]></programlisting> - +/** + * return the package qualified name (eg. com.foo.MyClass) of the type + * for which the aspect instance has been instantiated. + */ +public String getWithinTypeName() +]]></programlisting> + <para> In common with the other per-clause instantiation models, the execution of any advice declared within a <literal>pertypewithin</literal> aspect @@ -68,24 +68,24 @@ </para> <programlisting><![CDATA[ - import java.util.*; - - public aspect InstanceTracking pertypewithin(org.xyz..*) { - - // use WeakHashMap for auto-garbage collection of keys - private Map<Object,Boolean> instances = new WeakHashMap<Object,Boolean>(); - - after(Object o) returning() : execution(new(..)) && this(o) { - instances.put(o,true); - } - - public Set<?> getInstances() { - return instances.keySet(); - } - - } - ]]></programlisting> - +import java.util.*; + +public aspect InstanceTracking pertypewithin(org.xyz..*) { + + // use WeakHashMap for auto-garbage collection of keys + private Map<Object,Boolean> instances = new WeakHashMap<Object,Boolean>(); + + after(Object o) returning() : execution(new(..)) && this(o) { + instances.put(o,true); + } + + public Set<?> getInstances() { + return instances.keySet(); + } + +} +]]></programlisting> + <para> Then one aspect instance will be created for each type within <literal>org.xyz..*</literal>. For each aspect instance, the @@ -93,18 +93,18 @@ within the matched per-type-within type. The net result is that the aspect tracks all known instances of each type within <literal>org.xyz..*</literal>. To get access to the instances, a - programmer can simply write + programmer can simply write <literal>InstanceTracking.aspectOf(org.xyz.SomeType.class).getInstances()</literal>. </para> - + <para> The <literal>pertypewithin</literal> aspect instantiation model should be used when the implementation of a crosscutting concern requires that some state be maintained for each type in a set of types. To maintain state for a single type, it is easier to use a static inter-type declared field. Examples of usage include instance tracking, profiling, and the - implementation of a common tracing idiom that uses one Logger per + implementation of a common tracing idiom that uses one Logger per traced class. - </para> + </para> </chapter> diff --git a/docs/adk15ProgGuideDB/varargs.xml b/docs/adk15ProgGuideDB/varargs.xml index 487a8c01d..31dddde80 100644 --- a/docs/adk15ProgGuideDB/varargs.xml +++ b/docs/adk15ProgGuideDB/varargs.xml @@ -1,21 +1,21 @@ <chapter id="varargs" xreflabel="Varargs"> <title>Varargs</title> - + <sect1 id="varargs-inJava5" xreflabel="Varargs in Java 5"> <title>Variable-length Argument Lists in Java 5</title> - + <para> - Java 5 (and hence AspectJ 5) allows you to specify methods that take a + Java 5 (and hence AspectJ 5) allows you to specify methods that take a variable number of arguments of a specified type. This is achieved using - an ellipsis (...) in the method signature as shown: + an ellipsis (...) in the method signature as shown: </para> <programlisting><![CDATA[ - public void foo(int i, String... strings) { - } - ]]></programlisting> - +public void foo(int i, String... strings) { +} +]]></programlisting> + <para> A method or constructor may take at most one variable length argument, and this must always be the last declared argument in the signature. @@ -23,82 +23,81 @@ <sect2 id="calling-methods-and-constructors-with-variable-length-arguments" xreflabel="calling-methods-and-constructors-with-variable-length-arguments"> <title>Calling Methods and Constructors with variable-length arguments</title> - + <para> A <emphasis>varargs</emphasis> method may be called with zero or more arguments - in the variable argument position. For example, given the definition of + in the variable argument position. For example, given the definition of <literal>foo</literal> above, the following calls are all legal: </para> <programlisting><![CDATA[ - foo(5); - foo(5,"One String"); - foo(7,"One String","Two Strings"); - foo(3,"One String","Two Strings","Three Strings"); - ]]></programlisting> +foo(5); +foo(5,"One String"); +foo(7,"One String","Two Strings"); +foo(3,"One String","Two Strings","Three Strings"); +]]></programlisting> - <para>A <emphasis>varargs</emphasis> parameter is treated as an array within the + <para>A <emphasis>varargs</emphasis> parameter is treated as an array within the defining member. So in the body of <literal>foo</literal> we could write for example: </para> <programlisting><![CDATA[ - public void foo(int i, String... strings) { - String[] someStrings = strings; - // rest of method body - } - ]]></programlisting> +public void foo(int i, String... strings) { + String[] someStrings = strings; + // rest of method body +} +]]></programlisting> <para>One consequence of this treatment of a varargs parameter as an array is that you can also call a varargs method with an array:</para> <programlisting><![CDATA[ - foo(7,new String[] {"One String","Two Strings"}); - ]]></programlisting> - +foo(7,new String[] {"One String","Two Strings"}); +]]></programlisting> + </sect2> - + </sect1> <sect1 id="varargs-in-pcds"> <title>Using Variable-length arguments in advice and pointcut expressions</title> - + <para>AspectJ 5 allows variable-length arguments to be used for methods declared within aspects, and for inter-type declared methods and constructors, in accordance with the rules outlined in the previous section.</para> - + <para> AspectJ 5 also allows variable length arguments to be matched by pointcut expressions and bound as formals in advice. </para> - + <sect2 id="matching-signatures-based-on-variable-length-argument-types" xreflabel="matching-signatures-based-on-variable-length-argument-types"> <title>Matching signatures based on variable length argument types</title> - + <para> Recall from the definition of signature patterns given in the chapter on annotations (<xref linkend="signaturePatterns"/>), that <literal>MethodPattern</literal> and <literal>ConstructorPattern</literal> are extended to allow a <literal>varargs</literal> pattern in the last argument position of a method or constructor signature. </para> - - <programlisting><![CDATA[ - FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | - OptionalParensTypePattern (',' FormalsPattern)* | - TypePattern '...' - - FormalsPatternAfterDotDot := - OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | - TypePattern '...' - - ]]></programlisting> - + + <programlisting><![CDATA[ +FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | + OptionalParensTypePattern (',' FormalsPattern)* | + TypePattern '...' + +FormalsPatternAfterDotDot := + OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | + TypePattern '...' +]]></programlisting> + <para> Method and constructor patterns are used in the <literal>call</literal>, <literal>execution</literal>, <literal>initialization</literal>, <literal>preinitialization</literal>, and <literal>withincode</literal> pointcut designators. Some examples of usage follow: - </para> - + </para> + <variablelist> <varlistentry> @@ -121,7 +120,7 @@ </para> </listitem> </varlistentry> - + <varlistentry> <term>initialization(org.xyz.*.new((Foo || Goo)...))</term> <listitem> @@ -134,30 +133,30 @@ </para> </listitem> </varlistentry> - + </variablelist> - + <para>A variable argument parameter and an array parameter are treated as distinct signature elements, so given the method definitions: </para> <programlisting><![CDATA[ - void foo(String...); - void bar(String[]); - ]]></programlisting> - +void foo(String...); +void bar(String[]); +]]></programlisting> + <para> The pointcut <literal>execution(* *.*(String...))</literal> matches the execution join point - for <literal>foo</literal>, but not <literal>bar</literal>. The pointcut + for <literal>foo</literal>, but not <literal>bar</literal>. The pointcut <literal>execution(* *.*(String[]))</literal> matches the execution join point for <literal>bar</literal> but not <literal>foo</literal>. </para> - + </sect2> - + <sect2 id="exposing-variable-length-arguments-as-context-in-pointcuts-and-advice" xreflabel="exposing-variable-length-arguments-as-context-in-pointcuts-and-advice"> <title>Exposing variable-length arguments as context in pointcuts and advice</title> - + <para> When a varargs parameter is used within the body of a method, it has an array type, as discussed in the introduction to this section. We follow the @@ -166,9 +165,9 @@ </para> <programlisting><![CDATA[ - public void foo(int i, String... strings) { - } - ]]></programlisting> +public void foo(int i, String... strings) { +} +]]></programlisting> <para> The call or execution join points for <literal>foo</literal> will be matched @@ -176,34 +175,34 @@ to use the varargs syntax within an args pointcut designator - so you <emphasis>cannot</emphasis> write <literal>args(int,String...)</literal>. </para> - + <para> Binding of a varargs parameter in an advice statement is straightforward: </para> - + <programlisting><![CDATA[ - before(int i, String[] ss) : call(* foo(int,String...)) && args(i,ss) { - // varargs String... argument is accessible in advice body through ss - // ... - } - ]]></programlisting> - +before(int i, String[] ss) : call(* foo(int,String...)) && args(i,ss) { + // varargs String... argument is accessible in advice body through ss + // ... +} +]]></programlisting> + <para>Since you cannot use the varargs syntax in the <literal>args</literal> pointcut designator, you also cannot use the varargs syntax to declare - advice parameters.</para> - - <para>Note: the proposal in this section does not allow you to + advice parameters.</para> + + <para>Note: the proposal in this section does not allow you to distinguish between a join point with a signature (int, String...) - and a join point with a signature (int, String[]) based + and a join point with a signature (int, String[]) based <emphasis>solely</emphasis> on the use of the <literal>args</literal> pointcut designator. If this distinction is required, <literal>args</literal> - can always be coupled with <literal>call</literal> or + can always be coupled with <literal>call</literal> or <literal>execution</literal>.</para> </sect2> - + </sect1> - + </chapter> |