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>tags/V1_9_7_M2
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -1,9 +1,9 @@ | |||
<refentry id="aj-ref" xreflabel="The aj Command-line Reference"> | |||
<refnamediv> | |||
<refnamediv> | |||
<refname>aj</refname> | |||
<refpurpose>command-line launcher for basic load-time weaving</refpurpose> | |||
</refnamediv> | |||
</refnamediv> | |||
<refsynopsisdiv> | |||
<cmdsynopsis> | |||
@@ -16,39 +16,39 @@ | |||
</refsynopsisdiv> | |||
<refsect1 id="aj" xreflabel="aj"> | |||
<title>Description</title> | |||
<para>The | |||
<command>aj</command> command runs Java programs in Java 1.4 or | |||
later by setting up | |||
<literal>WeavingURLClassLoader</literal> as the system class | |||
loader, to do load-time bytecode weaving. </para> | |||
<para> The arguments are the same as those used to launch the Java program. | |||
Users should define the environment variables | |||
<literal>CLASSPATH</literal> and | |||
<literal>ASPECTPATH</literal>. </para> | |||
<para>For more information and alternatives for load-time weaving, | |||
see <xref linkend="ltw"/>. | |||
</para> | |||
<refsect2> | |||
<title>Examples</title> | |||
<example id="simpleajexample"> | |||
<title>A simple example</title> | |||
<para>Use ajc to build a library, then weave at load time</para> | |||
<programlisting><![CDATA[ | |||
REM compile library | |||
${ASPECTJ_HOME}\bin\ajc.bat -outjar lib\aspects.jar @aspects.lst | |||
REM run, weaving into application at load-time set | |||
ASPECTPATH=lib\aspects.jar set CLASSPATH=app\app.jar | |||
${ASPECTJ_HOME}\bin\aj.bat com.company.app.Main "Hello, World!" | |||
]]> </programlisting> | |||
<programlisting><![CDATA[ | |||
REM compile library | |||
${ASPECTJ_HOME}\bin\ajc.bat -outjar lib\aspects.jar @aspects.lst | |||
REM run, weaving into application at load-time set | |||
ASPECTPATH=lib\aspects.jar set CLASSPATH=app\app.jar | |||
${ASPECTJ_HOME}\bin\aj.bat com.company.app.Main "Hello, World!" | |||
]]> </programlisting> | |||
</example> | |||
</refsect2> | |||
</refsect1> |
@@ -5,33 +5,33 @@ | |||
<sect1 id="ajbrowser-intro"> | |||
<title>Introduction</title> | |||
<para> | |||
AJBrowser presents a GUI for compiling programs with ajc | |||
AJBrowser presents a GUI for compiling programs with ajc | |||
and navigating crosscutting structure. | |||
</para> | |||
<para> | |||
The AspectJ Browser can edit program source files, | |||
compile using the AspectJ compiler <literal>ajc</literal> | |||
run a program, | |||
and graphically navigate the program's | |||
and graphically navigate the program's | |||
crosscutting structure. | |||
For more information on <literal>ajc</literal>, | |||
For more information on <literal>ajc</literal>, | |||
see <xref linkend="ajc-ref"/>. | |||
</para> | |||
<para> | |||
Launch the browser from the command line either | |||
by typing "ajbrowser" to invoke the script in | |||
<literal>{aspectj}/bin</literal> | |||
(if AspectJ is installed correctly) | |||
(if AspectJ is installed correctly) | |||
or by using the | |||
<literal>aspectjtools.jar</literal> directly, | |||
and specifying no arguments or some number of | |||
build configuration files | |||
build configuration files | |||
(suffix <literal>.lst</literal>): | |||
<programlisting> | |||
java -jar aspectj1.1/lib/aspectjtools.jar aspectj1.1/doc/examples/spacewar/debug.lst | |||
java -jar aspectj1.1/lib/aspectjtools.jar aspectj1.1/doc/examples/spacewar/debug.lst | |||
</programlisting> | |||
</para> | |||
@@ -47,35 +47,35 @@ | |||
Because <literal>ajc</literal> requires all sources to be specified | |||
(at least using the <literal>-sourceroots</literal> option), | |||
most users create <literal>.lst</literal> files that list | |||
the files to compile (one argument per line, globbing | |||
the files to compile (one argument per line, globbing | |||
permitted - for more details, see <xref linkend="ajc-ref"/>). | |||
</para> | |||
<para> | |||
To work with a particular program, select the | |||
To work with a particular program, select the | |||
corresponding ".lst" build configuration file | |||
from the GUI using the File menu, "open" item, | |||
or by using the | |||
from the GUI using the File menu, "open" item, | |||
or by using the | |||
"Open Build Configuration" button | |||
(<inlinemediaobject> | |||
<imageobject> | |||
<imagedata fileref="openConfig.gif"/> | |||
</imageobject> | |||
</inlinemediaobject>). | |||
You can populate the build list from the command line | |||
by passing any number of ".lst" paths. | |||
(However, if you pass in any non-".lst" arguments, | |||
by passing any number of ".lst" paths. | |||
(However, if you pass in any non-".lst" arguments, | |||
it will run the command-line compiler directly.) | |||
</para> | |||
<para> | |||
To switch between build configurations, | |||
select, add, or remove them | |||
using the corresponding toolbar buttons. | |||
using the corresponding toolbar buttons. | |||
</para> | |||
<para>Global build options are stored in an | |||
<para>Global build options are stored in an | |||
<literal>.ajbrowser</literal> file in your HOME directory. | |||
Edit these from the GUI by clicking the "Options" button | |||
or selecting the Tools menu item "Options...". | |||
Edit these from the GUI by clicking the "Options" button | |||
or selecting the Tools menu item "Options...". | |||
This is how to set classpath, aspectpath, etc. | |||
</para> | |||
<para>The following sections walk through a build. | |||
@@ -90,8 +90,8 @@ | |||
<imageobject> | |||
<imagedata fileref="build.gif"/> | |||
</imageobject> | |||
</inlinemediaobject>), or | |||
or use the tools menu. | |||
</inlinemediaobject>), or | |||
or use the tools menu. | |||
</para> | |||
<!-- | |||
<para>To build using AspectJ 1.1's incremental mode, | |||
@@ -99,7 +99,7 @@ | |||
the <literal>AspectJ Build Options</literal> tab | |||
of the <literal>Options</literal> dialog. | |||
Once in incremental mode, you can force a full rebuild | |||
by holding the shift key down when selecting the | |||
by holding the shift key down when selecting the | |||
build menu item or button. | |||
</para> | |||
--> | |||
@@ -120,7 +120,7 @@ | |||
<sect1 id="ajbrowser-navigating"> | |||
<title>Navigating Program Structure</title> | |||
<para> | |||
Select nodes in the program structure by clicking them (see label 2). | |||
If one node is related to one or more other nodes by an association the | |||
@@ -175,9 +175,9 @@ | |||
</inlinemediaobject>). Click the <literal>Build Options</literal> tab | |||
to view the Build Paths pane. Edit the classpath entry to use your | |||
install location. For example, if you ran from the base Aspectj | |||
directory, the classpath need only include | |||
directory, the classpath need only include | |||
<literal>lib/aspectjrt.jar</literal> (though the browser may populate | |||
the classpath with the bootclasspath and classpath initially.) | |||
the classpath with the bootclasspath and classpath initially.) | |||
Be sure to use the | |||
<literal>lib/aspectjrt.jar</literal> that came with the browser. | |||
</para> | |||
@@ -274,13 +274,13 @@ | |||
<literal>affects</literal> relations will list different | |||
kinds of join points - constructor or method calls, etc. | |||
</para> | |||
<para>Note that the AspectJ browser can only display | |||
<para>Note that the AspectJ browser can only display | |||
static structure (whether hierarchical or crosscutting). | |||
That means that dynamicly-determined pointcuts (like | |||
<literal>cflow(pointcut)</literal>) | |||
<literal>cflow(pointcut)</literal>) | |||
will not be shown as picking out static points in | |||
source code. Displayable pointcuts roughly correspond | |||
to those that can be used in a | |||
to those that can be used in a | |||
<literal>declare error</literal> statement. | |||
</para> | |||
</listitem> | |||
@@ -297,19 +297,19 @@ | |||
You can run in the same VM or spawn a new process; | |||
the latter is generally better for GUI programs. | |||
</para> | |||
<para>Both require that any classpath you set be specified | |||
<para>Both require that any classpath you set be specified | |||
using platform-specific paths and path separators (the | |||
compiler might be more tolerant). | |||
Output and error streams will be | |||
merged into the streams of the browser (using separate | |||
threads, so it may take a few seconds for the pipe | |||
threads to gain control.) Errors should | |||
threads to gain control.) Errors should | |||
be detected and displayed in a dialog. | |||
</para> | |||
<para> | |||
The GUI does not support killing a running program, | |||
so if your program might hang, | |||
be sure to save your files since you may need to | |||
be sure to save your files since you may need to | |||
kill the browser itself to kill its child processes. | |||
</para> | |||
</sect1> | |||
@@ -318,36 +318,36 @@ | |||
<title>Isolating problems running the AspectJ browser</title> | |||
<para> | |||
If you have problems with the browser not solved by the documentation, | |||
please try to see if you have the same problems when running ajc | |||
If you have problems with the browser not solved by the documentation, | |||
please try to see if you have the same problems when running ajc | |||
directly on the command line. | |||
</para> | |||
<itemizedlist> | |||
<listitem><para> | |||
If the problem occurs on the command line also, then the problem | |||
is not in the browser. | |||
If the problem occurs on the command line also, then the problem | |||
is not in the browser. | |||
(It may be in the compiler; please send bug reports.) | |||
</para></listitem> | |||
<listitem><para> | |||
If the problem does not occur on the command line, then it may | |||
If the problem does not occur on the command line, then it may | |||
lie in the parameters you are supplying in the build options. | |||
</para></listitem> | |||
<listitem><para> | |||
If the build options look correct and the problem only occurs | |||
If the build options look correct and the problem only occurs | |||
when building from the browser, then please submit a bug report. | |||
</para></listitem> | |||
</para></listitem> | |||
</itemizedlist> | |||
<sect2 id="ajbrowser-knownProblems"> | |||
<title>Known issues with the AspectJ browser</title> | |||
<para> | |||
For the most up-to-date information on known problems, | |||
see the | |||
For the most up-to-date information on known problems, | |||
see the | |||
<ulink url="http://bugs.eclipse.org/bugs">bug database</ulink> | |||
for unresolved | |||
for unresolved | |||
<ulink url="http://bugs.eclipse.org/bugs/buglist.cgi?&product=AspectJ&component=Compiler&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED"> | |||
compiler bugs | |||
</ulink> or | |||
</ulink> or | |||
<ulink url="http://bugs.eclipse.org/bugs/buglist.cgi?&product=AspectJ&component=IDE&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED"> | |||
IDE bugs | |||
</ulink>. | |||
@@ -355,55 +355,55 @@ | |||
<para> | |||
<itemizedlist> | |||
<listitem><para> | |||
Memory and forking: Users email most about the browser task running | |||
out of memory. | |||
This is not a problem with the browser; some compiles take a lot of | |||
Memory and forking: Users email most about the browser task running | |||
out of memory. | |||
This is not a problem with the browser; some compiles take a lot of | |||
memory, often more than similar compiles using javac. | |||
The browser does not support forking, so the only solution is to | |||
edit the java command line or script that launches the browser | |||
to add memory. | |||
</para></listitem> | |||
</para></listitem> | |||
<listitem><para> | |||
Editing build configuration files: this is not currently supported. | |||
</para></listitem> | |||
</para></listitem> | |||
<listitem><para> | |||
The structure model is incomplete after incremental compiles. | |||
To get a complete structure model requires a full build. | |||
</para></listitem> | |||
</para></listitem> | |||
<listitem><para> | |||
If you change the output directory, you must do a | |||
full build. | |||
</para></listitem> | |||
full build. | |||
</para></listitem> | |||
</itemizedlist> | |||
</para> | |||
</para> | |||
</sect2> | |||
<sect2 id="ajbrowser-limitations"> | |||
<title>Limitations</title> | |||
<para> | |||
<para> | |||
<itemizedlist> | |||
<listitem><para> | |||
The AJBrowser expects the package and directory structure to match. If they do not | |||
The AJBrowser expects the package and directory structure to match. If they do not | |||
it will be unable to browse to the corresponding file. | |||
</para></listitem> | |||
</para></listitem> | |||
<listitem><para> | |||
The "Run" feature launches applications in the same VM. As a result, if a Swing application | |||
is disposed the AJBrowser will be disposed as well. | |||
</para></listitem> | |||
</para></listitem> | |||
</itemizedlist> | |||
</para> | |||
</sect2> | |||
<sect2 id="ajbrowser-feedback"> | |||
<title>AspectJ Browser questions and bugs</title> | |||
<para> | |||
You can send email to | |||
<para> | |||
You can send email to | |||
<ulink url="mailto:aspectj-users@dev.eclipse.org"> | |||
aspectj-users@dev.eclipse.org</ulink>. | |||
(Do join the list to participate!) | |||
We also welcome any bug reports, patches, and feature requests; | |||
you can submit them to the bug database at | |||
aspectj-users@dev.eclipse.org</ulink>. | |||
(Do join the list to participate!) | |||
We also welcome any bug reports, patches, and feature requests; | |||
you can submit them to the bug database at | |||
<ulink url="http://bugs.eclipse.org/bugs"> | |||
http://bugs.eclipse.org/bugs</ulink> | |||
using the AspectJ product and IDE component. | |||
using the AspectJ product and IDE component. | |||
</para> | |||
</sect2> | |||
</sect1> |
@@ -1,9 +1,9 @@ | |||
<refentry id="ajc-ref" xreflabel="The ajc Command-line Reference"> | |||
<refnamediv> | |||
<refnamediv> | |||
<refname>ajc</refname> | |||
<refpurpose>compiler and bytecode weaver for the AspectJ and Java languages</refpurpose> | |||
</refnamediv> | |||
</refnamediv> | |||
<refsynopsisdiv> | |||
<cmdsynopsis> | |||
@@ -19,8 +19,8 @@ | |||
<refsect1 id="ajc" xreflabel="ajc"> | |||
<title>Description</title> | |||
<para>The <command>ajc</command> command compiles and weaves AspectJ and | |||
Java source and .class files, producing .class files compliant with any | |||
<para>The <command>ajc</command> command compiles and weaves AspectJ and | |||
Java source and .class files, producing .class files compliant with any | |||
Java VM (1.1 or later). It combines compilation and bytecode weaving | |||
and supports incremental builds; you can also weave bytecode | |||
at run-time using <xref linkend="ltw"/>. | |||
@@ -29,28 +29,28 @@ | |||
<para> The arguments after the options specify the source file(s) to compile. | |||
To specify source classes, use <parameter>-inpath</parameter> (below). | |||
Files may be listed directly on the command line or in a file. | |||
The <parameter>-argfile <replaceable>file</replaceable></parameter> | |||
The <parameter>-argfile <replaceable>file</replaceable></parameter> | |||
and <parameter>@<replaceable>file</replaceable></parameter> forms | |||
are equivalent, and are interpreted as meaning all the arguments | |||
listed in the specified file. | |||
are equivalent, and are interpreted as meaning all the arguments | |||
listed in the specified file. | |||
</para> | |||
<para> | |||
<command>Note:</command> | |||
<para> | |||
<command>Note:</command> | |||
You must explicitly pass <command>ajc</command> all necessary sources. | |||
Be sure to include the source not only for the | |||
aspects or pointcuts but also for any affected types. | |||
Specifying all sources is necessary because, unlike javac, ajc does not | |||
aspects or pointcuts but also for any affected types. | |||
Specifying all sources is necessary because, unlike javac, ajc does not | |||
search the sourcepath for classes. | |||
(For a discussion of what affected types might be required, | |||
see <ulink url="../progguide/implementation.html">The AspectJ | |||
Programming Guide, Implementation Appendix</ulink>.) | |||
</para> | |||
<para> | |||
To specify sources, you can list source files as arguments or use the | |||
To specify sources, you can list source files as arguments or use the | |||
options <parameter>-sourceroots</parameter> or <parameter>-inpath</parameter>. | |||
If there are multiple sources for any type, the result is undefined | |||
since ajc has no way to determine which source is correct. (This | |||
since ajc has no way to determine which source is correct. (This | |||
happens most often when users include the destination directory | |||
on the inpath and rebuild.) | |||
</para> | |||
@@ -71,12 +71,12 @@ | |||
<varlistentry> | |||
<term>-inpath <replaceable>Path</replaceable></term> | |||
<listitem><para> | |||
Accept as source bytecode any .class files in the | |||
.jar files or directories on Path. | |||
Accept as source bytecode any .class files in the | |||
.jar files or directories on Path. | |||
The output will include these | |||
classes, possibly as woven with any applicable aspects. | |||
Path is a single argument containing | |||
a list of paths to zip files or directories, | |||
a list of paths to zip files or directories, | |||
delimited by the platform-specific path delimiter. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -87,7 +87,7 @@ | |||
Weave binary aspects from jar files and directories on path into all sources. | |||
The aspects should have been output by the same version | |||
of the compiler. | |||
When running the output classes, the run classpath should contain | |||
When running the output classes, the run classpath should contain | |||
all aspectpath entries. | |||
Path, like classpath, is a single argument containing | |||
a list of paths to jar files, delimited by the platform- | |||
@@ -100,7 +100,7 @@ | |||
<listitem><para> | |||
The file contains a line-delimited list of arguments. | |||
Each line in the file should contain one option, filename, or | |||
argument string (e.g., a classpath or inpath). | |||
argument string (e.g., a classpath or inpath). | |||
Arguments read from the file are inserted into the argument list | |||
for the command. Relative paths in the file are calculated from | |||
the directory containing the file (not the current working directory). | |||
@@ -146,8 +146,8 @@ | |||
<varlistentry> | |||
<term>-sourceroots <replaceable>DirPaths</replaceable></term> | |||
<listitem><para>Find and build all .java or .aj source files under | |||
any directory listed in DirPaths. | |||
<listitem><para>Find and build all .java or .aj source files under | |||
any directory listed in DirPaths. | |||
DirPaths, like classpath, is a single argument containing | |||
a list of paths to directories, delimited by the platform- | |||
specific classpath delimiter. | |||
@@ -183,7 +183,7 @@ | |||
<listitem><para>Set default level for messages about potential | |||
programming mistakes in crosscutting code. | |||
{level} may be ignore, warning, or error. | |||
This overrides entries in | |||
This overrides entries in | |||
org/aspectj/weaver/XlintDefault.properties | |||
from aspectjtools.jar, but does not override levels set | |||
using the -Xlintfile option. | |||
@@ -193,7 +193,7 @@ | |||
<varlistentry> | |||
<term>-Xlintfile <replaceable>PropertyFile</replaceable></term> | |||
<listitem><para>Specify properties file to set levels for | |||
specific crosscutting messages. | |||
specific crosscutting messages. | |||
PropertyFile is a path to a Java .properties file that | |||
takes the same property names and values as | |||
org/aspectj/weaver/XlintDefault.properties | |||
@@ -220,7 +220,7 @@ | |||
<listitem><para> | |||
Specify where to find user class files. | |||
Path is a single argument containing | |||
a list of paths to zip files or directories, | |||
a list of paths to zip files or directories, | |||
delimited by the platform-specific path delimiter. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -228,10 +228,10 @@ | |||
<varlistentry> | |||
<term>-bootclasspath <replaceable>Path</replaceable></term> | |||
<listitem><para> | |||
Override location of VM's bootclasspath | |||
Override location of VM's bootclasspath | |||
for purposes of evaluating types when compiling. | |||
Path is a single argument containing | |||
a list of paths to zip files or directories, | |||
a list of paths to zip files or directories, | |||
delimited by the platform-specific path delimiter. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -239,10 +239,10 @@ | |||
<varlistentry> | |||
<term>-extdirs <replaceable>Path</replaceable></term> | |||
<listitem><para> | |||
Override location of VM's extension directories | |||
Override location of VM's extension directories | |||
for purposes of evaluating types when compiling. | |||
Path is a single argument containing | |||
a list of paths to directories, | |||
a list of paths to directories, | |||
delimited by the platform-specific path delimiter. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -251,7 +251,7 @@ | |||
<term>-d <replaceable>Directory</replaceable></term> | |||
<listitem><para> | |||
Specify where to place generated .class files. | |||
If not specified, <replaceable>Directory</replaceable> | |||
If not specified, <replaceable>Directory</replaceable> | |||
defaults to the current working dir. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -264,7 +264,7 @@ | |||
<varlistentry> | |||
<term>-1.3</term> | |||
<listitem><para>Set compliance level to 1.3 | |||
<listitem><para>Set compliance level to 1.3 | |||
This implies -source 1.3 and -target 1.1. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -288,11 +288,11 @@ | |||
<listitem><para>Toggle assertions (1.3, 1.4, or 1.5 - default is 1.4). | |||
When using -source 1.3, an assert() statement valid under | |||
Java 1.4 will result in a compiler error. | |||
When using -source 1.4, | |||
treat <literal>assert</literal> as a keyword and | |||
When using -source 1.4, | |||
treat <literal>assert</literal> as a keyword and | |||
implement assertions according to the 1.4 language spec. | |||
When using -source 1.5, | |||
Java 5 language features are permitted. | |||
Java 5 language features are permitted. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -308,22 +308,22 @@ | |||
<varlistentry> | |||
<term>-warn: <replaceable>items</replaceable></term> | |||
<listitem><para>Emit warnings for any instances of | |||
the comma-delimited list of questionable code | |||
the comma-delimited list of questionable code | |||
(eg '-warn:unusedLocals,deprecation'): | |||
<programlisting><!-- unable to embed itemizedlist? --> | |||
constructorName method with constructor name | |||
packageDefaultMethod attempt to override package-default method | |||
deprecation usage of deprecated type or member | |||
maskedCatchBlocks hidden catch block | |||
unusedLocals local variable never read | |||
unusedArguments method argument never read | |||
unusedImports import statement not used by code in file | |||
none suppress all compiler warnings | |||
constructorName method with constructor name | |||
packageDefaultMethod attempt to override package-default method | |||
deprecation usage of deprecated type or member | |||
maskedCatchBlocks hidden catch block | |||
unusedLocals local variable never read | |||
unusedArguments method argument never read | |||
unusedImports import statement not used by code in file | |||
none suppress all compiler warnings | |||
</programlisting> | |||
<literal>-warn:none</literal> does not suppress messages | |||
generated by <literal>declare warning</literal> or | |||
<literal>Xlint</literal>. | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -341,7 +341,7 @@ | |||
<varlistentry> | |||
<term>-proceedOnError</term> | |||
<listitem><para>Keep compiling after error, | |||
<listitem><para>Keep compiling after error, | |||
dumping class files with problem methods | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -351,12 +351,12 @@ | |||
<listitem> | |||
<para>debug attributes level, that may take three forms: | |||
<programlisting> | |||
-g all debug info ('-g:lines,vars,source') | |||
-g:none no debug info | |||
-g:{items} debug info for any/all of [lines, vars, source], e.g., | |||
-g:lines,source | |||
-g all debug info ('-g:lines,vars,source') | |||
-g:none no debug info | |||
-g:{items} debug info for any/all of [lines, vars, source], e.g., | |||
-g:lines,source | |||
</programlisting> | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -383,16 +383,16 @@ | |||
<varlistentry> | |||
<term>-verbose</term> | |||
<listitem><para>Emit messages about accessed/processed compilation units | |||
<listitem><para>Emit messages about accessed/processed compilation units | |||
</para></listitem> | |||
</varlistentry> | |||
<varlistentry> | |||
<term>-showWeaveInfo</term> | |||
<listitem><para>Emit messages about weaving | |||
<listitem><para>Emit messages about weaving | |||
</para></listitem> | |||
</varlistentry> | |||
<varlistentry> | |||
<term>-log <replaceable>file</replaceable></term> | |||
<listitem><para>Specify a log file for compiler messages. | |||
@@ -420,7 +420,7 @@ | |||
<varlistentry> | |||
<term>-repeat <replaceable>N</replaceable></term> | |||
<listitem><para>Repeat compilation process N times | |||
<listitem><para>Repeat compilation process N times | |||
(typically to do performance analysis). | |||
</para></listitem> | |||
</varlistentry> | |||
@@ -430,7 +430,7 @@ | |||
<listitem><para>Causes compiler to terminate before weaving | |||
</para></listitem> | |||
</varlistentry> | |||
<varlistentry> | |||
<term>-XaddSerialVersionUID</term> | |||
<listitem><para>Causes the compiler to calculate and add | |||
@@ -440,10 +440,10 @@ | |||
taken place. | |||
</para></listitem> | |||
</varlistentry> | |||
<varlistentry> | |||
<term>-Xreweavable[:compress]</term> | |||
<listitem><para>(Experimental - deprecated as now default) | |||
<listitem><para>(Experimental - deprecated as now default) | |||
Runs weaver in reweavable mode which causes | |||
it to create woven classes that can be rewoven, subject to the restriction that | |||
on attempting a reweave all the types that advised the woven type must be accessible. | |||
@@ -458,8 +458,8 @@ | |||
<varlistentry> | |||
<term>-XincrementalFile <replaceable>file</replaceable></term> | |||
<listitem><para>(Experimental) This works like incremental mode, | |||
but using a file rather than standard input to control the compiler. | |||
<listitem><para>(Experimental) This works like incremental mode, | |||
but using a file rather than standard input to control the compiler. | |||
It will recompile each time file is changed and | |||
and halt when file is deleted. | |||
</para></listitem> | |||
@@ -497,7 +497,7 @@ | |||
</refsect2> | |||
<refsect2> | |||
<refsect2> | |||
<title>File names</title> | |||
<para>ajc accepts source files with either the <filename>.java</filename> | |||
@@ -511,7 +511,7 @@ | |||
<para>We'd like to discourage other means of mechanical distinction such as | |||
naming conventions or sub-packages in favor of the <filename>.aj</filename> | |||
extension.</para> | |||
<itemizedlist> | |||
<listitem><para>Filename conventions are hard to enforce and lead to awkward names | |||
@@ -560,7 +560,7 @@ | |||
<para>Compile two files:</para> | |||
<programlisting> | |||
ajc HelloWorld.java Trace.java | |||
ajc HelloWorld.java Trace.java | |||
</programlisting> | |||
</example> | |||
@@ -569,28 +569,29 @@ | |||
<title>An example using -argfile/@</title> | |||
<para> | |||
To avoid specifying file names on the command line, | |||
To avoid specifying file names on the command line, | |||
list source files in a line-delimited text argfile. | |||
Source file paths may be absolute or relative to the argfile, | |||
and may include other argfiles by @-reference. | |||
The following file <literal>sources.lst</literal> | |||
contains absolute and relative files and @-references: | |||
</para> | |||
<programlisting> | |||
<programlisting> | |||
Gui.java | |||
/home/user/src/Library.java | |||
data/Repository.java | |||
data/Access.java | |||
@../../common/common.lst | |||
@/home/user/src/lib.lst | |||
view/body/ArrayView.java</programlisting> | |||
view/body/ArrayView.java | |||
</programlisting> | |||
<para>Compile the files using either the -argfile or @ form:</para> | |||
<programlisting> | |||
ajc -argfile sources.lst | |||
ajc @sources.lst</programlisting> | |||
<para> | |||
Argfiles are also supported by jikes and javac, so you | |||
Argfiles are also supported by jikes and javac, so you | |||
can use the files in hybrid builds. However, the support varies: | |||
</para> | |||
<itemizedlist> | |||
@@ -604,110 +605,110 @@ ajc @sources.lst</programlisting> | |||
<example id="examplebytecode"> | |||
<title>An example using -inpath and -aspectpath</title> | |||
<para>Bytecode weaving using -inpath: | |||
AspectJ 1.2 supports weaving .class files in input zip/jar files | |||
and directories. | |||
Using input jars is like compiling the corresponding | |||
source files, and all binaries are emitted to output. Although | |||
Java-compliant compilers may differ in their output, ajc should | |||
take as input any class files produced by javac, jikes, eclipse, | |||
AspectJ 1.2 supports weaving .class files in input zip/jar files | |||
and directories. | |||
Using input jars is like compiling the corresponding | |||
source files, and all binaries are emitted to output. Although | |||
Java-compliant compilers may differ in their output, ajc should | |||
take as input any class files produced by javac, jikes, eclipse, | |||
and, of course, ajc. Aspects included in -inpath will be woven into | |||
like other .class files, and they will affect other types as usual. | |||
</para> | |||
<para>Aspect libraries using -aspectpath: | |||
AspectJ 1.1 supports weaving from read-only libraries containing | |||
aspects. Like input jars, they affect all input; unlike input | |||
jars, they themselves are not affected or emitted as output. | |||
Sources compiled with aspect libraries must be run with the same | |||
aspect libraries on their classpath. | |||
AspectJ 1.1 supports weaving from read-only libraries containing | |||
aspects. Like input jars, they affect all input; unlike input | |||
jars, they themselves are not affected or emitted as output. | |||
Sources compiled with aspect libraries must be run with the same | |||
aspect libraries on their classpath. | |||
</para> | |||
<para>The following example builds the tracing example in a | |||
command-line environment; it creates a read-only aspect library, | |||
compiles some classes for use as input bytecode, and | |||
<para>The following example builds the tracing example in a | |||
command-line environment; it creates a read-only aspect library, | |||
compiles some classes for use as input bytecode, and | |||
compiles the classes and other sources with the aspect library. | |||
</para> | |||
<para>The tracing example is in the AspectJ distribution | |||
<para>The tracing example is in the AspectJ distribution | |||
({aspectj}/doc/examples/tracing). This uses the following files: | |||
</para> | |||
<para><programlisting> | |||
aspectj1.1/ | |||
bin/ | |||
ajc | |||
lib/ | |||
aspectjrt.jar | |||
examples/ | |||
tracing/ | |||
Circle.java | |||
ExampleMain.java | |||
lib/ | |||
AbstractTrace.java | |||
TraceMyClasses.java | |||
notrace.lst | |||
Square.java | |||
tracelib.lst | |||
tracev3.lst | |||
TwoDShape.java | |||
version3/ | |||
Trace.java | |||
TraceMyClasses.java | |||
aspectj1.1/ | |||
bin/ | |||
ajc | |||
lib/ | |||
aspectjrt.jar | |||
examples/ | |||
tracing/ | |||
Circle.java | |||
ExampleMain.java | |||
lib/ | |||
AbstractTrace.java | |||
TraceMyClasses.java | |||
notrace.lst | |||
Square.java | |||
tracelib.lst | |||
tracev3.lst | |||
TwoDShape.java | |||
version3/ | |||
Trace.java | |||
TraceMyClasses.java | |||
</programlisting></para> | |||
<para>Below, the path separator is taken as ";", but file separators | |||
are "/". All commands are on one line. Adjust paths and | |||
commands to your environment as needed. | |||
<para>Below, the path separator is taken as ";", but file separators | |||
are "/". All commands are on one line. Adjust paths and | |||
commands to your environment as needed. | |||
</para><para>Setup the path, classpath, and current directory:</para> | |||
</para><para>Setup the path, classpath, and current directory:</para> | |||
<programlisting> | |||
cd examples | |||
export ajrt=../lib/aspectjrt.jar | |||
export CLASSPATH="$ajrt" | |||
export PATH="../bin:$PATH" | |||
cd examples | |||
export ajrt=../lib/aspectjrt.jar | |||
export CLASSPATH="$ajrt" | |||
export PATH="../bin:$PATH" | |||
</programlisting> | |||
<para>Build a read-only tracing library:</para> | |||
<para>Build a read-only tracing library:</para> | |||
<programlisting> | |||
ajc -argfile tracing/tracelib.lst -outjar tracelib.jar | |||
ajc -argfile tracing/tracelib.lst -outjar tracelib.jar | |||
</programlisting> | |||
<para>Build the application with tracing in one step:</para> | |||
<para>Build the application with tracing in one step:</para> | |||
<programlisting> | |||
ajc -aspectpath tracelib.jar -argfile tracing/notrace.lst -outjar tracedapp.jar | |||
ajc -aspectpath tracelib.jar -argfile tracing/notrace.lst -outjar tracedapp.jar | |||
</programlisting> | |||
<para>Run the application with tracing:</para> | |||
<para>Run the application with tracing:</para> | |||
<programlisting> | |||
java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain | |||
java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain | |||
</programlisting> | |||
<para>Build the application with tracing from binaries in two steps:</para> | |||
<para>Build the application with tracing from binaries in two steps:</para> | |||
<itemizedlist><listitem><para> | |||
(a) Build the application classes (using javac for demonstration's sake):</para> | |||
(a) Build the application classes (using javac for demonstration's sake):</para> | |||
<programlisting> | |||
mkdir classes | |||
javac -d classes tracing/*.java | |||
jar cfM app.jar -C classes . | |||
mkdir classes | |||
javac -d classes tracing/*.java | |||
jar cfM app.jar -C classes . | |||
</programlisting> | |||
</listitem> | |||
<listitem><para> | |||
(b) Build the application with tracing:</para> | |||
(b) Build the application with tracing:</para> | |||
<programlisting> | |||
ajc -inpath app.jar -aspectpath tracelib.jar -outjar tracedapp.jar | |||
ajc -inpath app.jar -aspectpath tracelib.jar -outjar tracedapp.jar | |||
</programlisting> | |||
</listitem></itemizedlist> | |||
<para>Run the application with tracing (same as above):</para> | |||
<para>Run the application with tracing (same as above):</para> | |||
<programlisting> | |||
java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain | |||
java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain | |||
</programlisting> | |||
<para>Run the application without tracing:</para> | |||
<para>Run the application without tracing:</para> | |||
<programlisting> | |||
java -classpath "app.jar" tracing.ExampleMain | |||
java -classpath "app.jar" tracing.ExampleMain | |||
</programlisting> | |||
</example> | |||
@@ -721,7 +722,7 @@ commands to your environment as needed. | |||
called as a Java class. The only interface that should be considered | |||
public are the public methods in <literal>org.aspectj.tools.ajc.Main</literal>. | |||
E.g., <literal>main(String[] args)</literal> takes the | |||
the standard <command>ajc</command> command line arguments. | |||
the standard <command>ajc</command> command line arguments. | |||
This means that an alternative way to run the | |||
compiler is </para> | |||
@@ -736,9 +737,9 @@ commands to your environment as needed. | |||
<literal>ajc</literal> reports each message to the holder | |||
using <literal>IMessageHolder.handleMessage(..)</literal>. | |||
If you just want to collect the messages, use | |||
<literal>MessageHandler</literal> as your | |||
<literal>MessageHandler</literal> as your | |||
<literal>IMessageHolder</literal>. | |||
For example, compile and run the following with | |||
For example, compile and run the following with | |||
<literal>aspectjtools.jar</literal> on the classpath: | |||
</para> | |||
<programlisting> | |||
@@ -763,19 +764,19 @@ public class WrapAjc { | |||
<para>Unlike traditional java compilers, the AspectJ compiler may in | |||
certain cases generate classfiles from multiple source files. | |||
Unfortunately, the original Java class file format does not support | |||
Unfortunately, the original Java class file format does not support | |||
multiple | |||
SourceFile attributes. In order to make sure all source file | |||
information is available, the AspectJ compiler may in some cases | |||
encode multiple filenames in the SourceFile attribute. | |||
encode multiple filenames in the SourceFile attribute. | |||
When the Java VM generates stack traces, it uses this attribute | |||
to specify the source file. | |||
</para> | |||
<para>(The AspectJ 1.0 compiler also supports the .class file extensions of JSR-45. | |||
These permit compliant debuggers (such as jdb in Java 1.4.1) to identify | |||
These permit compliant debuggers (such as jdb in Java 1.4.1) to identify | |||
the right file and line even given many source files for a single class. | |||
JSR-45 support is planned for ajc in AspectJ 1.1, but is not in the initial | |||
release. To get fully debuggable .class files, use the -XnoInline option.) | |||
release. To get fully debuggable .class files, use the -XnoInline option.) | |||
</para> | |||
<para>Probably the only time you may see this format is when you view | |||
@@ -787,7 +788,7 @@ java.lang.NullPointerException | |||
at Main.new$constructor_call37(Main.java;SynchAspect.java[1k]:1030) | |||
</programlisting> | |||
<para>where instead of the usual | |||
<para>where instead of the usual | |||
</para> | |||
<programlisting> | |||
@@ -801,14 +802,14 @@ File:LineNumber | |||
File0;File1[Number1];File2[Number2] ... :LineNumber | |||
</programlisting> | |||
<para>In this case, LineNumber is the usual offset in lines plus the | |||
"start line" of the actual source file. That means you use LineNumber | |||
both to identify the source file and to find the line at issue. | |||
<para>In this case, LineNumber is the usual offset in lines plus the | |||
"start line" of the actual source file. That means you use LineNumber | |||
both to identify the source file and to find the line at issue. | |||
The number in [brackets] after each file tells you the | |||
virtual "start line" for that file (the first file has a start of 0). | |||
virtual "start line" for that file (the first file has a start of 0). | |||
</para> | |||
<para> In our example from the null pointer exception trace, | |||
<para> In our example from the null pointer exception trace, | |||
the virtual start line is 1030. Since the file SynchAspect.java | |||
"starts" at line 1000 [1k], the LineNumber points to line 30 of | |||
SynchAspect.java. |
@@ -43,11 +43,11 @@ | |||
<para> | |||
Note: As of the 1.0.3 release, AspectJ supports JSR-45, which provides | |||
source-level debugging from many source files per class | |||
and non-Java source files. | |||
JSR-45 is implemented in the J2SE 1.4 debugger support, so | |||
and non-Java source files. | |||
JSR-45 is implemented in the J2SE 1.4 debugger support, so | |||
you may be able to use your existing debugger to step through | |||
AspectJ source code if both the source and target VM's are | |||
running under Java 1.4 or later. | |||
running under Java 1.4 or later. | |||
However, existing debuggers will display synthetic methods | |||
in the stack frame. | |||
</para> <!-- todo find docs on JSR-45 --> | |||
@@ -132,23 +132,23 @@ | |||
spacewar/Ship.java</userinput> which generates the following | |||
output: | |||
<programlisting> | |||
209 void fire() { | |||
210 // firing a shot takes energy | |||
211 if (!expendEnergy(BULLET_ENERGY)) | |||
212 return; | |||
213 | |||
214 //create a bullet object so it doesn't hit the ship that's firing it | |||
215 double xV = getXVel() + BULLET_SPEED * (Math.cos(orientation)); | |||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
217 | |||
218 // create the actual bullet | |||
219 new Bullet( | |||
220 getGame(), | |||
221 (getXPos() + ((getSize()/2 + 2) * (Math.cos(orientation))) + xV), | |||
222 (getYPos() + ((getSize()/2 + 2) * (Math.sin(orientation))) + yV), | |||
223 xV, | |||
224 yV); | |||
225 } | |||
209 void fire() { | |||
210 // firing a shot takes energy | |||
211 if (!expendEnergy(BULLET_ENERGY)) | |||
212 return; | |||
213 | |||
214 //create a bullet object so it doesn't hit the ship that's firing it | |||
215 double xV = getXVel() + BULLET_SPEED * (Math.cos(orientation)); | |||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
217 | |||
218 // create the actual bullet | |||
219 new Bullet( | |||
220 getGame(), | |||
221 (getXPos() + ((getSize()/2 + 2) * (Math.cos(orientation))) + xV), | |||
222 (getYPos() + ((getSize()/2 + 2) * (Math.sin(orientation))) + yV), | |||
223 xV, | |||
224 yV); | |||
225 } | |||
</programlisting> | |||
</para> | |||
<para>This is different from <command>jdb</command> because it allows | |||
@@ -187,8 +187,8 @@ | |||
breakpoint has been noted but will not be set until the class has | |||
been loaded by the VM: </para> | |||
<programlisting> | |||
Deferring breakpoint spacewar.Ship.fire() | |||
It will be set after the class is loaded. | |||
Deferring breakpoint spacewar.Ship.fire() | |||
It will be set after the class is loaded. | |||
</programlisting> | |||
<para> | |||
@@ -198,14 +198,14 @@ | |||
<para> | |||
When the breakpoint is set, the following message appears: | |||
<programlisting> | |||
Set deferred breakpoint spacewar.Ship.fire() | |||
Set deferred breakpoint spacewar.Ship.fire() | |||
</programlisting> | |||
</para> | |||
<para> We are notified that we've hit the breakpoint: | |||
<programlisting> | |||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=174, bci=0 209 void fire() { | |||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=174, bci=0 209 void fire() { | |||
</programlisting></para> | |||
<para> | |||
@@ -213,10 +213,10 @@ | |||
can view the current stack with the <literal>where</literal> | |||
command, as follows: | |||
<programlisting> | |||
Thread-2[1] where | |||
[1] fire (spacewar\Ship.java:209) | |||
[2] run (spacewar\Robot.java:100) | |||
[3] run [class java.lang.Thread] | |||
Thread-2[1] where | |||
[1] fire (spacewar\Ship.java:209) | |||
[2] run (spacewar\Robot.java:100) | |||
[3] run [class java.lang.Thread] | |||
</programlisting> | |||
</para> | |||
@@ -228,23 +228,23 @@ | |||
<para> | |||
The following message tells us the breakpoint was set: | |||
<programlisting> | |||
Set breakpoint Ship.java:216 | |||
Set breakpoint Ship.java:216 | |||
</programlisting> | |||
</para> | |||
<para> | |||
To continue execution, we type <userinput>cont</userinput> and the | |||
breakpoint at line 216 is hit | |||
<programlisting> | |||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=216, bci=28 | |||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=216, bci=28 | |||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
</programlisting></para> | |||
<para> | |||
To view the visible local variables, we type | |||
<userinput>locals</userinput> and ajdb responds with: | |||
<programlisting> | |||
Local variables | |||
xV = 12.242462584304468 | |||
Local variables | |||
xV = 12.242462584304468 | |||
</programlisting></para> | |||
<para> | |||
@@ -252,22 +252,22 @@ | |||
<userinput>set xV = 16.1</userinput> | |||
<programlisting> | |||
Changed 'xV' from '12.242462584304468' to '16.1' | |||
Changed 'xV' from '12.242462584304468' to '16.1' | |||
</programlisting></para> | |||
<para> | |||
To see our changes we can print the value of <literal>i</literal> | |||
by the following: | |||
<programlisting> | |||
print xV | |||
Value for printing 'xV' = 12.242462584304468 | |||
print xV | |||
Value for printing 'xV' = 12.242462584304468 | |||
</programlisting></para> | |||
<para>We can now type exit or quit to leave the debugger, and we | |||
receive the following message: | |||
<programlisting> | |||
The application has exited. | |||
The application has exited. | |||
</programlisting></para> | |||
</example> | |||
@@ -274,22 +274,23 @@ | |||
your <literal>load-path</literal> and are ``required''. This is an | |||
example for the 1.0 release: | |||
<programlisting> | |||
;; I keep my emacs packages in C:/Emacs | |||
(setq load-path | |||
(append | |||
'( | |||
"C:/Emacs/aspectj-emacsMode-1.0" ; for AJDEE | |||
"C:/Emacs/aspectj-emacsAJDEE-1.0" | |||
"C:/Emacs/jde-2.2.9beta6/lisp" | |||
"C:/Emacs/elib-1.0" ; for JDEE | |||
"C:/Emacs/speedbar-0.14beta2" ; for JDEE | |||
"C:/Emacs/semantic-1.4beta12" ; for JDEE/speedbar | |||
"C:/Emacs/eieio-0.17beta3" ; for JDEE | |||
) | |||
load-path)) | |||
(require 'jde) | |||
(require 'ajdee) ; can also appear in prj.el</programlisting> | |||
;; I keep my emacs packages in C:/Emacs | |||
(setq load-path | |||
(append | |||
'( | |||
"C:/Emacs/aspectj-emacsMode-1.0" ; for AJDEE | |||
"C:/Emacs/aspectj-emacsAJDEE-1.0" | |||
"C:/Emacs/jde-2.2.9beta6/lisp" | |||
"C:/Emacs/elib-1.0" ; for JDEE | |||
"C:/Emacs/speedbar-0.14beta2" ; for JDEE | |||
"C:/Emacs/semantic-1.4beta12" ; for JDEE/speedbar | |||
"C:/Emacs/eieio-0.17beta3" ; for JDEE | |||
) | |||
load-path)) | |||
(require 'jde) | |||
(require 'ajdee) ; can also appear in prj.el | |||
</programlisting> | |||
</para> | |||
</listitem> | |||
@@ -315,31 +316,33 @@ | |||
Here is a simple example: | |||
<programlisting> | |||
;; A default version for simple projects, maybe good for | |||
;;; .emacs file. | |||
(custom-set-variables | |||
'(jde-compiler '("ajc" "ajc")) | |||
'(jde-javadoc-command-path "ajdoc") | |||
;; A default version for simple projects, maybe good for | |||
;;; .emacs file. | |||
(custom-set-variables | |||
'(jde-compiler '("ajc" "ajc")) | |||
'(jde-javadoc-command-path "ajdoc") | |||
;; ajc requires all files to be named for a compile | |||
'(aspectj-compile-file-specification "*.java"))</programlisting> | |||
;; ajc requires all files to be named for a compile | |||
'(aspectj-compile-file-specification "*.java")) | |||
</programlisting> | |||
Here is an example for spacewar, in | |||
<filename>examples/spacewar</filename>. | |||
<programlisting> | |||
;;; These options are for the spacewar, in examples/spacewar. | |||
(custom-set-variables | |||
'(jde-compiler '("ajc" "ajc")) | |||
'(jde-javadoc-command-path "ajdoc") | |||
;; ajc provides an ``argfile'' mechanism for specifying all files. | |||
'(aspectj-compile-file-specification "-argfile demo.lst") | |||
;; *if* compiling packages, name root dir for package hierarchy | |||
;; to tell ajc where .class files should go. | |||
'(jde-compile-option-directory "..") | |||
'(jde-run-working-directory "..")) | |||
'(jde-run-application-class "spacewar.Game")</programlisting> | |||
;;; These options are for the spacewar, in examples/spacewar. | |||
(custom-set-variables | |||
'(jde-compiler '("ajc" "ajc")) | |||
'(jde-javadoc-command-path "ajdoc") | |||
;; ajc provides an ``argfile'' mechanism for specifying all files. | |||
'(aspectj-compile-file-specification "-argfile demo.lst") | |||
;; *if* compiling packages, name root dir for package hierarchy | |||
;; to tell ajc where .class files should go. | |||
'(jde-compile-option-directory "..") | |||
'(jde-run-working-directory "..")) | |||
'(jde-run-application-class "spacewar.Game") | |||
</programlisting> | |||
</para> | |||
</listitem> | |||
<listitem> |
@@ -118,7 +118,7 @@ | |||
<entry>M-x aspectj-jump-menu (C-x C-j)</entry> | |||
<entry> | |||
Display popup menu of advisers, advisees, and inter-type declarations. | |||
Navigate to item by selecting with mouse | |||
Navigate to item by selecting with mouse | |||
(see <link linkend="aspectjmodescreenshot2">figure</link> below). | |||
</entry> | |||
</row> | |||
@@ -208,9 +208,10 @@ | |||
The files in this package need to be in the load-path and | |||
``required''. For example, for the 1.0 release: | |||
<programlisting> | |||
;; I keep my emacs packages in C:/Emacs | |||
(setq load-path (cons "C:/Emacs/aspectj-emacsMode-1.0" load-path)) | |||
(require 'aspectj-mode)</programlisting> | |||
;; I keep my emacs packages in C:/Emacs | |||
(setq load-path (cons "C:/Emacs/aspectj-emacsMode-1.0" load-path)) | |||
(require 'aspectj-mode) | |||
</programlisting> | |||
</para> | |||
</listitem> | |||
@@ -329,17 +330,17 @@ Error in init file: File error: "Cannot open load file", "aspectj-mode" | |||
<listitem> | |||
<para><emphasis>Symptom</emphasis>: When trying to get a jump menu, | |||
I get the message "No crosscut elements at point" even though | |||
I get the message "No crosscut elements at point" even though | |||
there is a [list] on the same line. | |||
</para> | |||
<para>The caret (point) is probably on or after the list. | |||
To see the crosscut elements you need to hit the jump menu | |||
on the same line that the annotated elements appear as a list | |||
of items surrounded by '[' and ']' on the same line as the | |||
affected declaration. If the caret is on the same line as the | |||
elements and before the list (i.e. not at the end of the | |||
list of elements) the jump menu should work. | |||
To see the crosscut elements you need to hit the jump menu | |||
on the same line that the annotated elements appear as a list | |||
of items surrounded by '[' and ']' on the same line as the | |||
affected declaration. If the caret is on the same line as the | |||
elements and before the list (i.e. not at the end of the | |||
list of elements) the jump menu should work. | |||
</para> | |||
</listitem> | |||
</itemizedlist> |
@@ -146,54 +146,53 @@ | |||
may define abstract pointcuts (but not abstract | |||
methods). The following example shows a simple aop.xml file: </para> | |||
<programlisting><![CDATA[ | |||
<aspectj> | |||
<aspects> | |||
<!-- declare two existing aspects to the weaver --> | |||
<aspect name="com.MyAspect"/> | |||
<aspect name="com.MyAspect.Inner"/> | |||
<!-- define a concrete aspect inline --> | |||
<concrete-aspect name="com.xyz.tracing.MyTracing" | |||
extends="tracing.AbstractTracing" | |||
precedence="com.xyz.first, *"> | |||
<pointcut name="tracingScope" expression="within(org.maw.*)"/> | |||
</concrete-aspect> | |||
<!-- Of the set of aspects declared to the weaver | |||
use aspects matching the type pattern "com..*" for weaving. --> | |||
<include within="com..*"/> | |||
<!-- Of the set of aspects declared to the weaver | |||
do not use any aspects with the @CoolAspect annotation for weaving --> | |||
<exclude within="@CoolAspect *"/> | |||
</aspects> | |||
<weaver options="-verbose"> | |||
<!-- Weave types that are within the javax.* or org.aspectj.* | |||
packages. Also weave all types in the foo package that do | |||
not have the @NoWeave annotation. --> | |||
<include within="javax.*"/> | |||
<include within="org.aspectj.*"/> | |||
<include within="(!@NoWeave foo.*) AND foo.*"/> | |||
<!-- Do not weave types within the "bar" pakage --> | |||
<exclude within="bar.*"/> | |||
<!-- Dump all types within the "com.foo.bar" package | |||
to the "./_ajdump" folder on disk (for diagnostic purposes) --> | |||
<dump within="com.foo.bar.*"/> | |||
<!-- Dump all types within the "com.foo.bar" package and sub-packages, | |||
both before are after they are woven, | |||
which can be used for byte-code generated at runtime | |||
<dump within="com.foo.bar..*" beforeandafter="true"/> | |||
</weaver> | |||
</aspectj> | |||
]]></programlisting> | |||
<aspectj> | |||
<aspects> | |||
<!-- declare two existing aspects to the weaver --> | |||
<aspect name="com.MyAspect"/> | |||
<aspect name="com.MyAspect.Inner"/> | |||
<!-- define a concrete aspect inline --> | |||
<concrete-aspect name="com.xyz.tracing.MyTracing" | |||
extends="tracing.AbstractTracing" | |||
precedence="com.xyz.first, *"> | |||
<pointcut name="tracingScope" expression="within(org.maw.*)"/> | |||
</concrete-aspect> | |||
<!-- Of the set of aspects declared to the weaver | |||
use aspects matching the type pattern "com..*" for weaving. --> | |||
<include within="com..*"/> | |||
<!-- Of the set of aspects declared to the weaver | |||
do not use any aspects with the @CoolAspect annotation for weaving --> | |||
<exclude within="@CoolAspect *"/> | |||
</aspects> | |||
<weaver options="-verbose"> | |||
<!-- Weave types that are within the javax.* or org.aspectj.* | |||
packages. Also weave all types in the foo package that do | |||
not have the @NoWeave annotation. --> | |||
<include within="javax.*"/> | |||
<include within="org.aspectj.*"/> | |||
<include within="(!@NoWeave foo.*) AND foo.*"/> | |||
<!-- Do not weave types within the "bar" pakage --> | |||
<exclude within="bar.*"/> | |||
<!-- Dump all types within the "com.foo.bar" package | |||
to the "./_ajdump" folder on disk (for diagnostic purposes) --> | |||
<dump within="com.foo.bar.*"/> | |||
<!-- Dump all types within the "com.foo.bar" package and sub-packages, | |||
both before are after they are woven, | |||
which can be used for byte-code generated at runtime | |||
<dump within="com.foo.bar..*" beforeandafter="true"/> | |||
</weaver> | |||
</aspectj> | |||
]]></programlisting> | |||
<para> | |||
The DTD defining the format of this file is available here: | |||
@@ -301,37 +300,37 @@ | |||
Consider the following: | |||
</para> | |||
<programlisting><![CDATA[ | |||
package mypack; | |||
package mypack; | |||
@Aspect | |||
public abstract class AbstractAspect { | |||
@Aspect | |||
public abstract class AbstractAspect { | |||
// abstract pointcut: no expression is defined | |||
@Pointcut | |||
abstract void scope(); | |||
// abstract pointcut: no expression is defined | |||
@Pointcut | |||
abstract void scope(); | |||
@Before("scope() && execution(* *..doSome(..))") | |||
public void before(JoinPoint jp) { | |||
.... | |||
} | |||
} | |||
]]></programlisting> | |||
@Before("scope() && execution(* *..doSome(..))") | |||
public void before(JoinPoint jp) { | |||
.... | |||
} | |||
} | |||
]]></programlisting> | |||
<para> | |||
This aspect is equivalent to the following in code style: | |||
</para> | |||
<programlisting><![CDATA[ | |||
package mypack; | |||
package mypack; | |||
public abstract aspect AbstractAspect { | |||
public abstract aspect AbstractAspect { | |||
// abstract pointcut: no expression is defined | |||
abstract pointcut scope(); | |||
// abstract pointcut: no expression is defined | |||
abstract pointcut scope(); | |||
before() : scope() && execution(* *..doSome(..)) { | |||
.... | |||
} | |||
} | |||
]]></programlisting> | |||
before() : scope() && execution(* *..doSome(..)) { | |||
.... | |||
} | |||
} | |||
]]></programlisting> | |||
<para> | |||
This aspect (in either style) can be made concrete using <literal>META-INF/aop.xml</literal>. | |||
It defines the abstract pointcut <literal>scope()</literal>. When using this mechanism the | |||
@@ -361,14 +360,14 @@ | |||
The following XML definition shows a valid concrete sub-aspect for the abstract aspects above: | |||
</para> | |||
<programlisting><![CDATA[ | |||
<aspectj> | |||
<aspects> | |||
<concrete-aspect name="mypack.__My__AbstractAspect" extends="mypack.AbstractAspect"> | |||
<pointcut name="scope" expression="within(yourpackage..*)"/> | |||
</concrete-aspect> | |||
<aspects> | |||
</aspectj> | |||
]]></programlisting> | |||
<aspectj> | |||
<aspects> | |||
<concrete-aspect name="mypack.__My__AbstractAspect" extends="mypack.AbstractAspect"> | |||
<pointcut name="scope" expression="within(yourpackage..*)"/> | |||
</concrete-aspect> | |||
<aspects> | |||
</aspectj> | |||
]]></programlisting> | |||
<para> | |||
It is important to remember that the <literal>name</literal> attribute in the | |||
<literal>concrete-aspect</literal> directive defines the fully qualified name that will be given to the | |||
@@ -381,12 +380,12 @@ | |||
as in: | |||
</para> | |||
<programlisting><![CDATA[ | |||
// exception handling omitted | |||
Class myConcreteAspectClass = Class.forName("mypack.__My__AbstractAspect"); | |||
// exception handling omitted | |||
Class myConcreteAspectClass = Class.forName("mypack.__My__AbstractAspect"); | |||
// here we are using a singleton aspect | |||
AbstractAspect concreteInstance = Aspects.aspectOf(myConcreteAspectClass); | |||
]]></programlisting> | |||
// here we are using a singleton aspect | |||
AbstractAspect concreteInstance = Aspects.aspectOf(myConcreteAspectClass); | |||
]]></programlisting> | |||
</sect2> | |||
<sect2 id="concrete-aspect-precedence" xreflabel="concrete-aspect-precedence"> | |||
@@ -406,13 +405,13 @@ | |||
Consider the following: | |||
</para> | |||
<programlisting><![CDATA[ | |||
<aspectj> | |||
<aspects> | |||
<concrete-aspect name="mypack.__MyDeclarePrecedence" | |||
precedence="*..*Security*, Logging+, *"/> | |||
</aspects> | |||
</aspectj> | |||
]]></programlisting> | |||
<aspectj> | |||
<aspects> | |||
<concrete-aspect name="mypack.__MyDeclarePrecedence" | |||
precedence="*..*Security*, Logging+, *"/> | |||
</aspects> | |||
</aspectj> | |||
]]></programlisting> | |||
<para> | |||
This deployment time definitions is only declaring a precedence rule. You have to remember | |||
that the <literal>name</literal> attribute must be a valid fully qualified class name | |||
@@ -430,13 +429,13 @@ | |||
search path. Everything that can be configured through XML can be configured using a | |||
Properties file, with the exception of declarative concrete aspects. For example: </para> | |||
<programlisting><![CDATA[ | |||
aspects.names=com.MyAspect,com.MyAspect.Inner | |||
aspects.include=com..* | |||
aspects.exclude=@CoolAspect | |||
aspects.names=com.MyAspect,com.MyAspect.Inner | |||
aspects.include=com..* | |||
aspects.exclude=@CoolAspect | |||
weaver.options=-verbose | |||
weaver.include=javax.* OR org.aspectj.* | |||
]]></programlisting> | |||
weaver.options=-verbose | |||
weaver.include=javax.* OR org.aspectj.* | |||
]]></programlisting> | |||
</sect2> | |||
--> | |||
@@ -594,8 +593,8 @@ | |||
<para> When using Java 5 the JVMTI agent can be used by starting the JVM with the | |||
following option (adapt according to the path to aspectjweaver.jar): </para> | |||
<programlisting><![CDATA[ | |||
-javaagent:pathto/aspectjweaver.jar | |||
]]></programlisting> | |||
-javaagent:pathto/aspectjweaver.jar | |||
]]></programlisting> | |||
</sect2> | |||
<sect2 id="jrockit" xreflabel="jrockit"> | |||
<title>JRockit with Java 1.3/1.4 (use JVMTI on Java 5)</title> |
@@ -1,26 +1,26 @@ | |||
<chapter id="ajcore" xreflabel="AspectJ Core Files"> | |||
<title>AspectJ Core Files</title> | |||
<sect1 id="ajcore-introduction"> | |||
<title>Introduction</title> | |||
<para> When the compiler terminates abnormally, either because a particular kind of message was | |||
issued or an exception was thrown, an AspectJ core file will be produced. You will | |||
find it the working directory of the compiler and it will have a name that contains | |||
the date and time that the file was produced | |||
the date and time that the file was produced | |||
e.g. <literal>ajcore.20060810.173655.626.txt</literal>. The file contains details | |||
of the problem such as the exception thrown as well as information about the | |||
environment such as operating system and Java version. When submitting a bug, | |||
include this file whenever it is available.</para> | |||
<sect2 id="configuration" xreflabel="configuration"> | |||
<title>Configuring dump files</title> | |||
<para> By default AspectJ will only create an <literal>ajcore</literal> file | |||
when an unexpected exception is thrown by the weaver or an | |||
<para> By default AspectJ will only create an <literal>ajcore</literal> file | |||
when an unexpected exception is thrown by the weaver or an | |||
<literal>abort</literal> message is | |||
issued. However it is possible to disable this feature or enable files to | |||
be produced under different circumstances. The table below lists the System | |||
be produced under different circumstances. The table below lists the System | |||
properties that can be used to configure <literal>ajcore</literal> files. </para> | |||
<informaltable> | |||
<tgroup cols="3"> | |||
@@ -52,7 +52,7 @@ | |||
</entry> | |||
<entry> | |||
Message kind for which to generate <literal>ajcore</literal> | |||
e.g. <literal>error</literal>. | |||
e.g. <literal>error</literal>. | |||
</entry> | |||
</row> | |||
<row> | |||
@@ -63,7 +63,7 @@ | |||
<literal>none</literal> | |||
</entry> | |||
<entry> | |||
The directory used for ajcore files. | |||
The directory used for ajcore files. | |||
</entry> | |||
</row> | |||
</tbody> | |||
@@ -73,7 +73,7 @@ | |||
<sect2 id="ajcore-examples" xreflabel="AJCore File Examples"> | |||
<title>AJCore File Examples</title> | |||
<para> Below is an extract from an <literal>ajcore</literal> file. You will see | |||
details of the dump configuration as well as the exception (with stack trace) that | |||
is the source of the problem and any messages issued by the compiler. Most importantly | |||
@@ -191,8 +191,8 @@ java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory | |||
at org.aspectj.tools.ajc.Main.run(Main.java:367) | |||
at org.aspectj.tools.ajc.Main.runMain(Main.java:246) | |||
at org.aspectj.tools.ajc.Main.main(Main.java:86) | |||
]]></programlisting> | |||
]]> </programlisting> | |||
</sect2> | |||
</sect1> | |||
</chapter> |
@@ -1,55 +1,55 @@ | |||
<chapter id="ltwdump" xreflabel="Dumping classes during load-time weaving"> | |||
<title>Dumping classes during load-time weaving</title> | |||
<sect1 id="ltwdump-introduction"> | |||
<title>Introduction</title> | |||
<para> | |||
Very rarely problems may be encountered with classes that have been | |||
<para> | |||
Very rarely problems may be encountered with classes that have been | |||
load-time woven. | |||
Symptoms will include incorrect program function or a Java exception such as | |||
Symptoms will include incorrect program function or a Java exception such as | |||
<literal>java.lang.VerifyError</literal>. | |||
In these situations it's most helpful to include the offending class | |||
in the bug report. When using load-time weaving the woven classes are | |||
In these situations it's most helpful to include the offending class | |||
in the bug report. When using load-time weaving the woven classes are | |||
in memory only so to save them to disk configure | |||
<literal>META-INF/aop.xml</literal> to dump the classes (by default | |||
to an <literal>_ajdump</literal> subdirectory of the current working | |||
directory). Also if the input class file is not available | |||
<literal>META-INF/aop.xml</literal> to dump the classes (by default | |||
to an <literal>_ajdump</literal> subdirectory of the current working | |||
directory). Also if the input class file is not available | |||
(e.g. it is a generated proxy or has already been instrumented by another agent) | |||
you can configure the weaver to dump the input classes as well. | |||
</para> | |||
<sect2 id="ltw-examples" xreflabel="ltwdump-configuration"> | |||
<title>Configuring bytecode dumping in load-time weaving</title> | |||
<para> | |||
For details of how to configure byte-code dumping, see the | |||
AspectJ Development Environment Guide section on | |||
For details of how to configure byte-code dumping, see the | |||
AspectJ Development Environment Guide section on | |||
<ulink url="../devguide/ltw-configuration.html#configuring-load-time-weaving-with-aopxml-files"> | |||
Configuring Load-time Weaving</ulink>. | |||
Configuring Load-time Weaving</ulink>. | |||
Following is a simple example. | |||
</para> | |||
</sect2> | |||
<sect2 id="ltwdump-examples" xreflabel="LTW Dump Examples"> | |||
<title>LTW Dump Examples</title> | |||
<para> The following <literal>META-INF/aop.xml</literal> will | |||
<para> The following <literal>META-INF/aop.xml</literal> will | |||
weave classes in the <literal>com.foo</literal> package (and subpackages) but not | |||
CGLIB generated classes in the <literal>com.foo.bar</literal> package (and subpackages). | |||
CGLIB generated classes in the <literal>com.foo.bar</literal> package (and subpackages). | |||
It will also ensure all | |||
woven byte-code is dumped both before and after weaving. </para> | |||
<programlisting><![CDATA[ | |||
<aspectj> | |||
<aspects> | |||
<aspect name="ataspectj.EmptyAspect"/> | |||
</aspects> | |||
<weaver options="-verbose -debug"> | |||
<dump within="com.foo.bar..*" beforeandafter="true"/> | |||
<include within="com.foo..*"/> | |||
<exclude within="com.foo.bar..*CGLIB*"/> | |||
</weaver> | |||
</aspectj> | |||
]]></programlisting> | |||
<aspectj> | |||
<aspects> | |||
<aspect name="ataspectj.EmptyAspect"/> | |||
</aspects> | |||
<weaver options="-verbose -debug"> | |||
<dump within="com.foo.bar..*" beforeandafter="true"/> | |||
<include within="com.foo..*"/> | |||
<exclude within="com.foo.bar..*CGLIB*"/> | |||
</weaver> | |||
</aspectj> | |||
]]></programlisting> | |||
<para> You should see messages similar to this: </para> | |||
<programlisting><![CDATA[ | |||
@@ -59,15 +59,15 @@ | |||
[WeavingURLClassLoader] info register aspect ataspectj.EmptyAspect | |||
[WeavingURLClassLoader] debug not weaving 'com.foo.bar.Test$$EnhancerByCGLIB$$12345' | |||
[WeavingURLClassLoader] debug weaving 'com.foo.bar.Test' | |||
]]></programlisting> | |||
]]></programlisting> | |||
<para> On disk you would find the following files: </para> | |||
<programlisting><![CDATA[ | |||
_ajdump/_before/com/foo/bar/Test.class | |||
_ajdump/com/foo/bar/Test.class | |||
]]></programlisting> | |||
_ajdump/_before/com/foo/bar/Test.class | |||
_ajdump/com/foo/bar/Test.class | |||
]]></programlisting> | |||
</sect2> | |||
</sect1> | |||
</chapter> |
@@ -1,6 +1,6 @@ | |||
<chapter id="messages" xreflabel="Messages"> | |||
<title>Messages</title> | |||
<sect1 id="messages-introduction"> | |||
<title>Introduction</title> | |||
<para> | |||
@@ -11,47 +11,47 @@ | |||
which are hidden. However, when investigating | |||
unexpected behavior it's helpful to show them. This section describes how | |||
to configure messages, presents some problem scenarios when | |||
compiling or doing load-time weaving, and summarizes some of the | |||
compiling or doing load-time weaving, and summarizes some of the | |||
more relevant messages. | |||
</para> | |||
<sect2 id="messages-introduction-config" | |||
<sect2 id="messages-introduction-config" | |||
xreflabel="messages-configuration"> | |||
<title>Configuring Messages</title> | |||
<para> | |||
The compiler offers <literal>-verbose</literal>, | |||
<literal>-warning</literal>, and <literal>-XLint</literal> options | |||
when invoked using the command-line, Ant, or embedded in an IDE. | |||
All options are listed in the AspectJ Development Environment Guide | |||
sections for | |||
<ulink url="../devguide/ajc-ref.html">Ajc</ulink> and | |||
The compiler offers <literal>-verbose</literal>, | |||
<literal>-warning</literal>, and <literal>-XLint</literal> options | |||
when invoked using the command-line, Ant, or embedded in an IDE. | |||
All options are listed in the AspectJ Development Environment Guide | |||
sections for | |||
<ulink url="../devguide/ajc-ref.html">Ajc</ulink> and | |||
<ulink url="../devguide/antTasks-iajc.html">Ant Tasks</ulink>. | |||
The <ulink url="../devguide/ltw.html">Load-time Weaving</ulink> | |||
The <ulink url="../devguide/ltw.html">Load-time Weaving</ulink> | |||
section describes how to use XML configuration files and | |||
system properties to pass options to the weaver. (You can also | |||
pass options to the weaver using system properties in build- | |||
time weaving.) | |||
time weaving.) | |||
The <literal>-verbose</literal> option has the effect of including | |||
messages level "info", which are normally ignored. | |||
Both <literal>warning</literal> and <literal>XLint</literal> | |||
enable you to identify specific messages to emit, but warning | |||
messages tend to be the same provided by the underlying Eclipse | |||
JDT (Java) compiler, while XLint messages are emitted by the | |||
enable you to identify specific messages to emit, but warning | |||
messages tend to be the same provided by the underlying Eclipse | |||
JDT (Java) compiler, while XLint messages are emitted by the | |||
AspectJ compiler or weaver. Obviously, during load-time weaving | |||
only weaver messages will be emitted. Similarly, if aspects | |||
are compiled but not woven, then only compiler messages will be | |||
emitted. However, the usual case for the compiler/weaver working | |||
at build time is to emit both compiler and weaver messages. | |||
</para> | |||
<para> The tables below list some options, System Properties (for LTW only) and Java 5 annotations | |||
<para> The tables below list some options, System Properties (for LTW only) and Java 5 annotations | |||
used to control AspectJ messages. The method | |||
of configuration depends on your environment so please refer to the relevant | |||
documentation for | |||
<ulink url="../devguide/ajc-ref.html">ajc</ulink>, | |||
<ulink url="../devguide/antTasks.html">Ant</ulink> or | |||
<ulink url="../devguide/ltw-configuration.html#weaver-options">LTW</ulink>. | |||
of configuration depends on your environment so please refer to the relevant | |||
documentation for | |||
<ulink url="../devguide/ajc-ref.html">ajc</ulink>, | |||
<ulink url="../devguide/antTasks.html">Ant</ulink> or | |||
<ulink url="../devguide/ltw-configuration.html#weaver-options">LTW</ulink>. | |||
</para> | |||
<para> | |||
<informaltable> | |||
<tgroup cols="2"> | |||
@@ -105,15 +105,15 @@ | |||
</entry> | |||
<entry> | |||
In Ant tasks and LTW respectively specify the class to receive all messages. | |||
See | |||
See | |||
<ulink url="../devguide/antTasks-iajc.html#antTasks-iajc-options"> | |||
iajc task options</ulink> or | |||
<ulink url="../devguide/ltw-configuration.html#weaver-options"> | |||
Weaver Options</ulink>. | |||
</entry> | |||
</row> | |||
<!-- We need full javadoc for this API | |||
<!-- We need full javadoc for this API | |||
<row> | |||
<entry> | |||
<literal>org.aspectj.tools.Main.setMessageHolder(..)</literal> | |||
@@ -123,7 +123,7 @@ | |||
outside of Ant. | |||
</entry> | |||
</row> | |||
--> | |||
--> | |||
</tbody> | |||
</tgroup> | |||
</informaltable> | |||
@@ -144,7 +144,7 @@ | |||
<literal>aj.weaving.verbose</literal> | |||
</entry> | |||
<entry> | |||
Show informational messages including AspectJ version and build date | |||
Show informational messages including AspectJ version and build date | |||
(same as <literal>-verbose</literal> option). | |||
</entry> | |||
</row> | |||
@@ -162,7 +162,7 @@ | |||
<literal>org.aspectj.weaving.messages</literal> | |||
</entry> | |||
<entry> | |||
Set this system property to enable tracing of all compiler | |||
Set this system property to enable tracing of all compiler | |||
messages. See <xref linkend="trace-configuration"/>. | |||
</entry> | |||
</row> | |||
@@ -170,7 +170,7 @@ | |||
</tgroup> | |||
</informaltable> | |||
</para> | |||
<para> | |||
<informaltable> | |||
<tgroup cols="2"> | |||
@@ -194,39 +194,39 @@ | |||
</tgroup> | |||
</informaltable> | |||
</para> | |||
</sect2> | |||
</sect1> | |||
</sect2> | |||
</sect1> | |||
<sect1 id="messages-scenarios"> | |||
<title>Message scenarios</title> | |||
<sect2 id="messages-scenarios-ct"> | |||
<title>Compile-time weaving scenarios</title> | |||
<sect3 id="messages-scenarios-ct-adviceNotWoven"> | |||
<title>Advice not woven</title> | |||
<para>This means that the pointcut for the advice did not match, | |||
and it should be debugged as described in | |||
and it should be debugged as described in | |||
<xref linkend="pointcuts"/>.</para> | |||
</sect3> | |||
</sect2> | |||
<sect2 id="messages-scenarios-ltw"> | |||
<title>Load-time weaving scenarios</title> | |||
<para> You can use <literal>META-INF/aop.xml</literal> to control which | |||
messages are produced during LTW. The following example will produce | |||
basic informational messages about the lifecyle of the weaver in | |||
addition to any warning or error messages. </para> | |||
<programlisting><![CDATA[ | |||
<aspectj> | |||
<weaver options="-verbose"> | |||
</weaver> | |||
</aspectj> | |||
]]></programlisting> | |||
<para>The messages indicate which <literal>META-INF/aop.xml</literal> | |||
configurations file(s) are being used. Each message is also preceeded by the | |||
<aspectj> | |||
<weaver options="-verbose"> | |||
</weaver> | |||
</aspectj> | |||
]]></programlisting> | |||
<para>The messages indicate which <literal>META-INF/aop.xml</literal> | |||
configurations file(s) are being used. Each message is also preceeded by the | |||
name of the defining class loader associated with weaver. You can use this | |||
information in a large system to distinguish between different applications each | |||
of which will typically have its own class loader. </para> | |||
@@ -238,25 +238,25 @@ | |||
[AppClassLoader@92e78c] info using configuration /C:/temp/META-INF/aop-ajc.xml | |||
[AppClassLoader@92e78c] info register aspect ExceptionHandler | |||
[AppClassLoader@92e78c] info processing reweavable type ExceptionHandler: ExceptionHandler.aj | |||
]]></programlisting> | |||
]]></programlisting> | |||
<sect3 id="messages-scenarios-ltw-adviceNotWoven"> | |||
<title>Advice not woven</title> | |||
<para> It is often difficult to determine, especially when using load-time weaving (LTW), | |||
why advice has not been woven. Here is a quick guide to the messages to | |||
look for. Firstly if you use the <literal>-verbose</literal> option you | |||
look for. Firstly if you use the <literal>-verbose</literal> option you | |||
should see the following message when your aspect is registered: </para> | |||
<programlisting><![CDATA[ | |||
info register aspect MyAspect | |||
]]></programlisting> | |||
info register aspect MyAspect | |||
]]></programlisting> | |||
<para> Secondly if you use the <literal>-debug</literal> option you should | |||
<para> Secondly if you use the <literal>-debug</literal> option you should | |||
see a message indicating that you class is being woven: </para> | |||
<programlisting><![CDATA[ | |||
debug weaving 'HelloWorld' | |||
]]></programlisting> | |||
debug weaving 'HelloWorld' | |||
]]></programlisting> | |||
<para> However this does not mean that advice has actually been woven into | |||
your class; it says that the class has been passed to the weaver. To determine | |||
@@ -264,18 +264,18 @@ | |||
option which will cause a message to be issued each time a join point is woven: </para> | |||
<programlisting><![CDATA[ | |||
weaveinfo Join point 'method-execution(void HelloWorld.main(java.lang.String[]))' ... | |||
]]></programlisting> | |||
<para>If advice is woven at this join point you should get the | |||
weaveinfo Join point 'method-execution(void HelloWorld.main(java.lang.String[]))' ... | |||
]]></programlisting> | |||
<para>If advice is woven at this join point you should get the | |||
corresponding message.</para> | |||
</sect3> | |||
</sect2> | |||
</sect1> | |||
<sect1 id="messages-xlint"> | |||
<title>Lint messages</title> | |||
<para> | |||
<para> | |||
The table below lists some useful <literal>-Xlint</literal> messages. </para> | |||
<informaltable> | |||
<tgroup cols="3"> | |||
@@ -297,8 +297,8 @@ | |||
<entry> | |||
If an aspect is not being woven, despite being | |||
registered, it could be that it has been excluded | |||
by either an <literal>include</literal> or <literal>exclude</literal> | |||
element in the | |||
by either an <literal>include</literal> or <literal>exclude</literal> | |||
element in the | |||
<literal>aspects</literal> section of <literal>META-INF/aop.xml</literal>. | |||
Enable this message to determine whether an aspect has | |||
been excluded. | |||
@@ -314,7 +314,7 @@ | |||
<entry> | |||
Issued when advice did not potentially affect any join points. | |||
This means the corresponding pointcut did not match any join | |||
points in the program. This may be valid e.g., in library | |||
points in the program. This may be valid e.g., in library | |||
aspects or code picking up error conditions, but often the | |||
programmer simply made a mistake in the pointcut. The best | |||
approach is to debug the pointcut. | |||
@@ -356,7 +356,7 @@ | |||
</entry> | |||
<entry> | |||
Before AspectJ 5, declare soft used to soften runtime exceptions | |||
(unnecessarily). Since then, it does not but does issue this | |||
(unnecessarily). Since then, it does not but does issue this | |||
warning in case the programmer did intend for the exception | |||
to be wrapped. | |||
</entry> | |||
@@ -381,5 +381,5 @@ | |||
</tgroup> | |||
</informaltable> | |||
</sect1> | |||
</chapter> |
@@ -1,29 +1,29 @@ | |||
<chapter id="trace" xreflabel="Tracing"> | |||
<title>Tracing</title> | |||
<sect1 id="trace-introduction"> | |||
<title>Introduction</title> | |||
<para> | |||
<para> | |||
The AspectJ developers have instrumented the compiler/weaver with | |||
many "trace" messages for their own debugging use. These remain in | |||
the production releases because tracing helps when it is hard to | |||
the production releases because tracing helps when it is hard to | |||
isolate the problem in a test case. This sections describes how | |||
to enable tracing so you can provide trace information on bug reports. | |||
</para> | |||
<para> | |||
The usual approach to opening a report on Bugzilla is to describe the symptoms of the | |||
</para> | |||
<para> | |||
The usual approach to opening a report on Bugzilla is to describe the symptoms of the | |||
problem and attach a simple testcase. This allows the AspectJ team to try and reproduce the problem in | |||
an attempt to fix it as well as improve the test suite. Unfortunately it may not be possible | |||
to produce such a testcase either because your program is too large or is commercially sensitive. Alternatively | |||
to produce such a testcase either because your program is too large or is commercially sensitive. Alternatively | |||
the problem may relate to your specific environment where AspectJ is being used and will not be | |||
reproducible by the AspectJ team. In each of these situations you can produce a | |||
trace of the compiler when the problem occurs instead. This can then be attached to the bug report. </para> | |||
<sect2 id="trace-configuration" xreflabel="Configuring Tracing"> | |||
<title>Configuring Tracing</title> | |||
<para> When available (Java 5 or later) AspectJ will use the | |||
<para> When available (Java 5 or later) AspectJ will use the | |||
<ulink url="http://java.sun.com/j2se/1.5.0/docs/guide/logging/index.html"> | |||
java.util.logging</ulink> infrastructure | |||
configured using a <literal>logging.properties</literal> file. By default only error | |||
@@ -31,14 +31,14 @@ | |||
method entry and exit events can be obtained using the appropriate configuration. All | |||
regular compiler messages can also be logged through the infrastructure by setting the | |||
<literal>org.aspectj.weaving.messages</literal> System property. </para> | |||
<para> If you are running the AspectJ compiler/weaver under JDK 1.4 or earlier, | |||
<para> If you are running the AspectJ compiler/weaver under JDK 1.4 or earlier, | |||
AspectJ will use a simple built-in trace | |||
infrastructure that logs to stderr. This is enabled by setting the | |||
infrastructure that logs to stderr. This is enabled by setting the | |||
<literal>org.aspectj.weaving.tracing.enabled</literal> System property. You may also override | |||
the default behaviour or provide your own trace implementation using the | |||
<literal>org.aspectj.weaving.tracing.factory</literal> System property. </para> | |||
<para> The table below lists the System properties that can be used to configure tracing. </para> | |||
<informaltable> | |||
<tgroup cols="2"> | |||
@@ -73,10 +73,10 @@ | |||
</entry> | |||
<entry> | |||
Select trace infrastructure. Specify the fully qualified class name | |||
of the <literal>org.aspectj.weaver.tools.TraceFactory</literal> | |||
of the <literal>org.aspectj.weaver.tools.TraceFactory</literal> | |||
interface to use a custom infrastructure. Specify a value of | |||
<literal>default</literal> to force AspectJ to use it's | |||
built-in infrastructure. | |||
built-in infrastructure. | |||
</entry> | |||
</row> | |||
<row> | |||
@@ -97,68 +97,68 @@ | |||
<sect2 id="trace-examples" xreflabel="trace-examples"> | |||
<title>Examples</title> | |||
<para> Using <literal>-Dorg.aspectj.tracing.factory=default</literal> | |||
to force AspectJ to use its internal infrastructure, | |||
<literal>-Dorg.aspectj.tracing.enabled=true</literal> to turn it on and | |||
<literal>-Dorg.aspectj.tracing.enabled=true</literal> to turn it on and | |||
<literal>-Dorg.aspectj.tracing.messages=true</literal> to include messages | |||
running a simple HelloWorld with LTW will generate tracing to stderr. Below | |||
is an extract from that trace with method arguments removed. | |||
is an extract from that trace with method arguments removed. | |||
You will notice the millisecond time stamp, | |||
thread id and indication of entry/exit/event or message type for each line | |||
of trace. | |||
</para> | |||
<programlisting><![CDATA[ | |||
15:44:18.630 main > org.aspectj.weaver.loadtime.Aj.<init> | |||
15:44:18.630 main > org.aspectj.weaver.loadtime.Aj.<init> | |||
15:44:18.660 main < org.aspectj.weaver.loadtime.Aj.<init> | |||
15:44:18.660 main > org.aspectj.weaver.loadtime.Aj.preProcess | |||
15:44:18.660 main - org.aspectj.weaver.loadtime.Aj.preProcess | |||
15:44:18.730 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.<init> | |||
15:44:18.730 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.<init> | |||
15:44:18.730 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize | |||
15:44:18.730 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize | |||
15:44:18.821 main I [AppClassLoader@92e78c] info AspectJ Weaver Version DEVELOPMENT ... | |||
15:44:18.821 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:18.821 main I [AppClassLoader@92e78c] info register classloader ... | |||
15:44:18.821 main - org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:18.841 main - org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:18.821 main - org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:18.841 main - org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:18.841 main I [AppClassLoader@92e78c] info using configuration ... | |||
15:44:18.891 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:18.891 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions | |||
15:44:19.021 main > org.aspectj.weaver.World$TypeMap.<init> | |||
15:44:19.021 main < org.aspectj.weaver.World$TypeMap.<init> | |||
15:44:19.021 main > org.aspectj.weaver.CrosscuttingMembersSet.<init> | |||
15:44:19.021 main < org.aspectj.weaver.CrosscuttingMembersSet.<init> | |||
15:44:19.021 main > org.aspectj.weaver.Lint.<init> | |||
15:44:19.021 main < org.aspectj.weaver.Lint.<init> | |||
15:44:19.021 main > org.aspectj.weaver.World.<init> | |||
15:44:19.021 main > org.aspectj.weaver.World.<init> | |||
15:44:19.111 main < org.aspectj.weaver.World.<init> | |||
15:44:19.201 main > org.aspectj.weaver.bcel.BcelWeaver.<init> | |||
15:44:19.201 main > org.aspectj.weaver.bcel.BcelWeaver.<init> | |||
15:44:19.201 main < org.aspectj.weaver.bcel.BcelWeaver.<init> | |||
15:44:19.201 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerDefinitions | |||
15:44:19.211 main > org.aspectj.weaver.bcel.BcelWeaver.setReweavableMode | |||
15:44:19.201 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerDefinitions | |||
15:44:19.211 main > org.aspectj.weaver.bcel.BcelWeaver.setReweavableMode | |||
15:44:19.351 main < org.aspectj.weaver.bcel.BcelWeaver.setReweavableMode | |||
15:44:19.351 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerAspects | |||
15:44:19.351 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerAspects | |||
15:44:19.351 main I [AppClassLoader@92e78c] info register aspect Aspect | |||
15:44:19.351 main > org.aspectj.weaver.bcel.BcelWeaver.addLibraryAspect | |||
15:44:19.501 main - org.aspectj.weaver.bcel.BcelWorld.lookupJavaClass | |||
15:44:19.632 main > org.aspectj.weaver.CrosscuttingMembersSet.addOrReplaceAspect | |||
15:44:19.792 main < org.aspectj.weaver.CrosscuttingMembersSet.addOrReplaceAspect | |||
15:44:19.792 main < org.aspectj.weaver.bcel.BcelWeaver.addLibraryAspect | |||
15:44:19.792 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerAspects | |||
15:44:19.792 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerDefinitions | |||
15:44:19.792 main > org.aspectj.weaver.bcel.BcelWeaver.prepareForWeave | |||
15:44:19.351 main > org.aspectj.weaver.bcel.BcelWeaver.addLibraryAspect | |||
15:44:19.501 main - org.aspectj.weaver.bcel.BcelWorld.lookupJavaClass | |||
15:44:19.632 main > org.aspectj.weaver.CrosscuttingMembersSet.addOrReplaceAspect | |||
15:44:19.792 main < org.aspectj.weaver.CrosscuttingMembersSet.addOrReplaceAspect | |||
15:44:19.792 main < org.aspectj.weaver.bcel.BcelWeaver.addLibraryAspect | |||
15:44:19.792 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerAspects | |||
15:44:19.792 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.registerDefinitions | |||
15:44:19.792 main > org.aspectj.weaver.bcel.BcelWeaver.prepareForWeave | |||
15:44:19.822 main < org.aspectj.weaver.bcel.BcelWeaver.prepareForWeave | |||
15:44:19.822 main > org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.weaveAndDefineConcete... | |||
15:44:19.822 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.weaveAndDefineConcete... | |||
15:44:19.822 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize | |||
15:44:19.822 main > org.aspectj.weaver.tools.WeavingAdaptor.weaveClass | |||
... | |||
]]></programlisting> | |||
15:44:19.822 main < org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize | |||
15:44:19.822 main > org.aspectj.weaver.tools.WeavingAdaptor.weaveClass | |||
... | |||
]]></programlisting> | |||
<para> Alternatively when running under Java 5 the <literal>logging.properties</literal> | |||
file below could be used to configure Java Logging. The resulting | |||
file, just containing trace for the | |||
file, just containing trace for the | |||
<literal>org.aspectj.weaver.loadtime</literal> package, will be | |||
written to <literal>java0.log</literal> in your <literal>user.home</literal> directory. | |||
written to <literal>java0.log</literal> in your <literal>user.home</literal> directory. | |||
</para> | |||
<programlisting><![CDATA[ | |||
@@ -172,15 +172,15 @@ java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter | |||
java.util.logging.FileHandler.level = FINER | |||
org.aspectj.weaver.loadtime.level = FINER | |||
]]></programlisting> | |||
<para> | |||
]]></programlisting> | |||
<para> | |||
By setting the System property <literal>-Dorg.aspectj.tracing.debug=true</literal> | |||
you should see a message confirming which trace infrastructure is being used. | |||
</para> | |||
<programlisting><![CDATA[ | |||
TraceFactory.instance=org.aspectj.weaver.tools.Jdk14TraceFactory@12dacd1 | |||
]]></programlisting> | |||
TraceFactory.instance=org.aspectj.weaver.tools.Jdk14TraceFactory@12dacd1 | |||
]]></programlisting> | |||
</sect2> | |||
</sect1> | |||
</chapter> |
@@ -541,14 +541,14 @@ public aspect ComparablePoint { | |||
</para> | |||
<para> | |||
The method <literal>Object.hashCode</literal> returns an | |||
The method <literal>Object.hashCode</literal> returns an | |||
integer, suitable for use as a hash table key. It is not required | |||
that two objects which are not equal (according to the | |||
that two objects which are not equal (according to the | |||
<literal>equals</literal> method) return different integer | |||
results from <literal>hashCode</literal> but it can | |||
improve performance when the integer is used as a key into a | |||
data structure. However, any two objects which are equal | |||
must return the same integer value from a call to | |||
improve performance when the integer is used as a key into a | |||
data structure. However, any two objects which are equal | |||
must return the same integer value from a call to | |||
<literal>hashCode</literal>. Since the default implementation | |||
of <literal>Object.equals</literal> returns <literal>true</literal> | |||
only when two objects are identical, we need to redefine both | |||
@@ -851,7 +851,7 @@ aspect TraceMyClasses { | |||
</para> | |||
<programlisting><![CDATA[ | |||
ajc -argfile tracing/tracev1.lst | |||
ajc -argfile tracing/tracev1.lst | |||
]]></programlisting> | |||
<para> | |||
@@ -969,7 +969,7 @@ public aspect TraceMyClasses extends Trace { | |||
</para> | |||
<programlisting><![CDATA[ | |||
ajc -argfile tracing/tracev2.lst | |||
ajc -argfile tracing/tracev2.lst | |||
]]></programlisting> | |||
<para> | |||
@@ -1099,7 +1099,7 @@ abstract aspect Trace { | |||
</para> | |||
<para> | |||
This example examines an aspect that makes Point objects into | |||
This example examines an aspect that makes Point objects into | |||
Java beans with bound properties. | |||
</para> | |||
@@ -1190,10 +1190,10 @@ class Point { | |||
<literal>Point</literal>'s "beanness". The first thing it does is | |||
privately declare that each <literal>Point</literal> has a | |||
<literal>support</literal> field that holds reference to an | |||
instance of <classname>PropertyChangeSupport</classname>. | |||
instance of <classname>PropertyChangeSupport</classname>. | |||
<programlisting><![CDATA[ | |||
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this); | |||
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this); | |||
]]></programlisting> | |||
The property change support object must be constructed with a | |||
@@ -1210,24 +1210,24 @@ class Point { | |||
which delegate the work to the property change support object: | |||
<programlisting><![CDATA[ | |||
public void Point.addPropertyChangeListener(PropertyChangeListener listener){ | |||
support.addPropertyChangeListener(listener); | |||
} | |||
public void Point.addPropertyChangeListener(String propertyName, | |||
PropertyChangeListener listener){ | |||
public void Point.addPropertyChangeListener(PropertyChangeListener listener){ | |||
support.addPropertyChangeListener(listener); | |||
} | |||
public void Point.addPropertyChangeListener(String propertyName, | |||
PropertyChangeListener listener){ | |||
support.addPropertyChangeListener(propertyName, listener); | |||
} | |||
public void Point.removePropertyChangeListener(String propertyName, | |||
PropertyChangeListener listener) { | |||
support.removePropertyChangeListener(propertyName, listener); | |||
} | |||
public void Point.removePropertyChangeListener(PropertyChangeListener listener) { | |||
support.removePropertyChangeListener(listener); | |||
} | |||
public void Point.hasListeners(String propertyName) { | |||
support.hasListeners(propertyName); | |||
} | |||
support.addPropertyChangeListener(propertyName, listener); | |||
} | |||
public void Point.removePropertyChangeListener(String propertyName, | |||
PropertyChangeListener listener) { | |||
support.removePropertyChangeListener(propertyName, listener); | |||
} | |||
public void Point.removePropertyChangeListener(PropertyChangeListener listener) { | |||
support.removePropertyChangeListener(listener); | |||
} | |||
public void Point.hasListeners(String propertyName) { | |||
support.hasListeners(propertyName); | |||
} | |||
]]></programlisting> | |||
</para> | |||
@@ -1237,7 +1237,7 @@ class Point { | |||
<classname>Serializable</classname> interface: | |||
<programlisting><![CDATA[ | |||
declare parents: Point implements Serializable; | |||
declare parents: Point implements Serializable; | |||
]]></programlisting> | |||
Implementing this interface in Java does not require any methods to | |||
@@ -1254,7 +1254,7 @@ class Point { | |||
<literal>Y</literal> properties, calls the original | |||
<literal>set</literal> method and then fires the appropriate | |||
property change event according to which set method was | |||
called. | |||
called. | |||
</para> | |||
<programlisting><![CDATA[ | |||
@@ -1323,33 +1323,33 @@ aspect BoundPoint { | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Demo implements PropertyChangeListener { | |||
class Demo implements PropertyChangeListener { | |||
static final String fileName = "test.tmp"; | |||
static final String fileName = "test.tmp"; | |||
public void propertyChange(PropertyChangeEvent e){ | |||
System.out.println("Property " + e.getPropertyName() + " changed from " + | |||
e.getOldValue() + " to " + e.getNewValue() ); | |||
} | |||
public static void main(String[] args){ | |||
Point p1 = new Point(); | |||
p1.addPropertyChangeListener(new Demo()); | |||
System.out.println("p1 =" + p1); | |||
p1.setRectangular(5,2); | |||
System.out.println("p1 =" + p1); | |||
p1.setX( 6 ); | |||
p1.setY( 3 ); | |||
System.out.println("p1 =" + p1); | |||
p1.offset(6,4); | |||
System.out.println("p1 =" + p1); | |||
save(p1, fileName); | |||
Point p2 = (Point) restore(fileName); | |||
System.out.println("Had: " + p1); | |||
System.out.println("Got: " + p2); | |||
} | |||
... | |||
public void propertyChange(PropertyChangeEvent e){ | |||
System.out.println("Property " + e.getPropertyName() + " changed from " + | |||
e.getOldValue() + " to " + e.getNewValue() ); | |||
} | |||
public static void main(String[] args){ | |||
Point p1 = new Point(); | |||
p1.addPropertyChangeListener(new Demo()); | |||
System.out.println("p1 =" + p1); | |||
p1.setRectangular(5,2); | |||
System.out.println("p1 =" + p1); | |||
p1.setX( 6 ); | |||
p1.setY( 3 ); | |||
System.out.println("p1 =" + p1); | |||
p1.offset(6,4); | |||
System.out.println("p1 =" + p1); | |||
save(p1, fileName); | |||
Point p2 = (Point) restore(fileName); | |||
System.out.println("Had: " + p1); | |||
System.out.println("Got: " + p2); | |||
} | |||
... | |||
} | |||
]]></programlisting> | |||
</sect3> | |||
@@ -1381,7 +1381,7 @@ java bean.Demo | |||
<para> | |||
This demo illustrates how the Subject/Observer design pattern can be | |||
coded with aspects. | |||
coded with aspects. | |||
</para> | |||
<para> | |||
@@ -1419,26 +1419,26 @@ java bean.Demo | |||
</para> | |||
<programlisting><![CDATA[ | |||
interface Subject { | |||
void addObserver(Observer obs); | |||
void removeObserver(Observer obs); | |||
Vector getObservers(); | |||
Object getData(); | |||
} | |||
interface Subject { | |||
void addObserver(Observer obs); | |||
void removeObserver(Observer obs); | |||
Vector getObservers(); | |||
Object getData(); | |||
} | |||
]]></programlisting> | |||
<para> | |||
<para> | |||
The <classname>Observer</classname> interface is just as simple, | |||
with methods to set and get <classname>Subject</classname> objects, | |||
and a method to call when the subject gets updated. | |||
</para> | |||
<programlisting><![CDATA[ | |||
interface Observer { | |||
void setSubject(Subject s); | |||
Subject getSubject(); | |||
void update(); | |||
} | |||
interface Observer { | |||
void setSubject(Subject s); | |||
Subject getSubject(); | |||
void update(); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1449,32 +1449,32 @@ java bean.Demo | |||
</para> | |||
<programlisting><![CDATA[ | |||
abstract aspect SubjectObserverProtocol { | |||
abstract aspect SubjectObserverProtocol { | |||
abstract pointcut stateChanges(Subject s); | |||
abstract pointcut stateChanges(Subject s); | |||
after(Subject s): stateChanges(s) { | |||
for (int i = 0; i < s.getObservers().size(); i++) { | |||
((Observer)s.getObservers().elementAt(i)).update(); | |||
} | |||
} | |||
after(Subject s): stateChanges(s) { | |||
for (int i = 0; i < s.getObservers().size(); i++) { | |||
((Observer)s.getObservers().elementAt(i)).update(); | |||
} | |||
} | |||
private Vector Subject.observers = new Vector(); | |||
public void Subject.addObserver(Observer obs) { | |||
observers.addElement(obs); | |||
obs.setSubject(this); | |||
} | |||
public void Subject.removeObserver(Observer obs) { | |||
observers.removeElement(obs); | |||
obs.setSubject(null); | |||
} | |||
public Vector Subject.getObservers() { return observers; } | |||
private Vector Subject.observers = new Vector(); | |||
public void Subject.addObserver(Observer obs) { | |||
observers.addElement(obs); | |||
obs.setSubject(this); | |||
} | |||
public void Subject.removeObserver(Observer obs) { | |||
observers.removeElement(obs); | |||
obs.setSubject(null); | |||
} | |||
public Vector Subject.getObservers() { return observers; } | |||
private Subject Observer.subject = null; | |||
public void Observer.setSubject(Subject s) { subject = s; } | |||
public Subject Observer.getSubject() { return subject; } | |||
private Subject Observer.subject = null; | |||
public void Observer.setSubject(Subject s) { subject = s; } | |||
public Subject Observer.getSubject() { return subject; } | |||
} | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1482,7 +1482,7 @@ java bean.Demo | |||
pointcut that extending aspects can override. It defines advice | |||
that should run after the join points of the pointcut. And it | |||
declares an inter-type field and two inter-type methods so that | |||
each <literal>Observer</literal> can hold onto its <literal>Subject</literal>. | |||
each <literal>Observer</literal> can hold onto its <literal>Subject</literal>. | |||
</para> | |||
</sect3> | |||
@@ -1497,28 +1497,28 @@ java bean.Demo | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Button extends java.awt.Button { | |||
static final Color defaultBackgroundColor = Color.gray; | |||
static final Color defaultForegroundColor = Color.black; | |||
static final String defaultText = "cycle color"; | |||
Button(Display display) { | |||
super(); | |||
setLabel(defaultText); | |||
setBackground(defaultBackgroundColor); | |||
setForeground(defaultForegroundColor); | |||
addActionListener(new ActionListener() { | |||
public void actionPerformed(ActionEvent e) { | |||
Button.this.click(); | |||
} | |||
}); | |||
display.addToFrame(this); | |||
} | |||
class Button extends java.awt.Button { | |||
static final Color defaultBackgroundColor = Color.gray; | |||
static final Color defaultForegroundColor = Color.black; | |||
static final String defaultText = "cycle color"; | |||
Button(Display display) { | |||
super(); | |||
setLabel(defaultText); | |||
setBackground(defaultBackgroundColor); | |||
setForeground(defaultForegroundColor); | |||
addActionListener(new ActionListener() { | |||
public void actionPerformed(ActionEvent e) { | |||
Button.this.click(); | |||
} | |||
}); | |||
display.addToFrame(this); | |||
} | |||
public void click() {} | |||
public void click() {} | |||
} | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1531,24 +1531,24 @@ java bean.Demo | |||
</para> | |||
<programlisting><![CDATA[ | |||
class ColorLabel extends Label { | |||
class ColorLabel extends Label { | |||
ColorLabel(Display display) { | |||
super(); | |||
display.addToFrame(this); | |||
} | |||
ColorLabel(Display display) { | |||
super(); | |||
display.addToFrame(this); | |||
} | |||
final static Color[] colors = {Color.red, Color.blue, | |||
Color.green, Color.magenta}; | |||
private int colorIndex = 0; | |||
private int cycleCount = 0; | |||
void colorCycle() { | |||
cycleCount++; | |||
colorIndex = (colorIndex + 1) % colors.length; | |||
setBackground(colors[colorIndex]); | |||
setText("" + cycleCount); | |||
} | |||
} | |||
final static Color[] colors = {Color.red, Color.blue, | |||
Color.green, Color.magenta}; | |||
private int colorIndex = 0; | |||
private int cycleCount = 0; | |||
void colorCycle() { | |||
cycleCount++; | |||
colorIndex = (colorIndex + 1) % colors.length; | |||
setBackground(colors[colorIndex]); | |||
setText("" + cycleCount); | |||
} | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1577,7 +1577,8 @@ aspect SubjectObserverProtocolImpl extends SubjectObserverProtocol { | |||
target(s) && | |||
call(void Button.click()); | |||
}]]></programlisting> | |||
} | |||
]]></programlisting> | |||
<para> | |||
It does this by assuring that <classname>Button</classname> and | |||
@@ -1594,7 +1595,7 @@ aspect SubjectObserverProtocolImpl extends SubjectObserverProtocol { | |||
<sect3> | |||
<title>Compiling and Running</title> | |||
<para> | |||
<para> | |||
<classname>Demo</classname> is the top class that starts this | |||
demo. It instantiates a two buttons and three observers and links | |||
them together as subjects and observers. So to run the demo, go to | |||
@@ -1602,8 +1603,8 @@ aspect SubjectObserverProtocolImpl extends SubjectObserverProtocol { | |||
</para> | |||
<programlisting><![CDATA[ | |||
ajc -argfile observer/files.lst | |||
java observer.Demo | |||
ajc -argfile observer/files.lst | |||
java observer.Demo | |||
]]></programlisting> | |||
</sect3> | |||
@@ -1803,43 +1804,43 @@ public class Customer { | |||
</para> | |||
<programlisting><![CDATA[ | |||
abstract class Connection { | |||
abstract class Connection { | |||
public static final int PENDING = 0; | |||
public static final int COMPLETE = 1; | |||
public static final int DROPPED = 2; | |||
public static final int PENDING = 0; | |||
public static final int COMPLETE = 1; | |||
public static final int DROPPED = 2; | |||
Customer caller, receiver; | |||
private int state = PENDING; | |||
Customer caller, receiver; | |||
private int state = PENDING; | |||
Connection(Customer a, Customer b) { | |||
this.caller = a; | |||
this.receiver = b; | |||
} | |||
Connection(Customer a, Customer b) { | |||
this.caller = a; | |||
this.receiver = b; | |||
} | |||
public int getState(){ | |||
return state; | |||
} | |||
public int getState(){ | |||
return state; | |||
} | |||
public Customer getCaller() { return caller; } | |||
public Customer getCaller() { return caller; } | |||
public Customer getReceiver() { return receiver; } | |||
public Customer getReceiver() { return receiver; } | |||
void complete() { | |||
state = COMPLETE; | |||
System.out.println("connection completed"); | |||
} | |||
void complete() { | |||
state = COMPLETE; | |||
System.out.println("connection completed"); | |||
} | |||
void drop() { | |||
state = DROPPED; | |||
System.out.println("connection dropped"); | |||
} | |||
void drop() { | |||
state = DROPPED; | |||
System.out.println("connection dropped"); | |||
} | |||
public boolean connects(Customer c){ | |||
return (caller == c || receiver == c); | |||
} | |||
public boolean connects(Customer c){ | |||
return (caller == c || receiver == c); | |||
} | |||
} | |||
} | |||
]]></programlisting> | |||
</sect3> | |||
@@ -1854,23 +1855,23 @@ public class Customer { | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Local extends Connection { | |||
Local(Customer a, Customer b) { | |||
super(a, b); | |||
System.out.println("[new local connection from " + | |||
a + " to " + b + "]"); | |||
} | |||
} | |||
class Local extends Connection { | |||
Local(Customer a, Customer b) { | |||
super(a, b); | |||
System.out.println("[new local connection from " + | |||
a + " to " + b + "]"); | |||
} | |||
} | |||
]]></programlisting> | |||
<programlisting><![CDATA[ | |||
class LongDistance extends Connection { | |||
LongDistance(Customer a, Customer b) { | |||
super(a, b); | |||
System.out.println("[new long distance connection from " + | |||
a + " to " + b + "]"); | |||
} | |||
} | |||
class LongDistance extends Connection { | |||
LongDistance(Customer a, Customer b) { | |||
super(a, b); | |||
System.out.println("[new long distance connection from " + | |||
a + " to " + b + "]"); | |||
} | |||
} | |||
]]></programlisting> | |||
</sect3> | |||
@@ -1913,22 +1914,22 @@ java telecom.BasicSimulation | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Timer { | |||
long startTime, stopTime; | |||
class Timer { | |||
long startTime, stopTime; | |||
public void start() { | |||
startTime = System.currentTimeMillis(); | |||
stopTime = startTime; | |||
} | |||
public void start() { | |||
startTime = System.currentTimeMillis(); | |||
stopTime = startTime; | |||
} | |||
public void stop() { | |||
stopTime = System.currentTimeMillis(); | |||
} | |||
public void stop() { | |||
stopTime = System.currentTimeMillis(); | |||
} | |||
public long getTime() { | |||
return stopTime - startTime; | |||
} | |||
} | |||
public long getTime() { | |||
return stopTime - startTime; | |||
} | |||
} | |||
]]></programlisting> | |||
</sect4> | |||
@@ -1963,14 +1964,14 @@ public aspect TimerLog { | |||
<para> | |||
The <classname>Timing</classname> aspect is declares an | |||
inter-type field <literal>totalConnectTime</literal> for | |||
inter-type field <literal>totalConnectTime</literal> for | |||
<classname>Customer</classname> to store the accumulated connection | |||
time per <classname>Customer</classname>. It also declares that | |||
each <classname>Connection</classname> object has a timer. | |||
each <classname>Connection</classname> object has a timer. | |||
<programlisting><![CDATA[ | |||
public long Customer.totalConnectTime = 0; | |||
private Timer Connection.timer = new Timer(); | |||
public long Customer.totalConnectTime = 0; | |||
private Timer Connection.timer = new Timer(); | |||
]]></programlisting> | |||
Two pieces of after advice ensure that the timer is started when | |||
@@ -2029,7 +2030,7 @@ public aspect Timing { | |||
runs after <classname>Timing</classname>'s advice on the same join | |||
point. Finally, it declares inter-type methods and fields for | |||
<classname>Customer</classname> to handle the | |||
<literal>totalCharge</literal>. | |||
<literal>totalCharge</literal>. | |||
</para> | |||
<programlisting><![CDATA[ | |||
@@ -2097,10 +2098,10 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
protected void report(Customer c){ | |||
Timing t = Timing.aspectOf(); | |||
System.out.println(c + " spent " + t.getTotalConnectTime(c)); | |||
} | |||
protected void report(Customer c){ | |||
Timing t = Timing.aspectOf(); | |||
System.out.println(c + " spent " + t.getTotalConnectTime(c)); | |||
} | |||
]]></programlisting> | |||
</sect3> | |||
@@ -2115,8 +2116,8 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
ajc -argfile telecom/timing.lst | |||
java telecom.TimingSimulation | |||
ajc -argfile telecom/timing.lst | |||
java telecom.TimingSimulation | |||
]]></programlisting> | |||
<para> | |||
@@ -2125,8 +2126,8 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
ajc -argfile telecom/billing.lst | |||
java telecom.BillingSimulation | |||
ajc -argfile telecom/billing.lst | |||
java telecom.BillingSimulation | |||
]]></programlisting> | |||
</sect3> | |||
@@ -2199,8 +2200,8 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
public static void traceEntry(String str); | |||
public static void traceExit(String str); | |||
public static void traceEntry(String str); | |||
public static void traceExit(String str); | |||
]]></programlisting> | |||
<para> | |||
@@ -2210,7 +2211,7 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
Trace.traceEntry("Square.distance in " + toString()); | |||
Trace.traceEntry("Square.distance in " + toString()); | |||
]]></programlisting> | |||
<para> | |||
@@ -2219,8 +2220,8 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
public static void traceEntry(String str, Object obj); | |||
public static void traceExit(String str, Object obj); | |||
public static void traceEntry(String str, Object obj); | |||
public static void traceExit(String str, Object obj); | |||
]]></programlisting> | |||
<para> | |||
@@ -2230,7 +2231,7 @@ public aspect Billing { | |||
</para> | |||
<programlisting><![CDATA[ | |||
Trace.traceEntry("Square.distance", this); | |||
Trace.traceEntry("Square.distance", this); | |||
]]></programlisting> | |||
<para> |
@@ -5,7 +5,7 @@ | |||
<sect1> | |||
<title>Compiler Notes</title> | |||
<para> | |||
<para> | |||
The initial implementations of AspectJ have all been | |||
compiler-based implementations. Certain elements of AspectJ's | |||
semantics are difficult to implement without making modifications | |||
@@ -25,7 +25,7 @@ | |||
</para> | |||
<programlisting><![CDATA[ | |||
before(): get(int Point.x) { System.out.println("got x"); } | |||
before(): get(int Point.x) { System.out.println("got x"); } | |||
]]></programlisting> | |||
<para> | |||
@@ -36,7 +36,7 @@ | |||
compiled, whether changes were made later, etc. | |||
</para> | |||
<para> | |||
<para> | |||
But AspectJ implementations are permitted to deviate from this in | |||
a well-defined way -- they are permitted to advise only accesses | |||
in <emphasis>code the implementation controls</emphasis>. Each | |||
@@ -67,11 +67,11 @@ | |||
can be advised only if ajc controls the bytecode for the method or | |||
constructor body in question. | |||
The end of an exception handler is underdetermined in bytecode, | |||
so ajc will not implement after or around advice on handler join | |||
so ajc will not implement after or around advice on handler join | |||
points. | |||
Similarly, ajc cannot implement around advice on initialization | |||
or preinitialization join points. | |||
In cases where ajc cannot implement advice, it will emit a | |||
Similarly, ajc cannot implement around advice on initialization | |||
or preinitialization join points. | |||
In cases where ajc cannot implement advice, it will emit a | |||
compile-time error noting this as a compiler limitation. | |||
</para> | |||
@@ -100,35 +100,35 @@ | |||
</para> | |||
<para> | |||
When declaring members on interfaces, the implementation must | |||
control both the interface and the top-level implementors of | |||
control both the interface and the top-level implementors of | |||
that interface (the classes that implement the interface but | |||
do not have a superclass that implements the interface). | |||
You may weave these separately, but be aware that you will get | |||
runtime exceptions if you run the affected top-level classes | |||
without the interface as produced by the same ajc implementation. | |||
Any intertype declaration of an abstract method on an interface | |||
must be specified as public, you will get a compile time error | |||
message indicating this is a compiler limitation if you do not | |||
without the interface as produced by the same ajc implementation. | |||
Any intertype declaration of an abstract method on an interface | |||
must be specified as public, you will get a compile time error | |||
message indicating this is a compiler limitation if you do not | |||
specify public. A non-abstract method declared on an interface | |||
can use any access modifier except protected. Note that this is | |||
different to normal Java rules where all members declared in | |||
different to normal Java rules where all members declared in | |||
an interface are implicitly public. | |||
Finally, note that one cannot define static fields or methods | |||
Finally, note that one cannot define static fields or methods | |||
on interfaces. | |||
</para> | |||
<para> | |||
When declaring methods on target types, only methods declared | |||
public are recognizable in the bytecode, so methods must be | |||
declared public to be overridden in any subtype or to be called | |||
When declaring methods on target types, only methods declared | |||
public are recognizable in the bytecode, so methods must be | |||
declared public to be overridden in any subtype or to be called | |||
from code in a later compile using the target type as a library. | |||
</para> | |||
<para> | |||
Other AspectJ implementations, indeed, future versions of ajc, may | |||
define <emphasis>code the implementation controls</emphasis> more | |||
liberally or restrictively, so long as they comport with the Java | |||
language. For example, the <literal>call</literal> pointcut does | |||
not pick out reflective calls to a method implemented in | |||
not pick out reflective calls to a method implemented in | |||
<literal>java.lang.reflect.Method.invoke(Object, Object[])</literal>. | |||
Some suggest that the call "happens" and the call pointcut should | |||
pick it out, but the AspectJ language shouldn't anticipate what happens | |||
@@ -172,12 +172,12 @@ | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Test { | |||
void main(String[] args) { | |||
System.out.println(Test.class); // calls Class.forName | |||
System.out.println(args[0] + args[1]); // calls StringBuffer.append | |||
} | |||
} | |||
class Test { | |||
void main(String[] args) { | |||
System.out.println(Test.class); // calls Class.forName | |||
System.out.println(args[0] + args[1]); // calls StringBuffer.append | |||
} | |||
} | |||
]]></programlisting> | |||
<para>In short, the join point model of the current AspectJ | |||
@@ -217,7 +217,7 @@ | |||
</para> | |||
<programlisting><![CDATA[ | |||
cflow(call(void foo()) || handler(java.io.IOException)) | |||
cflow(call(void foo()) || handler(java.io.IOException)) | |||
]]></programlisting> | |||
<para> will capture all join points in the control flow of a call to | |||
@@ -236,9 +236,9 @@ | |||
</para> | |||
<programlisting><![CDATA[ | |||
before(): handler(java.io.IOException) && cflow(void parse()) { | |||
System.out.println("about to handle an exception while parsing"); | |||
} | |||
before(): handler(java.io.IOException) && cflow(void parse()) { | |||
System.out.println("about to handle an exception while parsing"); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -258,16 +258,16 @@ | |||
</para> | |||
<programlisting><![CDATA[ | |||
class C { | |||
double d = Math.sqrt(2); | |||
} | |||
class C { | |||
double d = Math.sqrt(2); | |||
} | |||
]]></programlisting> | |||
<para> | |||
are considered part of constructors by the time AspectJ gets ahold | |||
of bytecode. That is, the assignment of d to the square root of | |||
two happens <emphasis>inside</emphasis> the default constructor of | |||
C. | |||
C. | |||
</para> | |||
<para> | |||
@@ -280,15 +280,15 @@ | |||
</para> | |||
<programlisting><![CDATA[ | |||
aspect A { | |||
C.new(Object o) {} // implicitly calls super() | |||
aspect A { | |||
C.new(Object o) {} // implicitly calls super() | |||
public static void main(String[] args) { | |||
System.out.println((new C() ).d); // prints 1.414... | |||
System.out.println((new C(null)).d); // prints 0.0 | |||
} | |||
public static void main(String[] args) { | |||
System.out.println((new C() ).d); // prints 1.414... | |||
System.out.println((new C(null)).d); // prints 0.0 | |||
} | |||
]]></programlisting> | |||
<para> | |||
It is the job of an inter-type constructor to do all the required | |||
initialization, or to delegate to a <literal>this</literal> | |||
@@ -302,8 +302,8 @@ | |||
<para>Writing aspects in annotation-style is subject to the same | |||
bytecode limitations since the binary aspects take the same | |||
form and are woven in the same way. However, the implementation | |||
differences (e.g., the mechanism for implementing around advice) | |||
may be apparent at runtime. See the documentation on annotation-style | |||
differences (e.g., the mechanism for implementing around advice) | |||
may be apparent at runtime. See the documentation on annotation-style | |||
for more information. | |||
</para> | |||
</sect1> | |||
@@ -311,7 +311,7 @@ | |||
<title>Summary of implementation requirements</title> | |||
<para> | |||
This summarizes the requirements of our implementation of AspectJ. | |||
For more details, see the relevant sections of this guide. | |||
For more details, see the relevant sections of this guide. | |||
</para> | |||
<itemizedlist spacing="compact"> | |||
<listitem> | |||
@@ -343,7 +343,7 @@ | |||
<para>Implementation Caveats</para> | |||
<itemizedlist spacing="compact"> | |||
<listitem> | |||
<para>The initialization and preinitialization join points | |||
<para>The initialization and preinitialization join points | |||
do not support around advice</para> | |||
</listitem> | |||
<listitem> | |||
@@ -355,7 +355,7 @@ | |||
</itemizedlist> | |||
</listitem> | |||
<listitem> | |||
<para>Declaring members on an interface in an aspect affects only | |||
<para>Declaring members on an interface in an aspect affects only | |||
the topmost implementing classes the implementation controls.</para> | |||
</listitem> | |||
<listitem> | |||
@@ -363,7 +363,7 @@ | |||
</listitem> | |||
<listitem> | |||
<para> | |||
Runtime <literal>ClassCastException</literal> may result | |||
Runtime <literal>ClassCastException</literal> may result | |||
from supplying a supertype of the actual type as an argument | |||
to proceed(..) in around advice.</para> | |||
</listitem> |
@@ -623,10 +623,10 @@ interface MyInterface { ... } | |||
</para> | |||
<programlisting> | |||
P --------------------- | |||
P --------------------- | |||
\ | |||
\ cflow of P | |||
\ | |||
\ cflow of P | |||
\ | |||
</programlisting> | |||
@@ -639,16 +639,16 @@ interface MyInterface { ... } | |||
</para> | |||
<programlisting> | |||
P --------------------- | |||
P --------------------- | |||
\ | |||
\ cflow of P | |||
\ | |||
\ cflow of P | |||
\ | |||
\ | |||
\ | |||
\ | |||
Q -------------\------- | |||
Q -------------\------- | |||
\ \ | |||
\ cflow of Q \ cflow(P) && cflow(Q) | |||
\ \ | |||
\ cflow of Q \ cflow(P) && cflow(Q) | |||
\ \ | |||
</programlisting> | |||
<para> | |||
@@ -666,10 +666,10 @@ interface MyInterface { ... } | |||
</para> | |||
<programlisting> | |||
P && Q ------------------- | |||
\ | |||
\ cflow of (P && Q) | |||
\ | |||
P && Q ------------------- | |||
\ | |||
\ cflow of (P && Q) | |||
\ | |||
</programlisting> | |||
<para> | |||
@@ -715,7 +715,7 @@ aspect A { | |||
<para> | |||
The <literal>!within(<replaceable>A</replaceable>)</literal> | |||
pointcut above is required to avoid the <literal>printPC</literal> | |||
pointcut above is required to avoid the <literal>printPC</literal> | |||
pointcut applying to the <literal>System.out.println</literal> | |||
call in the advice body. If this was not present a recursive call | |||
would result as the pointcut would apply to its own advice. | |||
@@ -734,9 +734,9 @@ aspect A { | |||
</para> | |||
<programlisting><![CDATA[ | |||
pointcut setter(): target(Point) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
pointcut setter(): target(Point) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
]]></programlisting> | |||
<para> | |||
@@ -751,9 +751,9 @@ aspect A { | |||
</para> | |||
<programlisting><![CDATA[ | |||
pointcut setter(Point p): target(p) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
pointcut setter(Point p): target(p) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
]]></programlisting> | |||
<para> | |||
@@ -774,9 +774,9 @@ aspect A { | |||
</para> | |||
<programlisting><![CDATA[ | |||
pointcut testEquality(Point p): target(Point) && | |||
args(p) && | |||
call(boolean equals(Object)); | |||
pointcut testEquality(Point p): target(Point) && | |||
args(p) && | |||
call(boolean equals(Object)); | |||
]]></programlisting> | |||
<para> | |||
@@ -796,9 +796,9 @@ aspect A { | |||
</para> | |||
<programlisting><![CDATA[ | |||
pointcut testEquality(Point p1, Point p2): target(p1) && | |||
args(p2) && | |||
call(boolean equals(Object)); | |||
pointcut testEquality(Point p1, Point p2): target(p1) && | |||
args(p2) && | |||
call(boolean equals(Object)); | |||
]]></programlisting> | |||
<para> | |||
@@ -828,9 +828,9 @@ pointcut setter(Point p, int newval): target(p) && | |||
following pointcut definition will result in a compilation error: | |||
<programlisting><![CDATA[ | |||
pointcut badPointcut(Point p1, Point p2): | |||
(target(p1) && call(void setX(int))) || | |||
(target(p2) && call(void setY(int))); | |||
pointcut badPointcut(Point p1, Point p2): | |||
(target(p1) && call(void setX(int))) || | |||
(target(p2) && call(void setY(int))); | |||
]]></programlisting> | |||
because <literal>p1</literal> is only bound when calling | |||
@@ -856,38 +856,38 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Handle { | |||
Partner partner = new Partner(); | |||
class Handle { | |||
Partner partner = new Partner(); | |||
public void foo() { partner.foo(); } | |||
public void bar(int x) { partner.bar(x); } | |||
public void foo() { partner.foo(); } | |||
public void bar(int x) { partner.bar(x); } | |||
public static void main(String[] args) { | |||
Handle h1 = new Handle(); | |||
h1.foo(); | |||
h1.bar(2); | |||
} | |||
public static void main(String[] args) { | |||
Handle h1 = new Handle(); | |||
h1.foo(); | |||
h1.bar(2); | |||
} | |||
} | |||
class Partner { | |||
boolean isAlive() { return true; } | |||
void foo() { System.out.println("foo"); } | |||
void bar(int x) { System.out.println("bar " + x); } | |||
} | |||
class Partner { | |||
boolean isAlive() { return true; } | |||
void foo() { System.out.println("foo"); } | |||
void bar(int x) { System.out.println("bar " + x); } | |||
} | |||
aspect HandleLiveness { | |||
before(Handle handle): target(handle) && call(public * *(..)) { | |||
if ( handle.partner == null || !handle.partner.isAlive() ) { | |||
throw new DeadPartnerException(); | |||
} | |||
aspect HandleLiveness { | |||
before(Handle handle): target(handle) && call(public * *(..)) { | |||
if ( handle.partner == null || !handle.partner.isAlive() ) { | |||
throw new DeadPartnerException(); | |||
} | |||
} | |||
} | |||
class DeadPartnerException extends RuntimeException {} | |||
class DeadPartnerException extends RuntimeException {} | |||
]]></programlisting> | |||
</sect2> | |||
<sect2 id="pointcut-best-practice" xreflabel="pointcut-best-practice"> | |||
<title>Writing good pointcuts</title> | |||
@@ -919,15 +919,15 @@ pointcut setter(Point p, int newval): target(p) && | |||
</listitem> | |||
</itemizedlist> | |||
<para> | |||
A well written pointcut should | |||
A well written pointcut should | |||
try and include at least the first two types (kinded and scoping), whilst the contextual designators may be included if wishing to | |||
match based on join point context, or bind that context for use in the advice. Supplying either just a kinded designator or | |||
just a contextual designator will work but could affect weaving performance (time and memory used) | |||
due to all the extra processing and analysis. | |||
Scoping designators are very fast to match, they can very quickly dismiss groups of join points that should not be further | |||
match based on join point context, or bind that context for use in the advice. Supplying either just a kinded designator or | |||
just a contextual designator will work but could affect weaving performance (time and memory used) | |||
due to all the extra processing and analysis. | |||
Scoping designators are very fast to match, they can very quickly dismiss groups of join points that should not be further | |||
processed - that is why a good pointcut should always include one if possible. | |||
</para> | |||
</sect2> | |||
</sect1> | |||
@@ -945,14 +945,14 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
pointcut setter(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int) || | |||
call(void setY(int))); | |||
pointcut setter(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int) || | |||
call(void setY(int))); | |||
before(Point p1, int newval): setter(p1, newval) { | |||
System.out.println("About to set something in " + p1 + | |||
" to the new value " + newval); | |||
} | |||
before(Point p1, int newval): setter(p1, newval) { | |||
System.out.println("About to set something in " + p1 + | |||
" to the new value " + newval); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -961,12 +961,12 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
before(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int)) || | |||
call(void setY(int))) { | |||
System.out.println("About to set something in " + p1 + | |||
" to the new value " + newval); | |||
} | |||
before(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int)) || | |||
call(void setY(int))) { | |||
System.out.println("About to set something in " + p1 + | |||
" to the new value " + newval); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -979,9 +979,9 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) return; | |||
} | |||
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) return; | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -991,9 +991,9 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
after(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) throw new PostConditionViolation(); | |||
} | |||
after(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) throw new PostConditionViolation(); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1004,9 +1004,9 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
after(Point p) returning(int x): target(p) && call(int getX()) { | |||
System.out.println("Returning int value " + x + " for p = " + p); | |||
} | |||
after(Point p) returning(int x): target(p) && call(int getX()) { | |||
System.out.println("Returning int value " + x + " for p = " + p); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1018,9 +1018,9 @@ pointcut setter(Point p, int newval): target(p) && | |||
</para> | |||
<programlisting><![CDATA[ | |||
after() throwing(Exception e): target(Point) && call(void setX(int)) { | |||
System.out.println(e); | |||
} | |||
after() throwing(Exception e): target(Point) && call(void setX(int)) { | |||
System.out.println(e); | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1059,7 +1059,7 @@ void around(Point p, int x): target(p) | |||
initialized to <literal>false</literal>: | |||
<programlisting><![CDATA[ | |||
private boolean Server.disabled = false; | |||
private boolean Server.disabled = false; | |||
]]></programlisting> | |||
It is declared <literal>private</literal>, which means that it is | |||
@@ -1077,7 +1077,7 @@ void around(Point p, int x): target(p) | |||
arguments that returns whatever <literal>this.x</literal> is: | |||
<programlisting><![CDATA[ | |||
public int Point.getX() { return this.x; } | |||
public int Point.getX() { return this.x; } | |||
]]></programlisting> | |||
Inside the body, <literal>this</literal> is the | |||
@@ -1092,7 +1092,7 @@ void around(Point p, int x): target(p) | |||
<literal>Point</literal>: | |||
<programlisting><![CDATA[ | |||
public Point.new(int x, int y) { this.x = x; this.y = y; } | |||
public Point.new(int x, int y) { this.x = x; this.y = y; } | |||
]]></programlisting> | |||
</para> | |||
@@ -1103,7 +1103,7 @@ void around(Point p, int x): target(p) | |||
to zero: | |||
<programlisting><![CDATA[ | |||
public int Point.x = 0; | |||
public int Point.x = 0; | |||
]]></programlisting> | |||
Because this is publically declared, it is an error if | |||
@@ -1117,7 +1117,7 @@ void around(Point p, int x): target(p) | |||
<literal>Comparable</literal> interface: | |||
<programlisting><![CDATA[ | |||
declare parents: Point implements Comparable; | |||
declare parents: Point implements Comparable; | |||
]]></programlisting> | |||
Of course, this will be an error unless <literal>Point</literal> | |||
@@ -1129,7 +1129,7 @@ void around(Point p, int x): target(p) | |||
<literal>GeometricObject</literal> class. | |||
<programlisting><![CDATA[ | |||
declare parents: Point extends GeometricObject; | |||
declare parents: Point extends GeometricObject; | |||
]]></programlisting> | |||
</para> | |||
@@ -1138,8 +1138,8 @@ void around(Point p, int x): target(p) | |||
following declarations | |||
<programlisting><![CDATA[ | |||
public String Point.name; | |||
public void Point.setName(String name) { this.name = name; } | |||
public String Point.name; | |||
public void Point.setName(String name) { this.name = name; } | |||
]]></programlisting> | |||
publicly declare that Point has both a String field | |||
@@ -1155,13 +1155,13 @@ void around(Point p, int x): target(p) | |||
interface: | |||
<programlisting><![CDATA[ | |||
aspect A { | |||
private interface HasName {} | |||
declare parents: (Point || Line || Square) implements HasName; | |||
aspect A { | |||
private interface HasName {} | |||
declare parents: (Point || Line || Square) implements HasName; | |||
private String HasName.name; | |||
public String HasName.getName() { return name; } | |||
} | |||
private String HasName.name; | |||
public String HasName.getName() { return name; } | |||
} | |||
]]></programlisting> | |||
This declares a marker interface <literal>HasName</literal>, and also declares that any | |||
@@ -1193,7 +1193,7 @@ void around(Point p, int x): target(p) | |||
aspect makes a private inter-type declaration of a field | |||
<programlisting><![CDATA[ | |||
private int Foo.x; | |||
private int Foo.x; | |||
]]></programlisting> | |||
Then code in the aspect can refer to <literal>Foo</literal>'s | |||
@@ -1230,38 +1230,38 @@ void around(Point p, int x): target(p) | |||
</para> | |||
<programlisting><![CDATA[ | |||
class Point { | |||
int x, y; | |||
class Point { | |||
int x, y; | |||
public void setX(int x) { this.x = x; } | |||
public void setY(int y) { this.y = y; } | |||
public void setX(int x) { this.x = x; } | |||
public void setY(int y) { this.y = y; } | |||
public static void main(String[] args) { | |||
Point p = new Point(); | |||
p.setX(3); p.setY(333); | |||
} | |||
} | |||
public static void main(String[] args) { | |||
Point p = new Point(); | |||
p.setX(3); p.setY(333); | |||
} | |||
} | |||
aspect PointAssertions { | |||
private boolean Point.assertX(int x) { | |||
return (x <= 100 && x >= 0); | |||
} | |||
private boolean Point.assertY(int y) { | |||
return (y <= 100 && y >= 0); | |||
} | |||
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) { | |||
System.out.println("Illegal value for x"); return; | |||
} | |||
} | |||
before(Point p, int y): target(p) && args(y) && call(void setY(int)) { | |||
if (!p.assertY(y)) { | |||
System.out.println("Illegal value for y"); return; | |||
} | |||
} | |||
} | |||
aspect PointAssertions { | |||
private boolean Point.assertX(int x) { | |||
return (x <= 100 && x >= 0); | |||
} | |||
private boolean Point.assertY(int y) { | |||
return (y <= 100 && y >= 0); | |||
} | |||
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) { | |||
System.out.println("Illegal value for x"); return; | |||
} | |||
} | |||
before(Point p, int y): target(p) && args(y) && call(void setY(int)) { | |||
if (!p.assertY(y)) { | |||
System.out.println("Illegal value for y"); return; | |||
} | |||
} | |||
} | |||
]]></programlisting> | |||
</sect2> | |||
@@ -1290,11 +1290,11 @@ void around(Point p, int x): target(p) | |||
</para> | |||
<programlisting><![CDATA[ | |||
aspect TraceNonStaticMethods { | |||
before(Point p): target(p) && call(* *(..)) { | |||
System.out.println("Entering " + thisJoinPoint + " in " + p); | |||
} | |||
} | |||
aspect TraceNonStaticMethods { | |||
before(Point p): target(p) && call(* *(..)) { | |||
System.out.println("Entering " + thisJoinPoint + " in " + p); | |||
} | |||
} | |||
]]></programlisting> | |||
<para> | |||
@@ -1304,7 +1304,7 @@ void around(Point p, int x): target(p) | |||
arguments of the join point: | |||
<programlisting><![CDATA[ | |||
thisJoinPoint.getArgs() | |||
thisJoinPoint.getArgs() | |||
]]></programlisting> | |||
In addition, it holds an object consisting of all the static | |||
@@ -1312,7 +1312,7 @@ void around(Point p, int x): target(p) | |||
and static signature: | |||
<programlisting><![CDATA[ | |||
thisJoinPoint.getStaticPart() | |||
thisJoinPoint.getStaticPart() | |||
]]></programlisting> | |||
If you only need the static information about the join point, you may | |||
@@ -1327,11 +1327,11 @@ void around(Point p, int x): target(p) | |||
</para> | |||
<programlisting><![CDATA[ | |||
thisJoinPointStaticPart == thisJoinPoint.getStaticPart() | |||
thisJoinPointStaticPart == thisJoinPoint.getStaticPart() | |||
thisJoinPoint.getKind() == thisJoinPointStaticPart.getKind() | |||
thisJoinPoint.getSignature() == thisJoinPointStaticPart.getSignature() | |||
thisJoinPoint.getSourceLocation() == thisJoinPointStaticPart.getSourceLocation() | |||
thisJoinPoint.getKind() == thisJoinPointStaticPart.getKind() | |||
thisJoinPoint.getSignature() == thisJoinPointStaticPart.getSignature() | |||
thisJoinPoint.getSourceLocation() == thisJoinPointStaticPart.getSourceLocation() | |||
]]></programlisting> | |||
<para> |