aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progguide
diff options
context:
space:
mode:
authorAlexander Kriegisch <Alexander@Kriegisch.name>2024-01-04 08:13:04 +0700
committerAlexander Kriegisch <Alexander@Kriegisch.name>2024-01-06 10:09:11 +0100
commit0065b755292708d6fd27c067564ecef2b10ede04 (patch)
tree2a88188271fe2910fd26c5b8536f39fabe111168 /docs/progguide
parentba6058a4007f937c3d32a6022446edaa149a0d1d (diff)
downloadaspectj-0065b755292708d6fd27c067564ecef2b10ede04.tar.gz
aspectj-0065b755292708d6fd27c067564ecef2b10ede04.zip
Delete 50+ XML DocBook resource files
in favour of the already existing asciidoc ones. Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'docs/progguide')
-rw-r--r--docs/progguide/aspectj-docs.css89
-rw-r--r--docs/progguide/aspectjdoc.dsl124
-rw-r--r--docs/progguide/build.sh79
-rw-r--r--docs/progguide/examples.xml2443
-rw-r--r--docs/progguide/gettingstarted.xml1310
-rw-r--r--docs/progguide/idioms.xml74
-rw-r--r--docs/progguide/implementation.xml377
-rw-r--r--docs/progguide/language.xml1354
-rw-r--r--docs/progguide/pitfalls.xml112
-rw-r--r--docs/progguide/preface.xml66
-rw-r--r--docs/progguide/progguide.html.xsl9
-rw-r--r--docs/progguide/progguide.xml63
-rw-r--r--docs/progguide/quickreference.xml773
-rw-r--r--docs/progguide/semantics.xml3271
14 files changed, 0 insertions, 10144 deletions
diff --git a/docs/progguide/aspectj-docs.css b/docs/progguide/aspectj-docs.css
deleted file mode 100644
index 9c2f5d4fc..000000000
--- a/docs/progguide/aspectj-docs.css
+++ /dev/null
@@ -1,89 +0,0 @@
-body {
- font-family: "Lucida Grande", "Trebuchet MS", sans-serif;
- line-height: 1.1em;
- }
-
-h1 {
- margin-bottom: 3px;
- padding-bottom: 0px;
- line-height: 1.1em;
-}
-
-h2 {
- font-size: 130%;
- font-weight: bold ;
- line-height: 16px;
- color: #FFFFFF;
- background-color: #0080C0;
- padding: 5px;
-}
-
-h3 {
- font-size: 110%;
- font-weight: bold ;
- line-height: 14px;
- color: #FFFFFF;
- background-color: orange;
- padding: 5px;
-}
-
-tt {
- font-size: 120%;
- color: #00AAF0;
- }
-
-tt tt {
- font-size: 100%;
- }
-
-.programlisting {
- padding-top: 5px;
- border: 2px solid #ccc;
- background: #eee;
- font-size: 120%;
- color: #111199;
-
- }
-
-.term {
- color: #111199;
- }
-
-.variablelist dd {
- margin-left: 18px;
- padding-left: 20px;
- background: url(dd_arrow.gif) no-repeat 0 2px;
- }
-
-.toc dt {
- font-size: 110%;
- padding-bottom: 0px;
- margin-bottom: 5px;
- }
-
-.toc dl dd dt {
- font-size: 100%;
- }
-
-.toc dt {
- font-size: 100%
- margin-bottom: 0;
- }
-
-.informaltable table {
- margin-left: 5%;
- }
-
-.informaltable th {
- background-color: orange;
- padding: 1px;
- }
-
-ul li {
- line-height: 1.2em;
- }
-
-.keyword {
- font-weight: bold;
- color: purple;
- } \ No newline at end of file
diff --git a/docs/progguide/aspectjdoc.dsl b/docs/progguide/aspectjdoc.dsl
deleted file mode 100644
index 4db3b678e..000000000
--- a/docs/progguide/aspectjdoc.dsl
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
- <!ENTITY html-ss PUBLIC "-//Norman Walsh//DOCUMENT DocBook HTML Stylesheet//EN" CDATA DSSSL>
- <!ENTITY print-ss PUBLIC "-//Norman Walsh//DOCUMENT DocBook Print Stylesheet//EN" CDATA DSSSL>
-]>
-
-<style-sheet>
-
-<!-- Customizations for the HTML version -->
-
-<style-specification id="html" use="html-stylesheet">
-<style-specification-body>
-
-;; Specify the CSS stylesheet to use
-(define %stylesheet% "../../style.css")
-
-;; Suppress Lists of Tables, Examples, ...
-(define ($generate-book-lot-list$)
- '())
-
-;; Display only the first two section levels in the table of contents
-(define (toc-depth nd)
- (if (string=? (gi nd) (normalize "book"))
- 2
- 1))
-
-;; Make references be appendices (or chapters), not parts.
-(define (en-label-number-format-list)
- (list
- (list (normalize "set") "1")
- (list (normalize "book") "1")
- (list (normalize "prefix") "1")
- (list (normalize "part") "I")
- (list (normalize "chapter") "1")
- (list (normalize "appendix") "A")
- ;;(list (normalize "reference") "1") ; references-as-chapters
- (list (normalize "reference") "A") ; references-as-appendices
- (list (normalize "example") "1")
- (list (normalize "figure") "1")
- (list (normalize "table") "1")
- (list (normalize "procedure") "1")
- (list (normalize "step") "1")
- (list (normalize "refsect1") "1")
- (list (normalize "refsect2") "1")
- (list (normalize "refsect3") "1")
- (list (normalize "sect1") "1")
- (list (normalize "sect2") "1")
- (list (normalize "sect3") "1")
- (list (normalize "sect4") "1")
- (list (normalize "sect5") "1")
- (list (normalize "section") "1")
- ))
- ;;; for references-as-appendices
- (define (reference-number-sibling-list cmp) (list (normalize "appendix")))
- (define (appendix-number-sibling-list cmp) (list (normalize "reference")))
- ;;; for references-as-chapters
- ;;(define (reference-number-sibling-list cmp) (list (normalize "chapter")))
- ;;(define (chapter-number-sibling-list cmp) (list (normalize "reference")))
-
-
-</style-specification-body>
-</style-specification>
-<external-specification id="html-stylesheet" document="html-ss">
-
-
-<!-- Customizations for the print version -->
-
-<style-specification id="print" use="print-stylesheet">
-<style-specification-body>
-
-;; Suppress Lists of Tables, Examples, ...
-(define ($generate-book-lot-list$)
- '())
-
-;; Display only the first two section levels in the table of contents
-(define (toc-depth nd)
- (if (string=? (gi nd) (normalize "book"))
- 2
- 1))
-
-(define %two-side% #t)
-(define bop-footnotes #t) ; doesn't seem to work
-
-;; Make references be appendices (or chapters), not parts.
-(define (en-label-number-format-list)
- (list
- (list (normalize "set") "1")
- (list (normalize "book") "1")
- (list (normalize "prefix") "1")
- (list (normalize "part") "I")
- (list (normalize "chapter") "1")
- (list (normalize "appendix") "A")
- ;;(list (normalize "reference") "1") ; references-as-chapters
- (list (normalize "reference") "A") ; references-as-appendices
- (list (normalize "example") "1")
- (list (normalize "figure") "1")
- (list (normalize "table") "1")
- (list (normalize "procedure") "1")
- (list (normalize "step") "1")
- (list (normalize "refsect1") "1")
- (list (normalize "refsect2") "1")
- (list (normalize "refsect3") "1")
- (list (normalize "sect1") "1")
- (list (normalize "sect2") "1")
- (list (normalize "sect3") "1")
- (list (normalize "sect4") "1")
- (list (normalize "sect5") "1")
- (list (normalize "section") "1")
- ))
- ;;; for references-as-appendices
- (define (reference-number-sibling-list cmp) (list (normalize "appendix")))
- (define (appendix-number-sibling-list cmp) (list (normalize "reference")))
- ;;; for references-as-chapters
- ;;(define (reference-number-sibling-list cmp) (list (normalize "chapter")))
- ;;(define (chapter-number-sibling-list cmp) (list (normalize "reference")))
-
-</style-specification-body>
-</style-specification>
-<external-specification id="print-stylesheet" document="print-ss">
-
-</style-sheet>
-
-<!-- Local Variables -->
-<!-- mode: scheme -->
-<!-- End -->
diff --git a/docs/progguide/build.sh b/docs/progguide/build.sh
deleted file mode 100644
index 19499ff3b..000000000
--- a/docs/progguide/build.sh
+++ /dev/null
@@ -1,79 +0,0 @@
-#/bin/sh
-
-JAVA_HOME="/opt/IBMJava2-13"
-DOCBOOK_HOME="/usr/local/docbook"
-
-SAXON="/home/vladimir/aspectj-external-lib/saxon"
-XERCES="/usr/local/xerces-1_4_3"
-
-saxon() { java -cp $SAXON/saxon.jar com.icl.saxon.StyleSheet $*; }
-xerces() { java -cp $XERCES/xercesSamples.jar sax.SAXCount -v $* ; }
-
-# echo ""; echo ""
-# echo "The following REMARKS still exist:"; echo ""
-# egrep -n -A3 "<remark>" *.xml
-# echo ""; echo ""
-
-# echo "Checking for required RPMS..."
-# for RPM in docbook-dtd docbook-xsl; do
-# rpm -q $RPM >/dev/null
-# if [ $? = 1 ]; then
-# echo "${RPM}: Required RPM not installed. Exiting..."
-# exit 1
-# fi
-# done
-
-# echo "Checking for required programs..."
-# for PROG in java tex; do
-# type $PROG >/dev/null 2>/dev/null
-# if [ $? = 1 ]; then
-# echo "$prog not found in PATH. Exiting..."
-# exit 1
-# fi
-# done
-
-# echo "Checking for required files..."
-# for FILE in $JAVA_HOME/jre/lib/ext/saxon.jar; do
-# if [ ! -s $FILE ]; then
-# echo "$FILE not found. Exiting..."
-# exit 1
-# fi
-# done
-
-OPT=$1
-shift 1
-
-if [ "$OPT" == "-v" ]; then
- COMMAND="xerces -v progguide.xml"
- echo " Validating the XML source: $COMMAND"
- ${COMMAND}
-fi
-
-if [ "$OPT" == "-t" ]; then
- COMMAND='openjade -t tex -d aspectjdoc.dsl#print /usr/share/sgml/xml.dcl progguide.xml'
- echo " Creating TeX from XML: $COMMAND"
- ${COMMAND}
- COMMAND="pdfjadetex progguide.tex"
- echo " Creating PDF from TeX: $COMMAND"
- ${COMMAND}
- ${COMMAND}
- exit
-fi
-
-COMMAND="saxon -w0 progguide.xml progguide.html.xsl"
-echo " Transforming XML to HTML: $COMMAND"
-${COMMAND}
-
-# echo "Transforming XML to FO..."
-# saxon -w0 -o progguide.fo progguide.xml ${XSL_STYLESHEET_HOME}/fo/docbook.xsl >progguide.fo.log 2>&1
-
-# echo -n "Transforming FO to PostScript"
-# tex --interaction nonstopmode -fmt /usr/local/texmf/tex/xmltex/base/xmltex progguide.fo >|progguide.ps.1.log 2>&1
-# echo "Pass 2..."
-# tex --interaction nonstopmode -fmt /usr/local/texmf/tex/xmltex/base/xmltex progguide.fo >|progguide.ps.2.log 2>&1
-# dvips progguide -o
-
-# echo "Transforming FO to PDF..."
-# pdflatex --interaction nonstopmode -fmt /usr/local/texmf/tex/xmltex/base/pdfxmltex progguide.fo >|progguide.pdf.log
-
-
diff --git a/docs/progguide/examples.xml b/docs/progguide/examples.xml
deleted file mode 100644
index 05645ab04..000000000
--- a/docs/progguide/examples.xml
+++ /dev/null
@@ -1,2443 +0,0 @@
-<chapter id="examples" xreflabel="Examples">
- <title>Examples</title>
-
- <sect1 id="examples-intro">
- <title>Introduction</title>
-
- <para>
- This chapter consists entirely of examples of AspectJ use.
- </para>
-
- <para>The examples can be grouped into four categories:</para>
-
- <simplelist columns="2" type="horiz">
- <member><emphasis role="bold">technique</emphasis></member>
- <member>Examples which illustrate how to use one or more features of the
- language. </member>
-
- <member><emphasis role="bold">development</emphasis></member>
- <member>Examples of using AspectJ during the development phase of a
- project. </member>
-
- <member><emphasis role="bold">production</emphasis></member>
- <member>Examples of using AspectJ to provide functionality in an
- application. </member>
-
- <member><emphasis role="bold">reusable</emphasis></member>
- <member>Examples of reuse of aspects and pointcuts.</member>
- </simplelist>
-
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="examples-howto">
- <title>Obtaining, Compiling and Running the Examples</title>
-
- <para>
- The examples source code is part of the AspectJ distribution which may be
- downloaded from the AspectJ project page ( <ulink
- url="https://eclipse.org/aspectj" /> ).
- </para>
-
- <para>
- Compiling most examples is straightforward. Go the
- <filename><replaceable>InstallDir</replaceable>/examples</filename>
- directory, and look for a <filename>.lst</filename> file in one of
- the example subdirectories. Use the <literal>-arglist</literal>
- option to <literal>ajc</literal> to compile the example. For
- instance, to compile the telecom example with billing, type
- </para>
-
-<programlisting>
-ajc -argfile telecom/billing.lst
-</programlisting>
-
- <para>
- To run the examples, your classpath must include the AspectJ run-time
- Java archive (<literal>aspectjrt.jar</literal>). You may either set the
- <literal>CLASSPATH</literal> environment variable or use the
- <literal>-classpath</literal> command line option to the Java
- interpreter:
- </para>
-
-<programlisting>
-(In Unix use a : in the CLASSPATH)
-java -classpath ".:<replaceable>InstallDir</replaceable>/lib/aspectjrt.jar" telecom.billingSimulation
-</programlisting>
-
-<programlisting>
-(In Windows use a ; in the CLASSPATH)
-java -classpath ".;<replaceable>InstallDir</replaceable>/lib/aspectjrt.jar" telecom.billingSimulation
-</programlisting>
-
- </sect1>
-
-
-<!-- ============================================================ -->
-
- <sect1 id="examples-basic">
- <title>Basic Techniques</title>
-
- <para>
- This section presents two basic techniques of using AspectJ, one each
- from the two fundamental ways of capturing crosscutting concerns:
- with dynamic join points and advice, and with static
- introduction. Advice changes an application's behavior. Introduction
- changes both an application's behavior and its structure.
- </para>
-
- <para>
- The first example, <xref linkend="examples-joinPoints" />, is about
- gathering and using information about the join point that has
- triggered some advice. The second example, <xref
- linkend="examples-roles" />, concerns a crosscutting view of an
- existing class hierarchy. </para>
-
-<!-- ======================================== -->
-
- <sect2 id="examples-joinPoints">
- <title>Join Points and <literal>thisJoinPoint</literal></title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/tjp</filename>.)
- </para>
-
- <para>
- A join point is some point in the execution of a program together
- with a view into the execution context when that point occurs. Join
- points are picked out by pointcuts. When a program reaches a join
- point, advice on that join point may run in addition to (or instead
- of) the join point itself.
- </para>
-
- <para>
- When using a pointcut that picks out join points of a single kind
- by name, typicaly the the advice will know exactly what kind of
- join point it is associated with. The pointcut may even publish
- context about the join point. Here, for example, since the only
- join points picked out by the pointcut are calls of a certain
- method, we can get the target value and one of the argument values
- of the method calls directly.
- </para>
-
-<programlisting><![CDATA[
-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;
- }
-}
-]]></programlisting>
-
- <para>
- But sometimes the shape of the join point is not so clear. For
- instance, suppose a complex application is being debugged, and we
- want to trace when any method of some class is executed. The
- pointcut
- </para>
-
-<programlisting><![CDATA[
-pointcut execsInProblemClass(): within(ProblemClass)
- && execution(* *(..));
-]]></programlisting>
-
- <para>
- will pick out each execution join point of every method defined
- within <classname>ProblemClass</classname>. Since advice executes
- at each join point picked out by the pointcut, we can reasonably
- ask which join point was reached.
- </para>
-
- <para>
- Information about the join point that was matched is available to
- advice through the special variable
- <varname>thisJoinPoint</varname>, of type <ulink
- url="../api/org/aspectj/lang/JoinPoint.html"><classname>org.aspectj.lang.JoinPoint</classname></ulink>.
- Through this object we can access information such as</para>
-
- <itemizedlist spacing="compact">
- <listitem>
- the kind of join point that was matched
- </listitem>
- <listitem>
- the source location of the code associated with the join point
- </listitem>
- <listitem>
- normal, short and long string representations of the
- current join point
- </listitem>
- <listitem>
- the actual argument values of the join point
- </listitem>
- <listitem>
- the signature of the member associated with the join point
- </listitem>
- <listitem>the currently executing object</listitem>
- <listitem>the target object</listitem>
- <listitem>
- an object encapsulating the static information about the join
- point. This is also available through the special variable
- <varname>thisJoinPointStaticPart</varname>.</listitem>
- </itemizedlist>
-
- <sect3>
- <title>The <classname>Demo</classname> class</title>
-
- <para>The class <classname>tjp.Demo</classname> in
- <filename>tjp/Demo.java</filename> defines two methods
- <literal>foo</literal> and <literal>bar</literal> with different
- parameter lists and return types. Both are called, with suitable
- arguments, by <classname>Demo</classname>'s
- <function>go</function> method which was invoked from within its
- <function>main</function> method.
- </para>
-
-<programlisting><![CDATA[
-public class Demo {
- static Demo d;
-
- public static void main(String[] args){
- new Demo().go();
- }
-
- void go(){
- d = new Demo();
- d.foo(1,d);
- System.out.println(d.bar(new Integer(3)));
- }
-
- void foo(int i, Object o){
- System.out.println("Demo.foo(" + i + ", " + o + ")\n");
- }
-
- String bar (Integer j){
- System.out.println("Demo.bar(" + j + ")\n");
- return "Demo.bar(" + j + ")";
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The <literal>GetInfo</literal> aspect</title>
-
- <para>
- This aspect uses around advice to intercept the execution of
- methods <literal>foo</literal> and <literal>bar</literal> in
- <classname>Demo</classname>, and prints out information garnered
- from <literal>thisJoinPoint</literal> to the console.
- </para>
-
-<programlisting><![CDATA[
-aspect GetInfo {
-
- static final void println(String s){ System.out.println(s); }
-
- pointcut goCut(): cflow(this(Demo) && execution(void go()));
-
- pointcut demoExecs(): within(Demo) && execution(* *(..));
-
- Object around(): demoExecs() && !execution(* go()) && goCut() {
- println("Intercepted message: " +
- thisJoinPointStaticPart.getSignature().getName());
- println("in class: " +
- thisJoinPointStaticPart.getSignature().getDeclaringType().getName());
- printParameters(thisJoinPoint);
- println("Running original method: \n" );
- Object result = proceed();
- println(" result: " + result );
- return result;
- }
-
- static private void printParameters(JoinPoint jp) {
- println("Arguments: " );
- Object[] args = jp.getArgs();
- String[] names = ((CodeSignature)jp.getSignature()).getParameterNames();
- Class[] types = ((CodeSignature)jp.getSignature()).getParameterTypes();
- for (int i = 0; i < args.length; i++) {
- println(" " + i + ". " + names[i] +
- " : " + types[i].getName() +
- " = " + args[i]);
- }
- }
-}
-]]></programlisting>
-
- <sect4>
- <title>Defining the scope of a pointcut</title>
-
- <para>The pointcut <function>goCut</function> is defined as
-
-<programlisting><![CDATA[
-cflow(this(Demo)) && execution(void go())
-]]></programlisting>
-
- so that only executions made in the control flow of
- <literal>Demo.go</literal> are intercepted. The control flow
- from the method <literal>go</literal> includes the execution of
- <literal>go</literal> itself, so the definition of the around
- advice includes <literal>!execution(* go())</literal> to
- exclude it from the set of executions advised. </para>
- </sect4>
-
- <sect4>
- <title>Printing the class and method name</title>
-
- <para>
- The name of the method and that method's defining class are
- available as parts of the <ulink
- url="../api/org/aspectj/lang/Signature.html">org.aspectj.lang.Signature</ulink>
- object returned by calling <literal>getSignature()</literal> on
- either <literal>thisJoinPoint</literal> or
- <literal>thisJoinPointStaticPart</literal>.
- </para>
- </sect4>
-
- <sect4>
- <title>Printing the parameters</title>
-
- <para>
- The static portions of the parameter details, the name and
- types of the parameters, can be accessed through the <ulink
- url="../api/org/aspectj/lang/reflect/CodeSignature.html"><literal>org.aspectj.lang.reflect.CodeSignature</literal></ulink>
- associated with the join point. All execution join points have code
- signatures, so the cast to <literal>CodeSignature</literal>
- cannot fail. </para>
-
- <para>
- The dynamic portions of the parameter details, the actual
- values of the parameters, are accessed directly from the
- execution join point object.
- </para>
- </sect4>
- </sect3>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="examples-roles">
- <title>Roles and Views</title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/introduction</filename>.)
- </para>
-
- <para>
- Like advice, inter-type declarations are members of an aspect. They
- declare members that act as if they were defined on another class.
- Unlike advice, inter-type declarations affect not only the behavior
- of the application, but also the structural relationship between an
- application's classes.
- </para>
-
- <para>
- This is crucial: Publically affecting the class structure of an
- application makes these modifications available to other components
- of the application.
- </para>
-
- <para>
- Aspects can declare inter-type
-
- <itemizedlist spacing="compact">
- <listitem>fields</listitem>
- <listitem>methods</listitem>
- <listitem>constructors</listitem>
- </itemizedlist>
-
- and can also declare that target types
-
- <itemizedlist spacing="compact">
- <listitem>implement new interfaces</listitem>
- <listitem>extend new classes</listitem>
- </itemizedlist>
- </para>
-
- <para>
- This example provides three illustrations of the use of inter-type
- declarations to encapsulate roles or views of a class. The class
- our aspect will be dealing with, <classname>Point</classname>, is a
- simple class with rectangular and polar coordinates. Our inter-type
- declarations will make the class <classname>Point</classname>, in
- turn, cloneable, hashable, and comparable. These facilities are
- provided by AspectJ without having to modify the code for the class
- <classname>Point</classname>.
- </para>
-
- <sect3>
- <title>The <classname>Point</classname> class</title>
-
- <para>The <classname>Point</classname> class defines geometric points
- whose interface includes polar and rectangular coordinates, plus some
- simple operations to relocate points. <classname>Point</classname>'s
- implementation has attributes for both its polar and rectangular
- coordinates, plus flags to indicate which currently reflect the
- position of the point. Some operations cause the polar coordinates to
- be updated from the rectangular, and some have the opposite effect.
- This implementation, which is in intended to give the minimum number
- of conversions between coordinate systems, has the property that not
- all the attributes stored in a <classname>Point</classname> object
- are necessary to give a canonical representation such as might be
- used for storing, comparing, cloning or making hash codes from
- points. Thus the aspects, though simple, are not totally trivial.
- </para>
-
- <para>
- The diagram below gives an overview of the aspects and their
- interaction with the class <classname>Point</classname>.</para>
-
- <para>
- <inlinemediaobject>
- <imageobject>
- <imagedata fileref="aspects.gif"/>
- </imageobject>
- </inlinemediaobject>
- </para>
- <para></para>
-
- </sect3>
-
- <sect3>
- <title>The <classname>CloneablePoint</classname> aspect</title>
-
- <para>
- This first aspect is responsible for
- <classname>Point</classname>'s implementation of the
- <classname>Cloneable</classname> interface. It declares that
- <literal>Point implements Cloneable</literal> with a
- <literal>declare parents</literal> form, and also publically
- declares a specialized <literal>Point</literal>'s
- <literal>clone()</literal> method. In Java, all objects inherit
- the method <literal>clone</literal> from the class
- <classname>Object</classname>, but an object is not cloneable
- unless its class also implements the interface
- <classname>Cloneable</classname>. In addition, classes
- frequently have requirements over and above the simple
- bit-for-bit copying that <literal>Object.clone</literal> does. In
- our case, we want to update a <classname>Point</classname>'s
- coordinate systems before we actually clone the
- <classname>Point</classname>. So our aspect makes sure that
- <literal>Point</literal> overrides
- <literal>Object.clone</literal> with a new method that does what
- we want.
- </para>
-
- <para>
- We also define a test <literal>main</literal> method in the
- aspect for convenience.
- </para>
-
-<programlisting><![CDATA[
-public aspect CloneablePoint {
-
- declare parents: Point implements Cloneable;
-
- public Object Point.clone() throws CloneNotSupportedException {
- // we choose to bring all fields up to date before cloning.
- makeRectangular();
- makePolar();
- return super.clone();
- }
-
- public static void main(String[] args){
- Point p1 = new Point();
- Point p2 = null;
-
- p1.setPolar(Math.PI, 1.0);
- try {
- p2 = (Point)p1.clone();
- } catch (CloneNotSupportedException e) {}
- System.out.println("p1 =" + p1 );
- System.out.println("p2 =" + p2 );
-
- p1.rotate(Math.PI / -2);
- System.out.println("p1 =" + p1 );
- System.out.println("p2 =" + p2 );
- }
-}
-]]></programlisting>
- </sect3>
-
- <sect3>
- <title>The <classname>ComparablePoint</classname> aspect</title>
-
- <para>
- <classname>ComparablePoint</classname> is responsible for
- <literal>Point</literal>'s implementation of the
- <literal>Comparable</literal> interface. </para>
-
- <para>
- The interface <classname>Comparable</classname> defines the
- single method <literal>compareTo</literal> which can be use to define
- a natural ordering relation among the objects of a class that
- implement it.
- </para>
-
- <para>
- <classname>ComparablePoint</classname> uses <literal>declare
- parents</literal> to declare that <literal>Point implements
- Comparable</literal>, and also publically declares the
- appropriate <literal>compareTo(Object)</literal> method: A
- <classname>Point</classname> <literal>p1</literal> is said to be
- less than another <classname>Point</classname><literal>
- p2</literal> if <literal>p1</literal> is closer to the
- origin.
- </para>
-
- <para>
- We also define a test <literal>main</literal> method in the
- aspect for convenience.
- </para>
-
-<programlisting><![CDATA[
-public aspect ComparablePoint {
-
- declare parents: Point implements Comparable;
-
- public int Point.compareTo(Object o) {
- return (int) (this.getRho() - ((Point)o).getRho());
- }
-
- public static void main(String[] args){
- Point p1 = new Point();
- Point p2 = new Point();
-
- System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
-
- p1.setRectangular(2,5);
- p2.setRectangular(2,5);
- System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
-
- p2.setRectangular(3,6);
- System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
-
- p1.setPolar(Math.PI, 4);
- p2.setPolar(Math.PI, 4);
- System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
-
- p1.rotate(Math.PI / 4.0);
- System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
-
- p1.offset(1,1);
- System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
- }
-}
-]]></programlisting>
- </sect3>
-
- <sect3>
- <title>The <classname>HashablePoint</classname> aspect</title>
-
- <para>
- Our third aspect is responsible for <literal>Point</literal>'s
- overriding of <literal>Object</literal>'s
- <literal>equals</literal> and <literal>hashCode</literal> methods
- in order to make <literal>Point</literal>s hashable.
- </para>
-
- <para>
- 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
- <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
- <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
- <function>equals</function> and <function>hashCode</function> to work
- correctly with objects of type <classname>Point</classname>. For
- example, we want two <classname>Point</classname> objects to test
- equal when they have the same <literal>x</literal> and
- <literal>y</literal> values, or the same <literal>rho</literal> and
- <literal>theta</literal> values, not just when they refer to the same
- object. We do this by overriding the methods
- <literal>equals</literal> and <literal>hashCode</literal> in the
- class <classname>Point</classname>.
- </para>
-
- <para>
- So <classname>HashablePoint</classname> declares
- <literal>Point</literal>'s <literal>hashCode</literal> and
- <literal>equals</literal> methods, using
- <classname>Point</classname>'s rectangular coordinates to
- generate a hash code and to test for equality. The
- <literal>x</literal> and <literal>y</literal> coordinates are
- obtained using the appropriate get methods, which ensure the
- rectangular coordinates are up-to-date before returning their
- values.
- </para>
-
- <para>
- And again, we supply a <literal>main</literal> method in the
- aspect for testing.
- </para>
-
-<programlisting><![CDATA[
-public aspect HashablePoint {
-
- public int Point.hashCode() {
- return (int) (getX() + getY() % Integer.MAX_VALUE);
- }
-
- public boolean Point.equals(Object o) {
- if (o == this) { return true; }
- if (!(o instanceof Point)) { return false; }
- Point other = (Point)o;
- return (getX() == other.getX()) && (getY() == other.getY());
- }
-
- public static void main(String[] args) {
- Hashtable h = new Hashtable();
- Point p1 = new Point();
-
- p1.setRectangular(10, 10);
- Point p2 = new Point();
-
- p2.setRectangular(10, 10);
-
- System.out.println("p1 = " + p1);
- System.out.println("p2 = " + p2);
- System.out.println("p1.hashCode() = " + p1.hashCode());
- System.out.println("p2.hashCode() = " + p2.hashCode());
-
- h.put(p1, "P1");
- System.out.println("Got: " + h.get(p2));
- }
-}
-]]></programlisting>
-
- </sect3>
- </sect2>
- </sect1>
-
-<!-- ============================================================ -->
-<!-- ============================================================ -->
-
- <sect1 id="examples-development">
- <title>Development Aspects</title>
-
- <sect2 id="tracing-using-aspects" xreflabel="tracing-using-aspects">
- <title>Tracing using aspects</title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/tracing</filename>.)
- </para>
-
- <para>
- Writing a class that provides tracing functionality is easy: a
- couple of functions, a boolean flag for turning tracing on and
- off, a choice for an output stream, maybe some code for
- formatting the output -- these are all elements that
- <classname>Trace</classname> classes have been known to
- have. <classname>Trace</classname> classes may be highly
- sophisticated, too, if the task of tracing the execution of a
- program demands it.
- </para>
-
- <para>
- But developing the support for tracing is just one part of the
- effort of inserting tracing into a program, and, most likely, not
- the biggest part. The other part of the effort is calling the
- tracing functions at appropriate times. In large systems, this
- interaction with the tracing support can be overwhelming. Plus,
- tracing is one of those things that slows the system down, so
- these calls should often be pulled out of the system before the
- product is shipped. For these reasons, it is not unusual for
- developers to write ad-hoc scripting programs that rewrite the
- source code by inserting/deleting trace calls before and after
- the method bodies.
- </para>
-
- <para>
- AspectJ can be used for some of these tracing concerns in a less
- ad-hoc way. Tracing can be seen as a concern that crosscuts the
- entire system and as such is amenable to encapsulation in an
- aspect. In addition, it is fairly independent of what the system
- is doing. Therefore tracing is one of those kind of system
- aspects that can potentially be plugged in and unplugged without
- any side-effects in the basic functionality of the system.
- </para>
-
- <sect3>
- <title>An Example Application</title>
-
- <para>
- Throughout this example we will use a simple application that
- contains only four classes. The application is about shapes. The
- <classname>TwoDShape</classname> class is the root of the shape
- hierarchy:
- </para>
-
-<programlisting><![CDATA[
-public abstract class TwoDShape {
- protected double x, y;
- protected TwoDShape(double x, double y) {
- this.x = x; this.y = y;
- }
- public double getX() { return x; }
- public double getY() { return y; }
- public double distance(TwoDShape s) {
- double dx = Math.abs(s.getX() - x);
- double dy = Math.abs(s.getY() - y);
- return Math.sqrt(dx*dx + dy*dy);
- }
- public abstract double perimeter();
- public abstract double area();
- public String toString() {
- return (" @ (" + String.valueOf(x) + ", " + String.valueOf(y) + ") ");
- }
-}
-]]></programlisting>
-
- <para>
- <classname>TwoDShape</classname> has two subclasses,
- <classname>Circle</classname> and <classname>Square</classname>:
- </para>
-
-<programlisting><![CDATA[
-public class Circle extends TwoDShape {
- protected double r;
- public Circle(double x, double y, double r) {
- super(x, y); this.r = r;
- }
- public Circle(double x, double y) { this( x, y, 1.0); }
- public Circle(double r) { this(0.0, 0.0, r); }
- public Circle() { this(0.0, 0.0, 1.0); }
- public double perimeter() {
- return 2 * Math.PI * r;
- }
- public double area() {
- return Math.PI * r*r;
- }
- public String toString() {
- return ("Circle radius = " + String.valueOf(r) + super.toString());
- }
-}
-]]></programlisting>
-
-<programlisting><![CDATA[
-public class Square extends TwoDShape {
- protected double s; // side
- public Square(double x, double y, double s) {
- super(x, y); this.s = s;
- }
- public Square(double x, double y) { this( x, y, 1.0); }
- public Square(double s) { this(0.0, 0.0, s); }
- public Square() { this(0.0, 0.0, 1.0); }
- public double perimeter() {
- return 4 * s;
- }
- public double area() {
- return s*s;
- }
- public String toString() {
- return ("Square side = " + String.valueOf(s) + super.toString());
- }
-}
-]]></programlisting>
-
- <para>
- To run this application, compile the classes. You can do it with or
- without ajc, the AspectJ compiler. If you've installed AspectJ, go
- to the directory
- <filename><replaceable>InstallDir</replaceable>/examples</filename>
- and type:
- </para>
-
-<programlisting>
-ajc -argfile tracing/notrace.lst
-</programlisting>
-
- <para>To run the program, type</para>
-
-<programlisting>
-java tracing.ExampleMain
-</programlisting>
-
- <para>(we don't need anything special on the classpath since this is pure
- Java code). You should see the following output:</para>
-
-<programlisting><![CDATA[
-c1.perimeter() = 12.566370614359172
-c1.area() = 12.566370614359172
-s1.perimeter() = 4.0
-s1.area() = 1.0
-c2.distance(c1) = 4.242640687119285
-s1.distance(c1) = 2.23606797749979
-s1.toString(): Square side = 1.0 @ (1.0, 2.0)
-]]></programlisting>
-
- </sect3>
- <sect3>
- <title>Tracing - Version 1</title>
-
- <para>
- In a first attempt to insert tracing in this application, we will
- start by writing a <classname>Trace</classname> class that is
- exactly what we would write if we didn't have aspects. The
- implementation is in <filename>version1/Trace.java</filename>. Its
- public interface is:
- </para>
-
-<programlisting><![CDATA[
-public class Trace {
- public static int TRACELEVEL = 0;
- public static void initStream(PrintStream s) {...}
- public static void traceEntry(String str) {...}
- public static void traceExit(String str) {...}
-}
-]]></programlisting>
-
- <para>
- If we didn't have AspectJ, we would have to insert calls to
- <literal>traceEntry</literal> and <literal>traceExit</literal> in
- all methods and constructors we wanted to trace, and to initialize
- <literal>TRACELEVEL</literal> and the stream. If we wanted to trace
- all the methods and constructors in our example, that would amount
- to around 40 calls, and we would hope we had not forgotten any
- method. But we can do that more consistently and reliably with the
- following aspect (found in
- <filename>version1/TraceMyClasses.java</filename>):
- </para>
-
-<programlisting><![CDATA[
-aspect TraceMyClasses {
- pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square);
- pointcut myConstructor(): myClass() && execution(new(..));
- pointcut myMethod(): myClass() && execution(* *(..));
-
- before (): myConstructor() {
- Trace.traceEntry("" + thisJoinPointStaticPart.getSignature());
- }
- after(): myConstructor() {
- Trace.traceExit("" + thisJoinPointStaticPart.getSignature());
- }
-
- before (): myMethod() {
- Trace.traceEntry("" + thisJoinPointStaticPart.getSignature());
- }
- after(): myMethod() {
- Trace.traceExit("" + thisJoinPointStaticPart.getSignature());
- }
-}]]></programlisting>
-
- <para>
- This aspect performs the tracing calls at appropriate
- times. According to this aspect, tracing is performed at the
- entrance and exit of every method and constructor defined within
- the shape hierarchy.
- </para>
-
- <para>
- What is printed at before and after each of the traced join points
- is the signature of the method executing. Since the signature is
- static information, we can get it through
- <literal>thisJoinPointStaticPart</literal>.
- </para>
-
- <para>
- To run this version of tracing, go to the directory
- <filename><replaceable>InstallDir</replaceable>/examples</filename>
- and type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile tracing/tracev1.lst
-]]></programlisting>
-
- <para>
- Running the main method of
- <classname>tracing.version1.TraceMyClasses</classname> should produce
- the output:
- </para>
-
-<programlisting><![CDATA[
- --> tracing.TwoDShape(double, double)
- <-- tracing.TwoDShape(double, double)
- --> tracing.Circle(double, double, double)
- <-- tracing.Circle(double, double, double)
- --> tracing.TwoDShape(double, double)
- <-- tracing.TwoDShape(double, double)
- --> tracing.Circle(double, double, double)
- <-- tracing.Circle(double, double, double)
- --> tracing.Circle(double)
- <-- tracing.Circle(double)
- --> tracing.TwoDShape(double, double)
- <-- tracing.TwoDShape(double, double)
- --> tracing.Square(double, double, double)
- <-- tracing.Square(double, double, double)
- --> tracing.Square(double, double)
- <-- tracing.Square(double, double)
- --> double tracing.Circle.perimeter()
- <-- double tracing.Circle.perimeter()
-c1.perimeter() = 12.566370614359172
- --> double tracing.Circle.area()
- <-- double tracing.Circle.area()
-c1.area() = 12.566370614359172
- --> double tracing.Square.perimeter()
- <-- double tracing.Square.perimeter()
-s1.perimeter() = 4.0
- --> double tracing.Square.area()
- <-- double tracing.Square.area()
-s1.area() = 1.0
- --> double tracing.TwoDShape.distance(TwoDShape)
- --> double tracing.TwoDShape.getX()
- <-- double tracing.TwoDShape.getX()
- --> double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.distance(TwoDShape)
-c2.distance(c1) = 4.242640687119285
- --> double tracing.TwoDShape.distance(TwoDShape)
- --> double tracing.TwoDShape.getX()
- <-- double tracing.TwoDShape.getX()
- --> double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.distance(TwoDShape)
-s1.distance(c1) = 2.23606797749979
- --> String tracing.Square.toString()
- --> String tracing.TwoDShape.toString()
- <-- String tracing.TwoDShape.toString()
- <-- String tracing.Square.toString()
-s1.toString(): Square side = 1.0 @ (1.0, 2.0)
-]]></programlisting>
-
- <para>
- When <filename>TraceMyClasses.java</filename> is not provided to
- <command>ajc</command>, the aspect does not have any affect on the
- system and the tracing is unplugged.
- </para>
- </sect3>
-
- <sect3>
- <title>Tracing - Version 2</title>
-
- <para>
- Another way to accomplish the same thing would be to write a
- reusable tracing aspect that can be used not only for these
- application classes, but for any class. One way to do this is to
- merge the tracing functionality of
- <literal>Trace - version1</literal> with the crosscutting
- support of <literal>TraceMyClasses - version1</literal>. We end
- up with a <literal>Trace</literal> aspect (found in
- <filename>version2/Trace.java</filename>) with the following public
- interface
- </para>
-
-<programlisting><![CDATA[
-abstract aspect Trace {
-
- public static int TRACELEVEL = 2;
- public static void initStream(PrintStream s) {...}
- protected static void traceEntry(String str) {...}
- protected static void traceExit(String str) {...}
- abstract pointcut myClass();
-}
-]]></programlisting>
-
- <para>
- In order to use it, we need to define our own subclass that knows
- about our application classes, in
- <filename>version2/TraceMyClasses.java</filename>:
- </para>
-
-<programlisting><![CDATA[
-public aspect TraceMyClasses extends Trace {
- pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square);
-
- public static void main(String[] args) {
- Trace.TRACELEVEL = 2;
- Trace.initStream(System.err);
- ExampleMain.main(args);
- }
-}
-]]></programlisting>
-
- <para>
- Notice that we've simply made the pointcut
- <literal>classes</literal>, that was an abstract pointcut in the
- super-aspect, concrete. To run this version of tracing, go to the
- directory <filename>examples</filename> and type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile tracing/tracev2.lst
-]]></programlisting>
-
- <para>
- The file tracev2.lst lists the application classes as well as this
- version of the files Trace.java and TraceMyClasses.java. Running
- the main method of
- <classname>tracing.version2.TraceMyClasses</classname> should
- output exactly the same trace information as that from version 1.
- </para>
-
- <para>
- The entire implementation of the new <classname>Trace</classname>
- class is:
- </para>
-
-<programlisting><![CDATA[
-abstract aspect Trace {
-
- // implementation part
-
- public static int TRACELEVEL = 2;
- protected static PrintStream stream = System.err;
- protected static int callDepth = 0;
-
- public static void initStream(PrintStream s) {
- stream = s;
- }
- protected static void traceEntry(String str) {
- if (TRACELEVEL == 0) return;
- if (TRACELEVEL == 2) callDepth++;
- printEntering(str);
- }
- protected static void traceExit(String str) {
- if (TRACELEVEL == 0) return;
- printExiting(str);
- if (TRACELEVEL == 2) callDepth--;
- }
- private static void printEntering(String str) {
- printIndent();
- stream.println("--> " + str);
- }
- private static void printExiting(String str) {
- printIndent();
- stream.println("<-- " + str);
- }
- private static void printIndent() {
- for (int i = 0; i < callDepth; i++)
- stream.print(" ");
- }
-
- // protocol part
-
- abstract pointcut myClass();
-
- pointcut myConstructor(): myClass() && execution(new(..));
- pointcut myMethod(): myClass() && execution(* *(..));
-
- before(): myConstructor() {
- traceEntry("" + thisJoinPointStaticPart.getSignature());
- }
- after(): myConstructor() {
- traceExit("" + thisJoinPointStaticPart.getSignature());
- }
-
- before(): myMethod() {
- traceEntry("" + thisJoinPointStaticPart.getSignature());
- }
- after(): myMethod() {
- traceExit("" + thisJoinPointStaticPart.getSignature());
- }
-}
-]]></programlisting>
-
- <para>
- This version differs from version 1 in several subtle ways. The
- first thing to notice is that this <classname>Trace</classname>
- class merges the functional part of tracing with the crosscutting
- of the tracing calls. That is, in version 1, there was a sharp
- separation between the tracing support (the class
- <classname>Trace</classname>) and the crosscutting usage of it (by
- the class <classname>TraceMyClasses</classname>). In this version
- those two things are merged. That's why the description of this
- class explicitly says that "Trace messages are printed before and
- after constructors and methods are," which is what we wanted in the
- first place. That is, the placement of the calls, in this version,
- is established by the aspect class itself, leaving less opportunity
- for misplacing calls.</para>
-
- <para>
- A consequence of this is that there is no need for providing
- <literal>traceEntry</literal> and <literal>traceExit</literal> as
- public operations of this class. You can see that they were
- classified as protected. They are supposed to be internal
- implementation details of the advice.
- </para>
-
- <para>
- The key piece of this aspect is the abstract pointcut classes that
- serves as the base for the definition of the pointcuts constructors
- and methods. Even though <classname>classes</classname> is
- abstract, and therefore no concrete classes are mentioned, we can
- put advice on it, as well as on the pointcuts that are based on
- it. The idea is "we don't know exactly what the pointcut will be,
- but when we do, here's what we want to do with it." In some ways,
- abstract pointcuts are similar to abstract methods. Abstract
- methods don't provide the implementation, but you know that the
- concrete subclasses will, so you can invoke those methods.
- </para>
- </sect3>
- </sect2>
- </sect1>
-
-<!-- ============================================================ -->
-<!-- ============================================================ -->
-
- <sect1 id="examples-production">
- <title>Production Aspects</title>
-
- <!-- ==================== -->
-
- <sect2 id="a-bean-aspect" xreflabel="a-bean-aspect"><!-- A Bean Aspect -->
- <title>A Bean Aspect</title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/bean</filename>.)
- </para>
-
- <para>
- This example examines an aspect that makes Point objects into
- Java beans with bound properties.
- </para>
-
- <para>
- Java beans are reusable software components that can be visually
- manipulated in a builder tool. The requirements for an object to be
- a bean are few. Beans must define a no-argument constructor and
- must be either <classname>Serializable</classname> or
- <classname>Externalizable</classname>. Any properties of the object
- that are to be treated as bean properties should be indicated by
- the presence of appropriate <literal>get</literal> and
- <literal>set</literal> methods whose names are
- <literal>get</literal><emphasis>property</emphasis> and
- <literal>set </literal><emphasis>property</emphasis> where
- <emphasis>property</emphasis> is the name of a field in the bean
- class. Some bean properties, known as bound properties, fire events
- whenever their values change so that any registered listeners (such
- as, other beans) will be informed of those changes. Making a bound
- property involves keeping a list of registered listeners, and
- creating and dispatching event objects in methods that change the
- property values, such as set<emphasis>property</emphasis>
- methods.
- </para>
-
- <para>
- <classname>Point</classname> is a simple class representing points
- with rectangular coordinates. <classname>Point</classname> does not
- know anything about being a bean: there are set methods for
- <literal>x</literal> and <literal>y</literal> but they do not fire
- events, and the class is not serializable. Bound is an aspect that
- makes <classname>Point</classname> a serializable class and makes
- its <literal>get</literal> and <literal>set</literal> methods
- support the bound property protocol.
- </para>
-
- <sect3>
- <title>The <classname>Point</classname> class</title>
-
- <para>
- The <classname>Point</classname> class is a very simple class with
- trivial getters and setters, and a simple vector offset method.
- </para>
-
-<programlisting><![CDATA[
-class Point {
-
- protected int x = 0;
- protected int y = 0;
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- public void setRectangular(int newX, int newY) {
- setX(newX);
- setY(newY);
- }
-
- public void setX(int newX) {
- x = newX;
- }
-
- public void setY(int newY) {
- y = newY;
- }
-
- public void offset(int deltaX, int deltaY) {
- setRectangular(x + deltaX, y + deltaY);
- }
-
- public String toString() {
- return "(" + getX() + ", " + getY() + ")" ;
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The <classname>BoundPoint</classname> aspect</title>
-
- <para>
- The <classname>BoundPoint</classname> aspect is responsible for
- <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>.
-
-<programlisting><![CDATA[
-private PropertyChangeSupport Point.support = new PropertyChangeSupport(this);
-]]></programlisting>
-
- The property change support object must be constructed with a
- reference to the bean for which it is providing support, so it is
- initialized by passing it <literal>this</literal>, an instance of
- <classname>Point</classname>. Since the <literal>support</literal>
- field is private declared in the aspect, only the code in the
- aspect can refer to it.
- </para>
-
- <para>
- The aspect also declares <literal>Point</literal>'s methods for
- registering and managing listeners for property change events,
- 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){
-
- 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>
-
- <para>
- The aspect is also responsible for making sure
- <classname>Point</classname> implements the
- <classname>Serializable</classname> interface:
-
-<programlisting><![CDATA[
-declare parents: Point implements Serializable;
-]]></programlisting>
-
- Implementing this interface in Java does not require any methods to
- be implemented. Serialization for <classname>Point</classname>
- objects is provided by the default serialization method.
- </para>
-
- <para>
- The <function>setters</function> pointcut picks out calls to the
- <literal>Point</literal>'s <literal>set</literal> methods: any
- method whose name begins with "<literal>set</literal>" and takes
- one parameter. The around advice on <literal>setters()</literal>
- stores the values of the <literal>X</literal> and
- <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.
- </para>
-
-<programlisting><![CDATA[
-aspect BoundPoint {
- private PropertyChangeSupport Point.support = new PropertyChangeSupport(this);
-
- 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);
- }
-
- declare parents: Point implements Serializable;
-
- pointcut setter(Point p): call(void Point.set*(*)) && target(p);
-
- void around(Point p): setter(p) {
- String propertyName =
- thisJoinPointStaticPart.getSignature().getName().substring("set".length());
- int oldX = p.getX();
- int oldY = p.getY();
- proceed(p);
- if (propertyName.equals("X")){
- firePropertyChange(p, propertyName, oldX, p.getX());
- } else {
- firePropertyChange(p, propertyName, oldY, p.getY());
- }
- }
-
- void firePropertyChange(Point p,
- String property,
- double oldval,
- double newval) {
- p.support.firePropertyChange(property,
- new Double(oldval),
- new Double(newval));
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The Test Program</title>
-
- <para>
- The test program registers itself as a property change listener to
- a <literal>Point</literal> object that it creates and then performs
- simple manipulation of that point: calling its set methods and the
- offset method. Then it serializes the point and writes it to a file
- and then reads it back. The result of saving and restoring the
- point is that a new point is created.
- </para>
-
-<programlisting><![CDATA[
-class Demo implements PropertyChangeListener {
-
- 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);
- }
- ...
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>Compiling and Running the Example</title>
-
- <para>
- To compile and run this example, go to the examples directory and type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile bean/files.lst
-java bean.Demo
-]]></programlisting>
-
- </sect3>
- </sect2>
-
- <!-- ==================== -->
-
- <sect2 id="the-subject-observer-protocol" xreflabel="the-subject-observer-protocol">
- <title>The Subject/Observer Protocol</title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/observer</filename>.)
- </para>
-
- <para>
- This demo illustrates how the Subject/Observer design pattern can be
- coded with aspects.
- </para>
-
- <para>
- The demo consists of the following: A colored label is a
- renderable object that has a color that cycles through a set of
- colors, and a number that records the number of cycles it has been
- through. A button is an action item that records when it is
- clicked.
- </para>
-
- <para>
- With these two kinds of objects, we can build up a Subject/Observer
- relationship in which colored labels observe the clicks of buttons;
- that is, where colored labels are the observers and buttons are the
- subjects.
- </para>
-
- <para>
- The demo is designed and implemented using the Subject/Observer
- design pattern. The remainder of this example explains the classes
- and aspects of this demo, and tells you how to run it.
- </para>
-
- <sect3>
- <title>Generic Components</title>
-
- <para>
- The generic parts of the protocol are the interfaces
- <classname>Subject</classname> and <classname>Observer</classname>,
- and the abstract aspect
- <classname>SubjectObserverProtocol</classname>. The
- <classname>Subject</classname> interface is simple, containing
- methods to add, remove, and view <classname>Observer</classname>
- objects, and a method for getting data about state changes:
- </para>
-
-<programlisting><![CDATA[
-interface Subject {
- void addObserver(Observer obs);
- void removeObserver(Observer obs);
- Vector getObservers();
- Object getData();
-}
-]]></programlisting>
-
- <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();
-}
-]]></programlisting>
-
- <para>
- The <classname>SubjectObserverProtocol</classname> aspect contains
- within it all of the generic parts of the protocol, namely, how to
- fire the <classname>Observer</classname> objects' update methods
- when some state changes in a subject.
- </para>
-
-<programlisting><![CDATA[
-abstract aspect SubjectObserverProtocol {
-
- 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();
- }
- }
-
- 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; }
-
-}
-]]></programlisting>
-
- <para>
- Note that this aspect does three things. It define an abstract
- 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>.
- </para>
- </sect3>
-
- <sect3>
- <title>Application Classes</title>
-
- <para>
- <classname>Button</classname> objects extend
- <classname>java.awt.Button</classname>, and all they do is make
- sure the <literal>void click()</literal> method is called whenever
- a button is clicked.
- </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);
- }
-
- public void click() {}
-
-}
-]]></programlisting>
-
- <para>
- Note that this class knows nothing about being a Subject.
- </para>
-
- <para>
- ColorLabel objects are labels that support the void colorCycle()
- method. Again, they know nothing about being an observer.
- </para>
-
-<programlisting><![CDATA[
-class ColorLabel extends Label {
-
- 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);
- }
-}
-]]></programlisting>
-
- <para>
- Finally, the <classname>SubjectObserverProtocolImpl</classname>
- implements the subject/observer protocol, with
- <classname>Button</classname> objects as subjects and
- <classname>ColorLabel</classname> objects as observers:
- </para>
-
-<programlisting><![CDATA[
-package observer;
-
-import java.util.Vector;
-
-aspect SubjectObserverProtocolImpl extends SubjectObserverProtocol {
-
- declare parents: Button implements Subject;
- public Object Button.getData() { return this; }
-
- declare parents: ColorLabel implements Observer;
- public void ColorLabel.update() {
- colorCycle();
- }
-
- pointcut stateChanges(Subject s):
- target(s) &&
- call(void Button.click());
-
-}
-]]></programlisting>
-
- <para>
- It does this by assuring that <classname>Button</classname> and
- <classname>ColorLabel</classname> implement the appropriate
- interfaces, declaring that they implement the methods required by
- those interfaces, and providing a definition for the abstract
- <literal>stateChanges</literal> pointcut. Now, every time a
- <classname>Button</classname> is clicked, all
- <classname>ColorLabel</classname> objects observing that button
- will <literal>colorCycle</literal>.
- </para>
- </sect3>
-
- <sect3>
- <title>Compiling and Running</title>
-
- <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
- the <filename>examples</filename> directory and type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile observer/files.lst
-java observer.Demo
-]]></programlisting>
-
- </sect3>
- </sect2>
-
- <!-- ==================== -->
-
- <sect2 id="a-simple-telecom-simulation" xreflabel="a-simple-telecom-simulation">
- <title>A Simple Telecom Simulation</title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/telecom</filename>.)
- </para>
-
- <para>
- This example illustrates some ways that dependent concerns can be
- encoded with aspects. It uses an example system comprising a simple
- model of telephone connections to which timing and billing features
- are added using aspects, where the billing feature depends upon the
- timing feature.
- </para>
-
- <sect3>
- <title>The Application</title>
-
- <para>
- The example application is a simple simulation of a telephony
- system in which customers make, accept, merge and hang-up both
- local and long distance calls. The application architecture is in
- three layers.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- The basic objects provide basic functionality to simulate
- customers, calls and connections (regular calls have one
- connection, conference calls have more than one).
- </para>
- </listitem>
-
- <listitem>
- <para>
- The timing feature is concerned with timing the connections
- and keeping the total connection time per customer. Aspects
- are used to add a timer to each connection and to manage the
- total time per customer.
- </para>
- </listitem>
-
- <listitem>
- <para>
- The billing feature is concerned with charging customers for
- the calls they make. Aspects are used to calculate a charge
- per connection and, upon termination of a connection, to add
- the charge to the appropriate customer's bill. The billing
- aspect builds upon the timing aspect: it uses a pointcut
- defined in Timing and it uses the timers that are associated
- with connections.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- The simulation of system has three configurations: basic, timing
- and billing. Programs for the three configurations are in classes
- <classname>BasicSimulation</classname>,
- <classname>TimingSimulation</classname> and
- <classname>BillingSimulation</classname>. These share a common
- superclass <classname>AbstractSimulation</classname>, which
- defines the method run with the simulation itself and the method
- wait used to simulate elapsed time.
- </para>
- </sect3>
-
- <sect3>
- <title>The Basic Objects</title>
-
- <para>
- The telecom simulation comprises the classes
- <classname>Customer</classname>, <classname>Call</classname> and
- the abstract class <classname>Connection</classname> with its two
- concrete subclasses <classname>Local</classname> and
- <classname>LongDistance</classname>. Customers have a name and a
- numeric area code. They also have methods for managing
- calls. Simple calls are made between one customer (the caller)
- and another (the receiver), a <classname>Connection</classname>
- object is used to connect them. Conference calls between more
- than two customers will involve more than one connection. A
- customer may be involved in many calls at one time.
-
- <inlinemediaobject>
- <imageobject>
- <imagedata fileref="telecom.gif"/>
- </imageobject>
- </inlinemediaobject>
- </para>
-
- </sect3>
-
- <sect3>
- <title>The <classname>Customer</classname> class</title>
-
- <para>
- <classname>Customer</classname> has methods
- <literal>call</literal>, <literal>pickup</literal>,
- <literal>hangup</literal> and <literal>merge</literal> for
- managing calls.
- </para>
-
-<programlisting><![CDATA[
-public class Customer {
-
- private String name;
- private int areacode;
- private Vector calls = new Vector();
-
- protected void removeCall(Call c){
- calls.removeElement(c);
- }
-
- protected void addCall(Call c){
- calls.addElement(c);
- }
-
- public Customer(String name, int areacode) {
- this.name = name;
- this.areacode = areacode;
- }
-
- public String toString() {
- return name + "(" + areacode + ")";
- }
-
- public int getAreacode(){
- return areacode;
- }
-
- public boolean localTo(Customer other){
- return areacode == other.areacode;
- }
-
- public Call call(Customer receiver) {
- Call call = new Call(this, receiver);
- addCall(call);
- return call;
- }
-
- public void pickup(Call call) {
- call.pickup();
- addCall(call);
- }
-
- public void hangup(Call call) {
- call.hangup(this);
- removeCall(call);
- }
-
- public void merge(Call call1, Call call2){
- call1.merge(call2);
- removeCall(call2);
- }
- }
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The <classname>Call</classname> class</title>
-
- <para>
- Calls are created with a caller and receiver who are customers. If
- the caller and receiver have the same area code then the call can
- be established with a <classname>Local</classname> connection (see
- below), otherwise a <classname>LongDistance</classname> connection
- is required. A call comprises a number of connections between
- customers. Initially there is only the connection between the
- caller and receiver but additional connections can be added if
- calls are merged to form conference calls.
- </para>
- </sect3>
-
- <sect3>
- <title>The <classname>Connection</classname> class</title>
-
- <para>
- The class <classname>Connection</classname> models the physical
- details of establishing a connection between customers. It does
- this with a simple state machine (connections are initially
- <literal>PENDING</literal>, then <literal>COMPLETED</literal> and
- finally <literal>DROPPED</literal>). Messages are printed to the
- console so that the state of connections can be
- observed. Connection is an abstract class with two concrete
- subclasses: <classname>Local</classname> and
- <classname>LongDistance</classname>.
- </para>
-
-<programlisting><![CDATA[
-abstract class Connection {
-
- 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;
-
- Connection(Customer a, Customer b) {
- this.caller = a;
- this.receiver = b;
- }
-
- public int getState(){
- return state;
- }
-
- public Customer getCaller() { return caller; }
-
- public Customer getReceiver() { return receiver; }
-
- void complete() {
- state = COMPLETE;
- System.out.println("connection completed");
- }
-
- void drop() {
- state = DROPPED;
- System.out.println("connection dropped");
- }
-
- public boolean connects(Customer c){
- return (caller == c || receiver == c);
- }
-
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The <literal>Local</literal> and <literal>LongDistance</literal> classes</title>
-
- <para>
- The two kinds of connections supported by our simulation are
- <literal>Local</literal> and <literal>LongDistance</literal>
- connections.
- </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 + "]");
- }
-}
-]]></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 + "]");
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>Compiling and Running the Basic Simulation</title>
-
- <para>
- The source files for the basic system are listed in the file
- <filename>basic.lst</filename>. To build and run the basic system,
- in a shell window, type these commands:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile telecom/basic.lst
-java telecom.BasicSimulation
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The Timing aspect</title>
-
- <para>
- The <classname>Timing</classname> aspect keeps track of total
- connection time for each <classname>Customer</classname> by
- starting and stopping a timer associated with each connection. It
- uses some helper classes:
- </para>
-
- <sect4>
- <title>The <classname>Timer</classname> class</title>
-
- <para>
- A <classname>Timer</classname> object simply records the current
- time when it is started and stopped, and returns their difference
- when asked for the elapsed time. The aspect
- <classname>TimerLog</classname> (below) can be used to cause the
- start and stop times to be printed to standard output.
- </para>
-
-<programlisting><![CDATA[
-class Timer {
- long startTime, stopTime;
-
- public void start() {
- startTime = System.currentTimeMillis();
- stopTime = startTime;
- }
-
- public void stop() {
- stopTime = System.currentTimeMillis();
- }
-
- public long getTime() {
- return stopTime - startTime;
- }
-}
-]]></programlisting>
-
- </sect4>
- </sect3>
-
- <sect3>
- <title>The <classname>TimerLog</classname> aspect</title>
-
- <para>
- The <classname>TimerLog</classname> aspect can be included in a
- build to get the timer to announce when it is started and
- stopped.
- </para>
-
-<programlisting><![CDATA[
-public aspect TimerLog {
-
- after(Timer t): target(t) && call(* Timer.start()) {
- System.err.println("Timer started: " + t.startTime);
- }
-
- after(Timer t): target(t) && call(* Timer.stop()) {
- System.err.println("Timer stopped: " + t.stopTime);
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The <classname>Timing</classname> aspect</title>
-
- <para>
- The <classname>Timing</classname> aspect is declares an
- 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.
-
-<programlisting><![CDATA[
-public long Customer.totalConnectTime = 0;
-private Timer Connection.timer = new Timer();
-]]></programlisting>
-
- Two pieces of after advice ensure that the timer is started when
- a connection is completed and and stopped when it is dropped. The
- pointcut <literal>endTiming</literal> is defined so that it can
- be used by the <classname>Billing</classname> aspect.
- </para>
-
-<programlisting><![CDATA[
-public aspect Timing {
-
- public long Customer.totalConnectTime = 0;
-
- public long getTotalConnectTime(Customer cust) {
- return cust.totalConnectTime;
- }
- private Timer Connection.timer = new Timer();
- public Timer getTimer(Connection conn) { return conn.timer; }
-
- after (Connection c): target(c) && call(void Connection.complete()) {
- getTimer(c).start();
- }
-
- pointcut endTiming(Connection c): target(c) &&
- call(void Connection.drop());
-
- after(Connection c): endTiming(c) {
- getTimer(c).stop();
- c.getCaller().totalConnectTime += getTimer(c).getTime();
- c.getReceiver().totalConnectTime += getTimer(c).getTime();
- }
-}]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>The <literal>Billing</literal> aspect</title>
-
- <para>
- The Billing system adds billing functionality to the telecom
- application on top of timing.
- </para>
-
- <para>
- The <classname>Billing</classname> aspect declares that each
- <classname>Connection</classname> has a <literal>payer</literal>
- inter-type field to indicate who initiated the call and therefore
- who is responsible to pay for it. It also declares the inter-type
- method <literal>callRate</literal> of
- <classname>Connection</classname> so that local and long distance
- calls can be charged differently. The call charge must be
- calculated after the timer is stopped; the after advice on pointcut
- <literal>Timing.endTiming</literal> does this, and
- <classname>Billing</classname> is declared to be more precedent
- than <classname>Timing</classname> to make sure that this advice
- 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>.
- </para>
-
-<programlisting><![CDATA[
-public aspect Billing {
- // precedence required to get advice on endtiming in the right order
- declare precedence: Billing, Timing;
-
- public static final long LOCAL_RATE = 3;
- public static final long LONG_DISTANCE_RATE = 10;
-
- public Customer Connection.payer;
- public Customer getPayer(Connection conn) { return conn.payer; }
-
- after(Customer cust) returning (Connection conn):
- args(cust, ..) && call(Connection+.new(..)) {
- conn.payer = cust;
- }
-
- public abstract long Connection.callRate();
-
- public long LongDistance.callRate() { return LONG_DISTANCE_RATE; }
- public long Local.callRate() { return LOCAL_RATE; }
-
- after(Connection conn): Timing.endTiming(conn) {
- long time = Timing.aspectOf().getTimer(conn).getTime();
- long rate = conn.callRate();
- long cost = rate * time;
- getPayer(conn).addCharge(cost);
- }
-
- public long Customer.totalCharge = 0;
- public long getTotalCharge(Customer cust) { return cust.totalCharge; }
-
- public void Customer.addCharge(long charge){
- totalCharge += charge;
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>Accessing the inter-type state</title>
-
- <para>
- Both the aspects <classname>Timing</classname> and
- <classname>Billing</classname> contain the definition of operations
- that the rest of the system may want to access. For example, when
- running the simulation with one or both aspects, we want to find
- out how much time each customer spent on the telephone and how big
- their bill is. That information is also stored in the classes, but
- they are accessed through static methods of the aspects, since the
- state they refer to is private to the aspect.
- </para>
-
- <para>
- Take a look at the file
- <filename>TimingSimulation.java</filename>. The most important
- method of this class is the method
- <filename>report(Customer)</filename>, which is used in the method
- run of the superclass
- <classname>AbstractSimulation</classname>. This method is intended
- to print out the status of the customer, with respect to the
- <classname>Timing</classname> feature.
- </para>
-
-<programlisting><![CDATA[
-protected void report(Customer c){
- Timing t = Timing.aspectOf();
- System.out.println(c + " spent " + t.getTotalConnectTime(c));
-}
-]]></programlisting>
- </sect3>
-
- <sect3>
- <title>Compiling and Running</title>
-
- <para>
- The files timing.lst and billing.lst contain file lists for the
- timing and billing configurations. To build and run the application
- with only the timing feature, go to the directory examples and
- type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile telecom/timing.lst
-java telecom.TimingSimulation
-]]></programlisting>
-
- <para>
- To build and run the application with the timing and billing
- features, go to the directory examples and type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile telecom/billing.lst
-java telecom.BillingSimulation
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>Discussion</title>
-
- <para>
- There are some explicit dependencies between the aspects Billing
- and Timing:
-
- <itemizedlist>
- <listitem>
- <para>
- Billing is declared more precedent than Timing so that Billing's
- after advice runs after that of Timing when they are on the
- same join point.
- </para>
- </listitem>
-
- <listitem>
- <para>
- Billing uses the pointcut Timing.endTiming.
- </para>
- </listitem>
-
- <listitem>
- <para>
- Billing needs access to the timer associated with a connection.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </sect3>
- </sect2>
- </sect1>
-
-<!-- ============================================================ -->
-<!-- ============================================================ -->
-
- <sect1 id="examples-reusable">
- <title>Reusable Aspects</title>
-
- <sect2 id="tracing-using-aspects-revisited" xreflabel="tracing-using-aspects-revisited">
- <title>Tracing using Aspects, Revisited</title>
-
- <para>
- (The code for this example is in
- <filename><replaceable>InstallDir</replaceable>/examples/tracing</filename>.)
- </para>
-
- <sect3>
- <title>Tracing - Version 3</title>
-
- <para>
- One advantage of not exposing the methods traceEntry and
- traceExit as public operations is that we can easily change their
- interface without any dramatic consequences in the rest of the
- code.
- </para>
-
- <para>
- Consider, again, the program without AspectJ. Suppose, for
- example, that at some point later the requirements for tracing
- change, stating that the trace messages should always include the
- string representation of the object whose methods are being
- traced. This can be achieved in at least two ways. One way is
- keep the interface of the methods <literal>traceEntry</literal>
- and <literal>traceExit</literal> as it was before,
- </para>
-
-<programlisting><![CDATA[
-public static void traceEntry(String str);
-public static void traceExit(String str);
-]]></programlisting>
-
- <para>
- In this case, the caller is responsible for ensuring that the
- string representation of the object is part of the string given
- as argument. So, calls must look like:
- </para>
-
-<programlisting><![CDATA[
-Trace.traceEntry("Square.distance in " + toString());
-]]></programlisting>
-
- <para>
- Another way is to enforce the requirement with a second argument
- in the trace operations, e.g.
- </para>
-
-<programlisting><![CDATA[
-public static void traceEntry(String str, Object obj);
-public static void traceExit(String str, Object obj);
-]]></programlisting>
-
- <para>
- In this case, the caller is still responsible for sending the
- right object, but at least there is some guarantees that some
- object will be passed. The calls will look like:
- </para>
-
-<programlisting><![CDATA[
-Trace.traceEntry("Square.distance", this);
-]]></programlisting>
-
- <para>
- In either case, this change to the requirements of tracing will
- have dramatic consequences in the rest of the code -- every call
- to the trace operations traceEntry and traceExit must be changed!
- </para>
-
- <para>
- Here's another advantage of doing tracing with an aspect. We've
- already seen that in version 2 <literal>traceEntry</literal> and
- <literal>traceExit</literal> are not publicly exposed. So
- changing their interfaces, or the way they are used, has only a
- small effect inside the <classname>Trace</classname>
- class. Here's a partial view at the implementation of
- <classname>Trace</classname>, version 3. The differences with
- respect to version 2 are stressed in the comments:
- </para>
-
-<programlisting><![CDATA[
-abstract aspect Trace {
-
- public static int TRACELEVEL = 0;
- protected static PrintStream stream = null;
- protected static int callDepth = 0;
-
- public static void initStream(PrintStream s) {
- stream = s;
- }
-
- protected static void traceEntry(String str, Object o) {
- if (TRACELEVEL == 0) return;
- if (TRACELEVEL == 2) callDepth++;
- printEntering(str + ": " + o.toString());
- }
-
- protected static void traceExit(String str, Object o) {
- if (TRACELEVEL == 0) return;
- printExiting(str + ": " + o.toString());
- if (TRACELEVEL == 2) callDepth--;
- }
-
- private static void printEntering(String str) {
- printIndent();
- stream.println("Entering " + str);
- }
-
- private static void printExiting(String str) {
- printIndent();
- stream.println("Exiting " + str);
- }
-
- private static void printIndent() {
- for (int i = 0; i < callDepth; i++)
- stream.print(" ");
- }
-
- abstract pointcut myClass(Object obj);
-
- pointcut myConstructor(Object obj): myClass(obj) && execution(new(..));
- pointcut myMethod(Object obj): myClass(obj) &&
- execution(* *(..)) && !execution(String toString());
-
- before(Object obj): myConstructor(obj) {
- traceEntry("" + thisJoinPointStaticPart.getSignature(), obj);
- }
- after(Object obj): myConstructor(obj) {
- traceExit("" + thisJoinPointStaticPart.getSignature(), obj);
- }
-
- before(Object obj): myMethod(obj) {
- traceEntry("" + thisJoinPointStaticPart.getSignature(), obj);
- }
- after(Object obj): myMethod(obj) {
- traceExit("" + thisJoinPointStaticPart.getSignature(), obj);
- }
-}
-]]></programlisting>
-
- <para>
- As you can see, we decided to apply the first design by preserving
- the interface of the methods <literal>traceEntry</literal> and
- <literal>traceExit</literal>. But it doesn't matter - we could
- as easily have applied the second design (the code in the directory
- <filename>examples/tracing/version3</filename> has the second
- design). The point is that the effects of this change in the
- tracing requirements are limited to the
- <classname>Trace</classname> aspect class.
- </para>
-
- <para>
- One implementation change worth noticing is the specification of
- the pointcuts. They now expose the object. To maintain full
- consistency with the behavior of version 2, we should have included
- tracing for static methods, by defining another pointcut for static
- methods and advising it. We leave that as an exercise.
- </para>
-
- <para>
- Moreover, we had to exclude the execution join point of the method
- <filename>toString</filename> from the <literal>methods</literal>
- pointcut. The problem here is that <literal>toString</literal> is
- being called from inside the advice. Therefore if we trace it, we
- will end up in an infinite recursion of calls. This is a subtle
- point, and one that you must be aware when writing advice. If the
- advice calls back to the objects, there is always the possibility
- of recursion. Keep that in mind!
- </para>
-
- <para>
- In fact, esimply excluding the execution join point may not be
- enough, if there are calls to other traced methods within it -- in
- which case, the restriction should be
- </para>
-
-<programlisting><![CDATA[
-&& !cflow(execution(String toString()))
-]]></programlisting>
-
- <para>
- excluding both the execution of toString methods and all join
- points under that execution.
- </para>
-
- <para>
- In summary, to implement the change in the tracing requirements we
- had to make a couple of changes in the implementation of the
- <classname>Trace</classname> aspect class, including changing the
- specification of the pointcuts. That's only natural. But the
- implementation changes were limited to this aspect. Without
- aspects, we would have to change the implementation of every
- application class.
- </para>
-
- <para>
- Finally, to run this version of tracing, go to the directory
- <filename>examples</filename> and type:
- </para>
-
-<programlisting><![CDATA[
-ajc -argfile tracing/tracev3.lst
-]]></programlisting>
-
- <para>
- The file tracev3.lst lists the application classes as well as this
- version of the files <filename>Trace.java</filename> and
- <filename>TraceMyClasses.java</filename>. To run the program, type
- </para>
-
-<programlisting><![CDATA[
-java tracing.version3.TraceMyClasses
-]]></programlisting>
-
- <para>The output should be:</para>
-
-<programlisting><![CDATA[
- --> tracing.TwoDShape(double, double)
- <-- tracing.TwoDShape(double, double)
- --> tracing.Circle(double, double, double)
- <-- tracing.Circle(double, double, double)
- --> tracing.TwoDShape(double, double)
- <-- tracing.TwoDShape(double, double)
- --> tracing.Circle(double, double, double)
- <-- tracing.Circle(double, double, double)
- --> tracing.Circle(double)
- <-- tracing.Circle(double)
- --> tracing.TwoDShape(double, double)
- <-- tracing.TwoDShape(double, double)
- --> tracing.Square(double, double, double)
- <-- tracing.Square(double, double, double)
- --> tracing.Square(double, double)
- <-- tracing.Square(double, double)
- --> double tracing.Circle.perimeter()
- <-- double tracing.Circle.perimeter()
-c1.perimeter() = 12.566370614359172
- --> double tracing.Circle.area()
- <-- double tracing.Circle.area()
-c1.area() = 12.566370614359172
- --> double tracing.Square.perimeter()
- <-- double tracing.Square.perimeter()
-s1.perimeter() = 4.0
- --> double tracing.Square.area()
- <-- double tracing.Square.area()
-s1.area() = 1.0
- --> double tracing.TwoDShape.distance(TwoDShape)
- --> double tracing.TwoDShape.getX()
- <-- double tracing.TwoDShape.getX()
- --> double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.distance(TwoDShape)
-c2.distance(c1) = 4.242640687119285
- --> double tracing.TwoDShape.distance(TwoDShape)
- --> double tracing.TwoDShape.getX()
- <-- double tracing.TwoDShape.getX()
- --> double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.getY()
- <-- double tracing.TwoDShape.distance(TwoDShape)
-s1.distance(c1) = 2.23606797749979
- --> String tracing.Square.toString()
- --> String tracing.TwoDShape.toString()
- <-- String tracing.TwoDShape.toString()
- <-- String tracing.Square.toString()
-s1.toString(): Square side = 1.0 @ (1.0, 2.0)
-]]></programlisting>
-
- </sect3>
- </sect2>
- </sect1>
-</chapter>
diff --git a/docs/progguide/gettingstarted.xml b/docs/progguide/gettingstarted.xml
deleted file mode 100644
index 6429d017f..000000000
--- a/docs/progguide/gettingstarted.xml
+++ /dev/null
@@ -1,1310 +0,0 @@
-<chapter id="starting" xreflabel="Getting Started with AspectJ">
-
- <title>Getting Started with AspectJ</title>
-
- <sect1 id="starting-intro">
- <title>Introduction</title>
-
- <para>
- Many software developers are attracted to the idea of aspect-oriented
- programming (AOP) but unsure about how to begin using the
- technology. They recognize the concept of crosscutting concerns, and
- know that they have had problems with the implementation of such
- concerns in the past. But there are many questions about how to adopt
- AOP into the development process. Common questions include:
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>Can I use aspects in my existing code?</para>
- </listitem>
-
- <listitem>
- <para>
- What kinds of benefits can I expect to get from using aspects?
- </para>
- </listitem>
-
- <listitem>
- <para>How do I find aspects in my programs?</para>
- </listitem>
-
- <listitem>
- <para>How steep is the learning curve for AOP?</para>
- </listitem>
-
- <listitem>
- <para>What are the risks of using this new technology?</para>
- </listitem>
-
- </itemizedlist>
- </para>
-
- <para>
- This chapter addresses these questions in the context of AspectJ: a
- general-purpose aspect-oriented extension to Java. A series of
- abridged examples illustrate the kinds of aspects programmers may
- want to implement using AspectJ and the benefits associated with
- doing so. Readers who would like to understand the examples in more
- detail, or who want to learn how to program examples like these, can
- find more complete examples and supporting material linked from the
- AspectJ web site ( <ulink url="https://eclipse.org/aspectj" /> ).
- </para>
-
- <para>
- A significant risk in adopting any new technology is going too far
- too fast. Concern about this risk causes many organizations to be
- conservative about adopting new technology. To address this issue,
- the examples in this chapter are grouped into three broad categories,
- with aspects that are easier to adopt into existing development
- projects coming earlier in this chapter. The next section, <xref
- linkend="starting-aspectj"/>, we present the core of AspectJ's
- features, and in <xref linkend="starting-development"/>, we present
- aspects that facilitate tasks such as debugging, testing and
- performance tuning of applications. And, in the section following,
- <xref linkend="starting-production"/>, we present aspects that
- implement crosscutting functionality common in Java applications. We
- will defer discussing a third category of aspects, reusable aspects,
- until <xref linkend="language"/>.
- </para>
-
- <para>
- These categories are informal, and this ordering is not the only way
- to adopt AspectJ. Some developers may want to use a production aspect
- right away. But our experience with current AspectJ users suggests
- that this is one ordering that allows developers to get experience
- with (and benefit from) AOP technology quickly, while also minimizing
- risk.
- </para>
- </sect1>
-
- <sect1 id="starting-aspectj" xreflabel="Introduction to AspectJ">
- <title>Introduction to AspectJ</title>
-
- <para>
- This section presents a brief introduction to the features of AspectJ
- used later in this chapter. These features are at the core of the
- language, but this is by no means a complete overview of AspectJ.
- </para>
-
- <para>
- The features are presented using a simple figure editor system. A
- <classname>Figure</classname> consists of a number of
- <classname>FigureElements</classname>, which can be either
- <classname>Point</classname>s or <classname>Line</classname>s. The
- <classname>Figure</classname> class provides factory services. There
- is also a <classname>Display</classname>. Most example programs later
- in this chapter are based on this system as well.
- </para>
-
- <para>
- <mediaobject>
- <imageobject>
- <imagedata fileref="figureUML.gif"/>
- </imageobject>
- <caption>
- <para>
- UML for the <literal>FigureEditor</literal> example
- </para>
- </caption>
- </mediaobject>
- </para>
-
- <para>
- The motivation for AspectJ (and likewise for aspect-oriented
- programming) is the realization that there are issues or concerns
- that are not well captured by traditional programming
- methodologies. Consider the problem of enforcing a security policy in
- some application. By its nature, security cuts across many of the
- natural units of modularity of the application. Moreover, the
- security policy must be uniformly applied to any additions as the
- application evolves. And the security policy that is being applied
- might itself evolve. Capturing concerns like a security policy in a
- disciplined way is difficult and error-prone in a traditional
- programming language.
- </para>
-
- <para>
- Concerns like security cut across the natural units of
- modularity. For object-oriented programming languages, the natural
- unit of modularity is the class. But in object-oriented programming
- languages, crosscutting concerns are not easily turned into classes
- precisely because they cut across classes, and so these aren't
- reusable, they can't be refined or inherited, they are spread through
- out the program in an undisciplined way, in short, they are difficult
- to work with.
- </para>
-
- <para>
- Aspect-oriented programming is a way of modularizing crosscutting
- concerns much like object-oriented programming is a way of
- modularizing common concerns. AspectJ is an implementation of
- aspect-oriented programming for Java.
- </para>
-
- <para>
- AspectJ adds to Java just one new concept, a join point -- and that's
- really just a name for an existing Java concept. It adds to Java
- only a few new constructs: pointcuts, advice, inter-type declarations
- and aspects. Pointcuts and advice dynamically affect program flow,
- inter-type declarations statically affects a program's class
- hierarchy, and aspects encapsulate these new constructs.
- </para>
-
- <para>
- A <emphasis>join point</emphasis> is a well-defined point in the
- program flow. A <emphasis>pointcut</emphasis> picks out certain join
- points and values at those points. A piece of
- <emphasis>advice</emphasis> is code that is executed when a join
- point is reached. These are the dynamic parts of AspectJ.
- </para>
-
- <para>
- AspectJ also has different kinds of <emphasis>inter-type
- declarations</emphasis> that allow the programmer to modify a
- program's static structure, namely, the members of its classes and
- the relationship between classes.
- </para>
-
- <para>
- AspectJ's <emphasis>aspect</emphasis> are the unit of modularity for
- crosscutting concerns. They behave somewhat like Java classes, but
- may also include pointcuts, advice and inter-type declarations.
- </para>
-
- <para>
- In the sections immediately following, we are first going to look at
- join points and how they compose into pointcuts. Then we will look at
- advice, the code which is run when a pointcut is reached. We will see
- how to combine pointcuts and advice into aspects, AspectJ's reusable,
- inheritable unit of modularity. Lastly, we will look at how to use
- inter-type declarations to deal with crosscutting concerns of a
- program's class structure.
- </para>
-
-<!-- ============================== -->
-
- <sect2 id="the-dynamic-join-point-model" xreflabel="the-dynamic-join-point-model">
- <title>The Dynamic Join Point Model</title>
-
- <para>
- A critical element in the design of any aspect-oriented language is
- the join point model. The join point model provides the common
- frame of reference that makes it possible to define the dynamic
- structure of crosscutting concerns. This chapter describes
- AspectJ's dynamic join points, in which join points are certain
- well-defined points in the execution of the program.
- </para>
-
- <para>
- AspectJ provides for many kinds of join points, but this chapter
- discusses only one of them: method call join points. A method call
- join point encompasses the actions of an object receiving a method
- call. It includes all the actions that comprise a method call,
- starting after all arguments are evaluated up to and including
- return (either normally or by throwing an exception).
- </para>
-
- <para>
- Each method call at runtime is a different join point, even if it
- comes from the same call expression in the program. Many other
- join points may run while a method call join point is executing --
- all the join points that happen while executing the method body,
- and in those methods called from the body. We say that these join
- points execute in the <emphasis>dynamic context</emphasis> of the
- original call join point.
- </para>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="pointcuts-starting" xreflabel="pointcuts-starting">
- <title>Pointcuts</title>
-
- <para>
- In AspectJ, <emphasis>pointcuts</emphasis> pick out certain join
- points in the program flow. For example, the pointcut
- </para>
-
-<programlisting format="linespecific">
-call(void Point.setX(int))
-</programlisting>
-
- <para>
- picks out each join point that is a call to a method that has the
- signature <literal>void Point.setX(int)</literal> - that is,
- <classname>Point</classname>'s void <function>setX</function>
- method with a single <literal>int</literal> parameter.
- </para>
-
- <para>
- A pointcut can be built out of other pointcuts with and, or, and
- not (spelled <literal>&amp;&amp;</literal>, <literal>||</literal>,
- and <literal>!</literal>). For example:
- </para>
-
-<programlisting format="linespecific">
-call(void Point.setX(int)) ||
-call(void Point.setY(int))
-</programlisting>
-
- <para>
- picks out each join point that is either a call to
- <function>setX</function> or a call to <function>setY</function>.
- </para>
-
- <para>
- Pointcuts can identify join points from many different types -
- in other words, they can crosscut types. For example,
- </para>
-
-<programlisting format="linespecific">
-call(void FigureElement.setXY(int,int)) ||
-call(void Point.setX(int)) ||
-call(void Point.setY(int)) ||
-call(void Line.setP1(Point)) ||
-call(void Line.setP2(Point));
-</programlisting>
-
- <para>
- picks out each join point that is a call to one of five methods
- (the first of which is an interface method, by the way).
- </para>
-
- <para>
- In our example system, this pointcut captures all the join points
- when a <classname>FigureElement</classname> moves. While this is a
- useful way to specify this crosscutting concern, it is a bit of a
- mouthful. So AspectJ allows programmers to define their own named
- pointcuts with the <literal>pointcut</literal> form. So the
- following declares a new, named pointcut:
- </para>
-
-<programlisting format="linespecific">
-pointcut move():
- call(void FigureElement.setXY(int,int)) ||
- call(void Point.setX(int)) ||
- call(void Point.setY(int)) ||
- call(void Line.setP1(Point)) ||
- call(void Line.setP2(Point));
-</programlisting>
-
- <para>
- and whenever this definition is visible, the programmer can simply
- use <literal>move()</literal> to capture this complicated
- pointcut.
- </para>
-
- <para>
- The previous pointcuts are all based on explicit enumeration of a
- set of method signatures. We sometimes call this
- <emphasis>name-based</emphasis> crosscutting. AspectJ also
- provides mechanisms that enable specifying a pointcut in terms of
- properties of methods other than their exact name. We call this
- <emphasis>property-based</emphasis> crosscutting. The simplest of
- these involve using wildcards in certain fields of the method
- signature. For example, the pointcut
- </para>
-
-<programlisting format="linespecific">
-call(void Figure.make*(..))
-</programlisting>
-
- <para>
- picks out each join point that's a call to a void method defined
- on <classname>Figure</classname> whose the name begins with
- "<literal>make</literal>" regardless of the method's parameters.
- In our system, this picks out calls to the factory methods
- <function>makePoint</function> and <function>makeLine</function>.
- The pointcut
- </para>
-
-<programlisting format="linespecific">
-call(public * Figure.* (..))
-</programlisting>
-
- <para>
- picks out each call to <classname>Figure</classname>'s public
- methods.
- </para>
-
- <para>
- But wildcards aren't the only properties AspectJ supports.
- Another pointcut, <function>cflow</function>, identifies join
- points based on whether they occur in the dynamic context of
- other join points. So
- </para>
-
-<programlisting format="linespecific">
-cflow(move())
-</programlisting>
-
- <para>
- picks out each join point that occurs in the dynamic context of
- the join points picked out by <literal>move()</literal>, our named
- pointcut defined above. So this picks out each join points that
- occurrs between when a move method is called and when it returns
- (either normally or by throwing an exception).
- </para>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="advice-starting" xreflabel="advice-starting">
- <title>Advice</title>
-
- <para>
- So pointcuts pick out join points. But they don't
- <emphasis>do</emphasis> anything apart from picking out join
- points. To actually implement crosscutting behavior, we use
- advice. Advice brings together a pointcut (to pick out join
- points) and a body of code (to run at each of those join points).
- </para>
-
- <para>
- AspectJ has several different kinds of advice. <emphasis>Before
- advice</emphasis> runs as a join point is reached, before the
- program proceeds with the join point. For example, before advice
- on a method call join point runs before the actual method starts
- running, just after the arguments to the method call are evaluated.
- </para>
-
-<programlisting><![CDATA[
-before(): move() {
- System.out.println("about to move");
-}
-]]></programlisting>
-
- <para>
- <emphasis>After advice</emphasis> on a particular join point runs
- after the program proceeds with that join point. For example,
- after advice on a method call join point runs after the method body
- has run, just before before control is returned to the caller.
- Because Java programs can leave a join point 'normally' or by
- throwing an exception, there are three kinds of after advice:
- <literal>after returning</literal>, <literal>after
- throwing</literal>, and plain <literal>after</literal> (which runs
- after returning <emphasis>or</emphasis> throwing, like Java's
- <literal>finally</literal>).
- </para>
-
-<programlisting><![CDATA[
-after() returning: move() {
- System.out.println("just successfully moved");
-}
-]]></programlisting>
-
- <para>
- <emphasis>Around advice</emphasis> on a join point runs as the join
- point is reached, and has explicit control over whether the program
- proceeds with the join point. Around advice is not discussed in
- this section.
- </para>
-
- <sect3>
- <title>Exposing Context in Pointcuts</title>
-
- <para>
- Pointcuts not only pick out join points, they can also expose
- part of the execution context at their join points. Values
- exposed by a pointcut can be used in the body of advice
- declarations.
- </para>
-
- <para>
- An advice declaration has a parameter list (like a method) that
- gives names to all the pieces of context that it uses. For
- example, the after advice
- </para>
-
-<programlisting><![CDATA[
-after(FigureElement fe, int x, int y) returning:
- ...SomePointcut... {
- ...SomeBody...
-}
-]]></programlisting>
-
- <para>
- uses three pieces of exposed context, a
- <literal>FigureElement</literal> named fe, and two
- <literal>int</literal>s named x and y.
- </para>
-
- <para>
- The body of the advice uses the names just like method
- parameters, so
- </para>
-
-<programlisting><![CDATA[
-after(FigureElement fe, int x, int y) returning:
- ...SomePointcut... {
- System.out.println(fe + " moved to (" + x + ", " + y + ")");
-}
-]]></programlisting>
-
- <para>
- The advice's pointcut publishes the values for the advice's
- arguments. The three primitive pointcuts
- <literal>this</literal>, <literal>target</literal> and
- <literal>args</literal> are used to publish these values. So now
- we can write the complete piece of advice:
- </para>
-
-<programlisting><![CDATA[
-after(FigureElement fe, int x, int y) returning:
- call(void FigureElement.setXY(int, int))
- && target(fe)
- && args(x, y) {
- System.out.println(fe + " moved to (" + x + ", " + y + ")");
-}
-]]></programlisting>
-
- <para>
- The pointcut exposes three values from calls to
- <function>setXY</function>: the target
- <classname>FigureElement</classname> -- which it publishes as
- <literal>fe</literal>, so it becomes the first argument to the
- after advice -- and the two int arguments -- which it publishes
- as <literal>x</literal> and <literal>y</literal>, so they become
- the second and third argument to the after advice.
- </para>
-
- <para>
- So the advice prints the figure element
- that was moved and its new <literal>x</literal> and
- <literal>y</literal> coordinates after each
- <classname>setXY</classname> method call.
- </para>
-
- <para>
- A named pointcut may have parameters like a piece of advice.
- When the named pointcut is used (by advice, or in another named
- pointcut), it publishes its context by name just like the
- <literal>this</literal>, <literal>target</literal> and
- <literal>args</literal> pointcut. So another way to write the
- above advice is
- </para>
-
-<programlisting><![CDATA[
-pointcut setXY(FigureElement fe, int x, int y):
- call(void FigureElement.setXY(int, int))
- && target(fe)
- && args(x, y);
-
-after(FigureElement fe, int x, int y) returning: setXY(fe, x, y) {
- System.out.println(fe + " moved to (" + x + ", " + y + ").");
-}
-]]></programlisting>
-
- </sect3>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="inter-type-declarations" xreflabel="inter-type-declarations">
- <title>Inter-type declarations</title>
-
- <para>
- Inter-type declarations in AspectJ are declarations that cut across
- classes and their hierarchies. They may declare members that cut
- across multiple classes, or change the inheritance relationship
- between classes. Unlike advice, which operates primarily
- dynamically, introduction operates statically, at compile-time.
- </para>
-
- <para>
- Consider the problem of expressing a capability shared by some
- existing classes that are already part of a class hierarchy,
- i.e. they already extend a class. In Java, one creates an
- interface that captures this new capability, and then adds to
- <emphasis>each affected class</emphasis> a method that implements
- this interface.
- </para>
-
- <para>
- AspectJ can express the concern in one place, by using inter-type
- declarations. The aspect declares the methods and fields that are
- necessary to implement the new capability, and associates the
- methods and fields to the existing classes.
- </para>
-
- <para>
- Suppose we want to have <classname>Screen</classname> objects
- observe changes to <classname>Point</classname> objects, where
- <classname>Point</classname> is an existing class. We can implement
- this by writing an aspect declaring that the class Point
- <classname>Point</classname> has an instance field,
- <varname>observers</varname>, that keeps track of the
- <classname>Screen</classname> objects that are observing
- <classname>Point</classname>s.
- </para>
-
-<programlisting><![CDATA[
-aspect PointObserving {
- private Vector Point.observers = new Vector();
- ...
-}
-]]></programlisting>
-
- <para>
- The <literal>observers</literal> field is private, so only
- <classname>PointObserving</classname> can see it. So observers are
- added or removed with the static methods
- <function>addObserver</function> and
- <function>removeObserver</function> on the aspect.
- </para>
-
-<programlisting><![CDATA[
-aspect PointObserving {
- private Vector Point.observers = new Vector();
-
- public static void addObserver(Point p, Screen s) {
- p.observers.add(s);
- }
- public static void removeObserver(Point p, Screen s) {
- p.observers.remove(s);
- }
- ...
-}
-]]></programlisting>
-
- <para>
- Along with this, we can define a pointcut
- <function>changes</function> that defines what we want to observe,
- and the after advice defines what we want to do when we observe a
- change.
- </para>
-
-<programlisting><![CDATA[
-aspect PointObserving {
- private Vector Point.observers = new Vector();
-
- public static void addObserver(Point p, Screen s) {
- p.observers.add(s);
- }
- public static void removeObserver(Point p, Screen s) {
- p.observers.remove(s);
- }
-
- pointcut changes(Point p): target(p) && call(void Point.set*(int));
-
- after(Point p): changes(p) {
- Iterator iter = p.observers.iterator();
- while ( iter.hasNext() ) {
- updateObserver(p, (Screen)iter.next());
- }
- }
-
- static void updateObserver(Point p, Screen s) {
- s.display(p);
- }
-}
-]]></programlisting>
-
- <para>
- Note that neither <classname>Screen</classname>'s nor
- <classname>Point</classname>'s code has to be modified, and that
- all the changes needed to support this new capability are local to
- this aspect.
- </para>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="aspects" xreflabel="aspects">
- <title>Aspects</title>
-
- <para>
- Aspects wrap up pointcuts, advice, and inter-type declarations in a
- a modular unit of crosscutting implementation. It is defined very
- much like a class, and can have methods, fields, and initializers
- in addition to the crosscutting members. Because only aspects may
- include these crosscutting members, the declaration of these
- effects is localized.
- </para>
-
- <para>
- Like classes, aspects may be instantiated, but AspectJ controls how
- that instantiation happens -- so you can't use Java's
- <literal>new</literal> form to build new aspect instances. By
- default, each aspect is a singleton, so one aspect instance is
- created. This means that advice may use non-static fields of the
- aspect, if it needs to keep state around:
- </para>
-
-<programlisting><![CDATA[
-aspect Logging {
- OutputStream logStream = System.err;
-
- before(): move() {
- logStream.println("about to move");
- }
-}
-]]></programlisting>
-
- <para>
- Aspects may also have more complicated rules for instantiation, but
- these will be described in a later chapter.
- </para>
-
- </sect2>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="starting-development" xreflabel="Development Aspects">
- <title>Development Aspects</title>
-
- <para>
- The next two sections present the use of aspects in increasingly
- sophisticated ways. Development aspects are easily removed from
- production builds. Production aspects are intended to be used in
- both development and in production, but tend to affect only a few
- classes.
- </para>
-
- <para>
- This section presents examples of aspects that can be used during
- development of Java applications. These aspects facilitate debugging,
- testing and performance tuning work. The aspects define behavior that
- ranges from simple tracing, to profiling, to testing of internal
- consistency within the application. Using AspectJ makes it possible
- to cleanly modularize this kind of functionality, thereby making it
- possible to easily enable and disable the functionality when desired.
- </para>
-
- <sect2 id="tracing" xreflabel="tracing">
- <title>Tracing</title>
-
- <para>
- This first example shows how to increase the visibility of the
- internal workings of a program. It is a simple tracing aspect that
- prints a message at specified method calls. In our figure editor
- example, one such aspect might simply trace whenever points are
- drawn.
- </para>
-
-<programlisting><![CDATA[
-aspect SimpleTracing {
- pointcut tracedCall():
- call(void FigureElement.draw(GraphicsContext));
-
- before(): tracedCall() {
- System.out.println("Entering: " + thisJoinPoint);
- }
-}
-]]></programlisting>
-
- <para>
- This code makes use of the <literal>thisJoinPoint</literal> special
- variable. Within all advice bodies this variable is bound to an
- object that describes the current join point. The effect of this
- code is to print a line like the following every time a figure
- element receives a <function>draw</function> method call:
- </para>
-
-<programlisting><![CDATA[
-Entering: call(void FigureElement.draw(GraphicsContext))
-]]></programlisting>
-
- <para>
- To understand the benefit of coding this with AspectJ consider
- changing the set of method calls that are traced. With AspectJ,
- this just requires editing the definition of the
- <function>tracedCalls</function> pointcut and recompiling. The
- individual methods that are traced do not need to be edited.
- </para>
-
- <para>
- When debugging, programmers often invest considerable effort in
- figuring out a good set of trace points to use when looking for a
- particular kind of problem. When debugging is complete or appears
- to be complete it is frustrating to have to lose that investment by
- deleting trace statements from the code. The alternative of just
- commenting them out makes the code look bad, and can cause trace
- statements for one kind of debugging to get confused with trace
- statements for another kind of debugging.
- </para>
-
- <para>
- With AspectJ it is easy to both preserve the work of designing a
- good set of trace points and disable the tracing when it isn t
- being used. This is done by writing an aspect specifically for that
- tracing mode, and removing that aspect from the compilation when it
- is not needed.
- </para>
-
- <para>
- This ability to concisely implement and reuse debugging
- configurations that have proven useful in the past is a direct
- result of AspectJ modularizing a crosscutting design element the
- set of methods that are appropriate to trace when looking for a
- given kind of information.
- </para>
- </sect2>
-
- <sect2 id="profiling-and-logging" xreflabel="profiling-and-logging">
- <title>Profiling and Logging</title>
-
- <para>
- Our second example shows you how to do some very specific
- profiling. Although many sophisticated profiling tools are
- available, and these can gather a variety of information and
- display the results in useful ways, you may sometimes want to
- profile or log some very specific behavior. In these cases, it is
- often possible to write a simple aspect similar to the ones above
- to do the job.
- </para>
-
- <para>
- For example, the following aspect counts the number of calls to the
- <function>rotate</function> method on a <classname>Line</classname>
- and the number of calls to the <function>set*</function> methods of
- a <classname>Point</classname> that happen within the control flow
- of those calls to <function>rotate</function>:
- </para>
-
-<programlisting><![CDATA[
-aspect SetsInRotateCounting {
- int rotateCount = 0;
- int setCount = 0;
-
- before(): call(void Line.rotate(double)) {
- rotateCount++;
- }
-
- before(): call(void Point.set*(int))
- && cflow(call(void Line.rotate(double))) {
- setCount++;
- }
-}
-]]></programlisting>
-
- <para>
- In effect, this aspect allows the programmer to ask very specific
- questions like
-
- <blockquote>
- How many times is the <function>rotate</function>
- method defined on <classname>Line</classname> objects called?
- </blockquote>
-
- and
-
- <blockquote>
- How many times are methods defined on
- <classname>Point</classname> objects whose name begins with
- "<function>set</function>" called in fulfilling those rotate
- calls?
- </blockquote>
-
- questions it may be difficult to express using standard
- profiling or logging tools.
- </para>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="pre-and-post-conditions" xreflabel="pre-and-post-conditions">
- <title>Pre- and Post-Conditions</title>
-
- <para>
- Many programmers use the "Design by Contract" style popularized by
- Bertand Meyer in <citetitle>Object-Oriented Software Construction,
- 2/e</citetitle>. In this style of programming, explicit
- pre-conditions test that callers of a method call it properly and
- explicit post-conditions test that methods properly do the work
- they are supposed to.
- </para>
-
- <para>
- AspectJ makes it possible to implement pre- and post-condition
- testing in modular form. For example, this code
- </para>
-
-
-<programlisting><![CDATA[
-aspect PointBoundsChecking {
-
- pointcut setX(int x):
- (call(void FigureElement.setXY(int, int)) && args(x, *))
- || (call(void Point.setX(int)) && args(x));
-
- pointcut setY(int y):
- (call(void FigureElement.setXY(int, int)) && args(*, y))
- || (call(void Point.setY(int)) && args(y));
-
- before(int x): setX(x) {
- if ( x < MIN_X || x > MAX_X )
- throw new IllegalArgumentException("x is out of bounds.");
- }
-
- before(int y): setY(y) {
- if ( y < MIN_Y || y > MAX_Y )
- throw new IllegalArgumentException("y is out of bounds.");
- }
-}
-]]></programlisting>
-
- <para>
- implements the bounds checking aspect of pre-condition testing for
- operations that move points. Notice that the
- <function>setX</function> pointcut refers to all the operations
- that can set a Point's <literal>x</literal> coordinate; this
- includes the <function>setX</function> method, as well as half of
- the <function>setXY</function> method. In this sense the
- <function>setX</function> pointcut can be seen as involving very
- fine-grained crosscutting - it names the the
- <function>setX</function> method and half of the
- <function>setXY</function> method.
- </para>
-
- <para>
- Even though pre- and post-condition testing aspects can often be
- used only during testing, in some cases developers may wish to
- include them in the production build as well. Again, because
- AspectJ makes it possible to modularize these crosscutting concerns
- cleanly, it gives developers good control over this decision.
- </para>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="contract-enforcement" xreflabel="contract-enforcement">
- <title>Contract Enforcement</title>
-
- <para>
- The property-based crosscutting mechanisms can be very useful in
- defining more sophisticated contract enforcement. One very powerful
- use of these mechanisms is to identify method calls that, in a
- correct program, should not exist. For example, the following
- aspect enforces the constraint that only the well-known factory
- methods can add an element to the registry of figure
- elements. Enforcing this constraint ensures that no figure element
- is added to the registry more than once.
- </para>
-
-<programlisting><![CDATA[
-aspect RegistrationProtection {
-
- pointcut register(): call(void Registry.register(FigureElement));
-
- pointcut canRegister(): withincode(static * FigureElement.make*(..));
-
- before(): register() && !canRegister() {
- throw new IllegalAccessException("Illegal call " + thisJoinPoint);
- }
-}
-]]></programlisting>
-
- <para>
- This aspect uses the withincode primitive pointcut to denote all
- join points that occur within the body of the factory methods on
- <classname>FigureElement</classname> (the methods with names that
- begin with "<literal>make</literal>"). This is a property-based
- pointcut because it identifies join points based not on their
- signature, but rather on the property that they occur specifically
- within the code of another method. The before advice declaration
- effectively says signal an error for any calls to register that are
- not within the factory methods.
- </para>
-
- <para>
- This advice throws a runtime exception at certain join points, but
- AspectJ can do better. Using the <literal>declare error</literal>
- form, we can have the <emphasis>compiler</emphasis> signal the
- error.
- </para>
-
-<programlisting><![CDATA[
-aspect RegistrationProtection {
-
- pointcut register(): call(void Registry.register(FigureElement));
- pointcut canRegister(): withincode(static * FigureElement.make*(..));
-
- declare error: register() && !canRegister(): "Illegal call"
-}
-]]></programlisting>
-
- <para>
- When using this aspect, it is impossible for the compiler to
- compile programs with these illegal calls. This early detection is
- not always possible. In this case, since we depend only on static
- information (the <literal>withincode</literal> pointcut picks out
- join points totally based on their code, and the
- <literal>call</literal> pointcut here picks out join points
- statically). Other enforcement, such as the precondition
- enforcement, above, does require dynamic information such as the
- runtime value of parameters.
- </para>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="configuration-management" xreflabel="configuration-management">
- <title>Configuration Management</title>
-
- <para>
- Configuration management for aspects can be handled using a variety
- of make-file like techniques. To work with optional aspects, the
- programmer can simply define their make files to either include the
- aspect in the call to the AspectJ compiler or not, as desired.
- </para>
-
- <para>
- Developers who want to be certain that no aspects are included in
- the production build can do so by configuring their make files so
- that they use a traditional Java compiler for production builds. To
- make it easy to write such make files, the AspectJ compiler has a
- command-line interface that is consistent with ordinary Java
- compilers.
- </para>
- </sect2>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="starting-production" xreflabel="Production Aspects">
- <title>Production Aspects</title>
-
- <para>
- This section presents examples of aspects that are inherently
- intended to be included in the production builds of an application.
- Production aspects tend to add functionality to an application
- rather than merely adding more visibility of the internals of a
- program. Again, we begin with name-based aspects and follow with
- property-based aspects. Name-based production aspects tend to
- affect only a small number of methods. For this reason, they are a
- good next step for projects adopting AspectJ. But even though they
- tend to be small and simple, they can often have a significant
- effect in terms of making the program easier to understand and
- maintain.
- </para>
-
- <sect2 id="change-monitoring" xreflabel="change-monitoring">
- <title>Change Monitoring</title>
-
- <para>
- The first example production aspect shows how one might implement
- some simple functionality where it is problematic to try and do it
- explicitly. It supports the code that refreshes the display. The
- role of the aspect is to maintain a dirty bit indicating whether or
- not an object has moved since the last time the display was
- refreshed.
- </para>
-
- <para>
- Implementing this functionality as an aspect is straightforward.
- The <function>testAndClear</function> method is called by the
- display code to find out whether a figure element has moved
- recently. This method returns the current state of the dirty flag
- and resets it to false. The pointcut <function>move</function>
- captures all the method calls that can move a figure element. The
- after advice on <function>move</function> sets the dirty flag
- whenever an object moves.
- </para>
-
-<programlisting><![CDATA[
-aspect MoveTracking {
- private static boolean dirty = false;
-
- public static boolean testAndClear() {
- boolean result = dirty;
- dirty = false;
- return result;
- }
-
- pointcut move():
- call(void FigureElement.setXY(int, int)) ||
- call(void Line.setP1(Point)) ||
- call(void Line.setP2(Point)) ||
- call(void Point.setX(int)) ||
- call(void Point.setY(int));
-
- after() returning: move() {
- dirty = true;
- }
-}
-]]></programlisting>
-
- <para>
- Even this simple example serves to illustrate some of the important
- benefits of using AspectJ in production code. Consider implementing
- this functionality with ordinary Java: there would likely be a
- helper class that contained the <literal>dirty</literal> flag, the
- <function>testAndClear</function> method, as well as a
- <function>setFlag</function> method. Each of the methods that could
- move a figure element would include a call to the
- <function>setFlag</function> method. Those calls, or rather the
- concept that those calls should happen at each move operation, are
- the crosscutting concern in this case.
- </para>
-
- <para>
- The AspectJ implementation has several advantages over the standard
- implementation:
- </para>
-
- <para>
- <emphasis>The structure of the crosscutting concern is captured
- explicitly.</emphasis> The moves pointcut clearly states all the
- methods involved, so the programmer reading the code sees not just
- individual calls to <literal>setFlag</literal>, but instead sees
- the real structure of the code. The IDE support included with
- AspectJ automatically reminds the programmer that this aspect
- advises each of the methods involved. The IDE support also
- provides commands to jump to the advice from the method and
- vice-versa.
- </para>
-
- <para>
- <emphasis>Evolution is easier.</emphasis> If, for example, the
- aspect needs to be revised to record not just that some figure
- element moved, but rather to record exactly which figure elements
- moved, the change would be entirely local to the aspect. The
- pointcut would be updated to expose the object being moved, and the
- advice would be updated to record that object. The paper
- <citetitle>An Overview of AspectJ</citetitle> (available linked off
- of the AspectJ web site -- <ulink
- url="https://eclipse.org/aspectj" />), presented at ECOOP
- 2001, presents a detailed discussion of various ways this aspect
- could be expected to evolve.
- </para>
-
- <para>
- <emphasis>The functionality is easy to plug in and out.</emphasis>
- Just as with development aspects, production aspects may need to be
- removed from the system, either because the functionality is no
- longer needed at all, or because it is not needed in certain
- configurations of a system. Because the functionality is
- modularized in a single aspect this is easy to do.
- </para>
-
- <para>
- <emphasis>The implementation is more stable.</emphasis> If, for
- example, the programmer adds a subclass of
- <classname>Line</classname> that overrides the existing methods,
- this advice in this aspect will still apply. In the ordinary Java
- implementation the programmer would have to remember to add the
- call to <function>setFlag</function> in the new overriding
- method. This benefit is often even more compelling for
- property-based aspects (see the section <xref
- linkend="starting-production-consistentBehavior"/>).
- </para>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="context-passing" xreflabel="context-passing">
- <title>Context Passing</title>
-
- <para>
- The crosscutting structure of context passing can be a significant
- source of complexity in Java programs. Consider implementing
- functionality that would allow a client of the figure editor (a
- program client rather than a human) to set the color of any figure
- elements that are created. Typically this requires passing a color,
- or a color factory, from the client, down through the calls that
- lead to the figure element factory. All programmers are familiar
- with the inconvenience of adding a first argument to a number of
- methods just to pass this kind of context information.
- </para>
-
- <para>
- Using AspectJ, this kind of context passing can be implemented in a
- modular way. The following code adds after advice that runs only
- when the factory methods of <classname>Figure</classname> are
- called in the control flow of a method on a
- <classname>ColorControllingClient</classname>.
- </para>
-
-<programlisting><![CDATA[
-aspect ColorControl {
- pointcut CCClientCflow(ColorControllingClient client):
- cflow(call(* * (..)) && target(client));
-
- pointcut make(): call(FigureElement Figure.make*(..));
-
- after (ColorControllingClient c) returning (FigureElement fe):
- make() && CCClientCflow(c) {
- fe.setColor(c.colorFor(fe));
- }
-}
-]]></programlisting>
-
- <para>
- This aspect affects only a small number of methods, but note that
- the non-AOP implementation of this functionality might require
- editing many more methods, specifically, all the methods in the
- control flow from the client to the factory. This is a benefit
- common to many property-based aspects while the aspect is short and
- affects only a modest number of benefits, the complexity the aspect
- saves is potentially much larger.
- </para>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="starting-production-consistentBehavior" xreflabel="Providing Consistent Behavior">
- <title>Providing Consistent Behavior</title>
-
- <para>
- This example shows how a property-based aspect can be used to
- provide consistent handling of functionality across a large set of
- operations. This aspect ensures that all public methods of the
- <literal>com.bigboxco</literal> package log any Errors they throw
- to their caller (in Java, an Error is like an Exception, but it
- indicates that something really bad and usually unrecoverable has
- happened). The <function>publicMethodCall</function> pointcut
- captures the public method calls of the package, and the after
- advice runs whenever one of those calls throws an Error. The advice
- logs that Error and then the throw resumes.
- </para>
-
- <programlisting><![CDATA[
-aspect PublicErrorLogging {
- Log log = new Log();
-
- pointcut publicMethodCall():
- call(public * com.bigboxco.*.*(..));
-
- after() throwing (Error e): publicMethodCall() {
- log.write(e);
- }
-}
-]]></programlisting>
-
- <para>
- In some cases this aspect can log an exception twice. This happens
- if code inside the <literal>com.bigboxco</literal> package itself
- calls a public method of the package. In that case this code will
- log the error at both the outermost call into the
- <literal>com.bigboxco</literal> package and the re-entrant
- call. The <function>cflow</function> primitive pointcut can be used
- in a nice way to exclude these re-entrant calls:</para>
-
-<programlisting><![CDATA[
-after() throwing (Error e):
- publicMethodCall() && !cflow(publicMethodCall()) {
- log.write(e);
-}
-]]></programlisting>
-
- <para>
- The following aspect is taken from work on the AspectJ compiler.
- The aspect advises about 35 methods in the
- <classname>JavaParser</classname> class. The individual methods
- handle each of the different kinds of elements that must be
- parsed. They have names like <function>parseMethodDec</function>,
- <function>parseThrows</function>, and
- <function>parseExpr</function>.
- </para>
-
-<programlisting><![CDATA[
-aspect ContextFilling {
- pointcut parse(JavaParser jp):
- call(* JavaParser.parse*(..))
- && target(jp)
- && !call(Stmt parseVarDec(boolean)); // var decs
- // are tricky
-
- around(JavaParser jp) returns ASTObject: parse(jp) {
- Token beginToken = jp.peekToken();
- ASTObject ret = proceed(jp);
- if (ret != null) jp.addContext(ret, beginToken);
- return ret;
- }
-}
-]]></programlisting>
-
- <para>
- This example exhibits a property found in many aspects with large
- property-based pointcuts. In addition to a general property based
- pattern <literal>call(* JavaParser.parse*(..))</literal> it
- includes an exception to the pattern <literal>!call(Stmt
- parseVarDec(boolean))</literal>. The exclusion of
- <function>parseVarDec</function> happens because the parsing of
- variable declarations in Java is too complex to fit with the clean
- pattern of the other <function>parse*</function> methods. Even with
- the explicit exclusion this aspect is a clear expression of a clean
- crosscutting modularity. Namely that all
- <function>parse*</function> methods that return
- <classname>ASTObjects</classname>, except for
- <function>parseVarDec</function> share a common behavior for
- establishing the parse context of their result.
- </para>
-
- <para>
- The process of writing an aspect with a large property-based
- pointcut, and of developing the appropriate exceptions can clarify
- the structure of the system. This is especially true, as in this
- case, when refactoring existing code to use aspects. When we first
- looked at the code for this aspect, we were able to use the IDE
- support provided in AJDE for JBuilder to see what methods the
- aspect was advising compared to our manual coding. We quickly
- discovered that there were a dozen places where the aspect advice
- was in effect but we had not manually inserted the required
- functionality. Two of these were bugs in our prior non-AOP
- implementation of the parser. The other ten were needless
- performance optimizations. So, here, refactoring the code to
- express the crosscutting structure of the aspect explicitly made
- the code more concise and eliminated latent bugs.
- </para>
- </sect2>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="starting-conclusion">
- <title>Conclusion</title>
-
- <para>
- AspectJ is a simple and practical aspect-oriented extension to
- Java. With just a few new constructs, AspectJ provides support for
- modular implementation of a range of crosscutting concerns.
- </para>
-
- <para>
- Adoption of AspectJ into an existing Java development project can be
- a straightforward and incremental task. One path is to begin by using
- only development aspects, going on to using production aspects and
- then reusable aspects after building up experience with
- AspectJ. Adoption can follow other paths as well. For example, some
- developers will benefit from using production aspects right
- away. Others may be able to write clean reusable aspects almost right
- away.
- </para>
-
- <para>
- AspectJ enables both name-based and property based crosscutting.
- Aspects that use name-based crosscutting tend to affect a small
- number of other classes. But despite their small scale, they can
- often eliminate significant complexity compared to an ordinary Java
- implementation. Aspects that use property-based crosscutting can
- have small or large scale.
- </para>
-
- <para>
- Using AspectJ results in clean well-modularized implementations of
- crosscutting concerns. When written as an AspectJ aspect the
- structure of a crosscutting concern is explicit and easy to
- understand. Aspects are also highly modular, making it possible to
- develop plug-and-play implementations of crosscutting
- functionality.
- </para>
-
- <para>
- AspectJ provides more functionality than was covered by this short
- introduction. The next chapter, <xref linkend="language"/>,
- covers in detail more of the features of the AspectJ language. The
- following chapter, <xref linkend="examples"/>, then presents some
- carefully chosen examples that show you how AspectJ might be used. We
- recommend that you read the next two chapters carefully before
- deciding to adopt AspectJ into a project.
- </para>
- </sect1>
-</chapter>
diff --git a/docs/progguide/idioms.xml b/docs/progguide/idioms.xml
deleted file mode 100644
index c6297c90b..000000000
--- a/docs/progguide/idioms.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<chapter id="idioms" xreflabel="Idioms">
- <title>Idioms</title>
-
- <sect1 id="idioms-intro">
- <title>Introduction</title>
-
- <para>
- This chapter consists of very short snippets of AspectJ code,
- typically pointcuts, that are particularly evocative or useful.
- This section is a work in progress.
- </para>
-
- <para>
- Here's an example of how to enfore a rule that code in the
- java.sql package can only be used from one particular package in
- your system. This doesn't require any access to code in the
- java.sql package.
- </para>
-
-<programlisting><![CDATA[
-/* Any call to methods or constructors in java.sql */
-pointcut restrictedCall():
- call(* java.sql.*.*(..)) || call(java.sql.*.new(..));
-
-/* Any code in my system not in the sqlAccess package */
-pointcut illegalSource():
- within(com.foo..*) && !within(com.foo.sqlAccess.*);
-
-declare error: restrictedCall() && illegalSource():
- "java.sql package can only be accessed from com.foo.sqlAccess";
-]]></programlisting>
-
- <para>Any call to an instance of a subtype of AbstractFacade whose class is
- not exactly equal to AbstractFacade:</para>
-
-<programlisting><![CDATA[
-pointcut nonAbstract(AbstractFacade af):
- call(* *(..))
- && target(af)
- && !if(af.getClass() == AbstractFacade.class);
-]]></programlisting>
-
- <para> If AbstractFacade is an abstract class or an interface, then every
- instance must be of a subtype and you can replace this with: </para>
-
-<programlisting><![CDATA[
-pointcut nonAbstract(AbstractFacade af):
- call(* *(..))
- && target(af);
-]]></programlisting>
-
- <para> Any call to a method which is defined by a subtype of
- AbstractFacade, but which isn't defined by the type AbstractFacade itself:
- </para>
-
-<programlisting><![CDATA[
-pointcut callToUndefinedMethod():
- call(* AbstractFacade+.*(..))
- && !call(* AbstractFacade.*(..));
-]]></programlisting>
-
- <para> The execution of a method that is defined in the source code for a
- type that is a subtype of AbstractFacade but not in AbstractFacade itself:
- </para>
-
-<programlisting><![CDATA[
-pointcut executionOfUndefinedMethod():
- execution(* *(..))
- && within(AbstractFacade+)
- && !within(AbstractFacade)
-]]></programlisting>
-
- </sect1>
-</chapter>
diff --git a/docs/progguide/implementation.xml b/docs/progguide/implementation.xml
deleted file mode 100644
index e1fa05f2b..000000000
--- a/docs/progguide/implementation.xml
+++ /dev/null
@@ -1,377 +0,0 @@
-<appendix id="implementation" xreflabel="Implementation Notes">
-
- <title>Implementation Notes</title>
-
-<sect1>
- <title>Compiler Notes</title>
-
- <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
- to the virtual machine, which a compiler-based implementation
- cannot do. One way to deal with this problem would be to specify
- only the behavior that is easiest to implement. We have chosen a
- somewhat different approach, which is to specify an ideal language
- semantics, as well as a clearly defined way in which
- implementations are allowed to deviate from that semantics. This
- makes it possible to develop conforming AspectJ implementations
- today, while still making it clear what later, and presumably
- better, implementations should do tomorrow.
- </para>
-
- <para>
- According to the AspectJ language semantics, the declaration
- </para>
-
-<programlisting><![CDATA[
-before(): get(int Point.x) { System.out.println("got x"); }
-]]></programlisting>
-
- <para>
- should advise all accesses of a field of type int and name x from
- instances of type (or subtype of) Point. It should do this
- regardless of whether all the source code performing the access
- was available at the time the aspect containing this advice was
- compiled, whether changes were made later, etc.
- </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
- implementation is free within certain bounds to provide its own
- definition of what it means to control code.
- </para>
-
- <para>
- In the current AspectJ compiler, ajc, control of the code means
- having bytecode for any aspects and all the code they should
- affect available during the compile. This means that if some class
- Client contains code with the expression <literal>new
- Point().x</literal> (which results in a field get join point at
- runtime), the current AspectJ compiler will fail to advise that
- access unless Client.java or Client.class is compiled as well. It
- also means that join points associated with code in native methods
- (including their execution join points) cannot be advised.
- </para>
-
- <para>
- Different join points have different requirements. Method and
- constructor call join points can be advised only if ajc controls
- the bytecode for the caller. Field reference or assignment join
- points can be advised only if ajc controls the bytecode for the
- "caller", the code actually making the reference or assignment.
- Initialization join points can be advised only if ajc controls the
- bytecode of the type being initialized, and execution join points
- 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
- points.
- 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>
-
- <para>
- Aspects that are defined <literal>perthis</literal> or
- <literal>pertarget</literal> also have restrictions based on
- control of the code. In particular, at a join point where the
- bytecode for the currently executing object is not available, an
- aspect defined <literal>perthis</literal> of that join point will
- not be associated. So aspects defined
- <literal>perthis(Object)</literal> will not create aspect
- instances for every object unless <literal>Object</literal>is part
- of the compile. Similar restrictions apply to
- <literal>pertarget</literal> aspects.
- </para>
-
- <para>
- Inter-type declarations such as <literal>declare parents</literal>
- also have restrictions based on control of the code. If the
- bytecode for the target of an inter-type declaration is not
- available, then the inter-type declaration is not made on that
- target. So, <literal>declare parents : String implements
- MyInterface</literal> will not work for
- <literal>java.lang.String</literal> unless
- <literal>java.lang.String</literal> is part of the compile.
- </para>
- <para>
- When declaring members on interfaces, the implementation must
- 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
- 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
- an interface are implicitly public.
- 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
- 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
- <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
- in code outside the control of the implementation, even when it
- is a a well-defined API in a Java standard library.
- </para>
-
- <para>
- The important thing to remember is that core concepts of AspectJ,
- such as the join point, are unchanged, regardless of which
- implementation is used. During your development, you will have to
- be aware of the limitations of the ajc compiler you're using, but
- these limitations should not drive the design of your aspects.
- </para>
-</sect1>
-
-<sect1>
- <title>Bytecode Notes</title>
-
- <sect2 id="the-class-expression-and-string" xreflabel="the-class-expression-and-string">
- <title>The .class expression and String +</title>
-
- <para> The java language form <literal>Foo.class</literal> is
- implemented in bytecode with a call to
- <literal>Class.forName</literal> guarded by an exception
- handler catching a <literal>ClassNotFoundException</literal>.
- </para>
-
- <para> The java language + operator, when applied to String
- arguments, is implemented in bytecode by calls to
- <literal>StringBuffer.append</literal>.
- </para>
-
- <para> In both of these cases, the current AspectJ compiler
- operates on the bytecode implementation of these language
- features; in short, it operates on what is really happening rather
- than what was written in source code. This means that there may
- be call join points to <literal>Class.forName</literal> or
- <literal>StringBuffer.append</literal> from programs that do not,
- at first glance, appear to contain such calls:
- </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
- }
-}
-]]></programlisting>
-
- <para>In short, the join point model of the current AspectJ
- compiler considers these as valid join points.
- </para>
-
- </sect2>
-
- <sect2 id="the-handler-join-point" xreflabel="the-handler-join-point">
- <title>The Handler join point</title>
-
-
- <para>The end of exception handlers cannot reliably be found in Java
- bytecode. Instead of removing the handler join point entirely, the
- current AspectJ compiler restricts what can be done with the handler
- join point:
- </para>
-
- <itemizedlist>
- <listitem>After and around advice cannot apply to handler
- join points.</listitem>
-
- <listitem>The control flow of a handler join point cannot be
- detected. </listitem>
- </itemizedlist>
-
- <para>
- The first of these is relatively straightforward. If any piece of
- after advice (returning, throwing, or "finally") would normally
- apply to a handler join point, it will not in code output by the
- current AspectJ compiler. A compiler warning is generated whenever
- this is detected to be the case. Before advice is allowed.
- </para>
-
- <para> The second is that the control flow of a handler join point
- is not picked out. For example, the following pointcut
- </para>
-
-<programlisting><![CDATA[
-cflow(call(void foo()) || handler(java.io.IOException))
-]]></programlisting>
-
- <para> will capture all join points in the control flow of a call to
- <literal>void foo()</literal>, but it will <emphasis>not</emphasis>
- capture those in the control flow of an
- <literal>IOException</literal> handler. It is equivalent to
- <literal>cflow(call(void foo()))</literal>. In general,
- <literal>cflow(handler(<replaceable>Type</replaceable>))</literal>
- will not pick out any join points, the one exception to this is join points
- that occur during the execution of any before advice on the handler.
- </para>
-
- <para> This does not restrict programs from placing before advice on
- handlers inside <emphasis>other</emphasis> control flows. This
- advice, for example, is perfectly fine:
- </para>
-
-<programlisting><![CDATA[
-before(): handler(java.io.IOException) && cflow(void parse()) {
- System.out.println("about to handle an exception while parsing");
-}
-]]></programlisting>
-
- <para>
- A source-code implementation of AspectJ (such as AspectJ 1.0.6) is
- able to detect the endpoint of a handler join point, and as such
- will likely have fewer such restrictions.
- </para>
-
- </sect2>
-
- <sect2 id="initializers-and-inter-type-constructors" xreflabel="initializers-and-inter-type-constructors">
- <title>Initializers and Inter-type Constructors</title>
-
- <para>
- The code for Java initializers, such as the assignment to the
- field d in
- </para>
-
-<programlisting><![CDATA[
-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.
- </para>
-
- <para>
- Thus inter-type constructors will not necessarily run a target
- type's initialization code. In particular, if the inter-type
- constructor calls a super-constructor (as opposed to a
- <literal>this</literal> constructor), the target type's
- initialization code will <emphasis>not</emphasis> be run when that
- inter-type constructor is called.
- </para>
-
-<programlisting><![CDATA[
-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
-}
-]]></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>
- constructor if necessary.
- </para>
- </sect2>
-</sect1>
-
-<sect1>
- <title>Annotation-style Notes</title>
- <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
- for more information.
- </para>
-</sect1>
-<sect1>
- <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.
- </para>
- <itemizedlist spacing="compact">
- <listitem>
- <para>The invoking code must be under the control of ajc
- for the following join points:</para>
- <itemizedlist spacing="compact">
- <listitem>call join point</listitem>
- <listitem>get join point</listitem>
- <listitem>set join point</listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>The declaring/target code must be under the control of ajc
- for the following join points and inter-type declarations:</para>
- <itemizedlist spacing="compact">
- <listitem>execution join point</listitem>
- <listitem>adviceexecution join point</listitem>
- <listitem>handler join point</listitem>
- <listitem>initialization join point</listitem>
- <listitem>preinitialiaztion join point</listitem>
- <listitem>staticinitialization join point</listitem>
- <listitem>perthis aspect</listitem>
- <listitem>pertarget aspect</listitem>
- <listitem>declare parents</listitem>
- <listitem>declare method or field (see interface caveats below)</listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>Implementation Caveats</para>
- <itemizedlist spacing="compact">
- <listitem>
- <para>The initialization and preinitialization join points
- do not support around advice</para>
- </listitem>
- <listitem>
- <para>The handler join point does not support...</para>
- <itemizedlist spacing="compact">
- <listitem>after advice</listitem>
- <listitem>around advice</listitem>
- <listitem>cflow(handler(..))</listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>Declaring members on an interface in an aspect affects only
- the topmost implementing classes the implementation controls.</para>
- </listitem>
- <listitem>
- <para>cflow and cflowbelow pointcuts work within a single thread.</para>
- </listitem>
- <listitem>
- <para>
- Runtime <literal>ClassCastException</literal> may result
- from supplying a supertype of the actual type as an argument
- to proceed(..) in around advice.</para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
-</sect1>
-</appendix>
-
-
-
diff --git a/docs/progguide/language.xml b/docs/progguide/language.xml
deleted file mode 100644
index 48b0fa62d..000000000
--- a/docs/progguide/language.xml
+++ /dev/null
@@ -1,1354 +0,0 @@
-<chapter id="language" xreflabel="The AspectJ Language">
-
- <title>The AspectJ Language</title>
-
- <sect1 id="language-intro">
- <title>Introduction</title>
-
- <para>
- The previous chapter, <xref linkend="starting" />, was a brief
- overview of the AspectJ language. You should read this chapter to
- understand AspectJ's syntax and semantics. It covers the same
- material as the previous chapter, but more completely and in much
- more detail.
- </para>
-
- <para>
- We will start out by looking at an example aspect that we'll build
- out of a pointcut, an introduction, and two pieces of advice. This
- example aspect will gives us something concrete to talk about.
- </para>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="language-anatomy">
- <title>The Anatomy of an Aspect</title>
-
- <para>
- This lesson explains the parts of AspectJ's aspects. By reading this
- lesson you will have an overview of what's in an aspect and you will
- be exposed to the new terminology introduced by AspectJ.
- </para>
-
- <sect2 id="an-example-aspect" xreflabel="an-example-aspect">
- <title>An Example Aspect</title>
-
- <para>
- Here's an example of an aspect definition in AspectJ:
- </para>
-
- <programlisting><![CDATA[
- 1 aspect FaultHandler {
- 2
- 3 private boolean Server.disabled = false;
- 4
- 5 private void reportFault() {
- 6 System.out.println("Failure! Please fix it.");
- 7 }
- 8
- 9 public static void fixServer(Server s) {
-10 s.disabled = false;
-11 }
-12
-13 pointcut services(Server s): target(s) && call(public * *(..));
-14
-15 before(Server s): services(s) {
-16 if (s.disabled) throw new DisabledException();
-17 }
-18
-19 after(Server s) throwing (FaultException e): services(s) {
-20 s.disabled = true;
-21 reportFault();
-22 }
-23 }
-]]></programlisting>
-
- <para>
- The <literal>FaultHandler</literal> consists of one inter-type
- field on <literal>Server</literal> (line 03), two methods (lines
- 05-07 and 09-11), one pointcut definition (line 13), and two pieces
- of advice (lines 15-17 and 19-22).
- </para>
-
- <para>
- This covers the basics of what aspects can contain. In general,
- aspects consist of an association of other program entities,
- ordinary variables and methods, pointcut definitions, inter-type declarations,
- and advice, where advice may be before, after or around advice. The
- remainder of this lesson focuses on those crosscut-related
- constructs.
- </para>
- </sect2>
-
- <sect2 id="pointcuts" xreflabel="pointcuts">
- <title>Pointcuts</title>
-
- <para>
- AspectJ's pointcut definitions give names to pointcuts. Pointcuts
- themselves pick out join points, i.e. interesting points in the
- execution of a program. These join points can be method or
- constructor invocations and executions, the handling of exceptions,
- field assignments and accesses, etc. Take, for example, the
- pointcut definition in line 13:
- </para>
-
-<programlisting><![CDATA[
-pointcut services(Server s): target(s) && call(public * *(..))
-]]></programlisting>
-
- <para>
- This pointcut, named <literal>services</literal>, picks out those
- points in the execution of the program when
- <literal>Server</literal> objects have their public methods called.
- It also allows anyone using the <literal>services</literal>
- pointcut to access the <literal>Server</literal> object whose
- method is being called.
- </para>
-
- <para>
- The idea behind this pointcut in the
- <literal>FaultHandler</literal> aspect is that
- fault-handling-related behavior must be triggered on the calls to
- public methods. For example, the server may be unable to proceed
- with the request because of some fault. The calls of those methods
- are, therefore, interesting events for this aspect, in the sense
- that certain fault-related things will happen when these events
- occur.
- </para>
-
- <para>
- Part of the context in which the events occur is exposed by the
- formal parameters of the pointcut. In this case, that consists of
- objects of type <literal>Server</literal>. That formal parameter
- is then being used on the right hand side of the declaration in
- order to identify which events the pointcut refers to. In this
- case, a pointcut picking out join points where a Server is the
- target of some operation (target(s)) is being composed
- (<literal><![CDATA[&&]]></literal>, meaning and) with a pointcut
- picking out call join points (call(...)). The calls are identified
- by signatures that can include wild cards. In this case, there are
- wild cards in the return type position (first *), in the name
- position (second *) and in the argument list position (..); the
- only concrete information is given by the qualifier
- <literal>public</literal>.
- </para>
-
- <para>
- Pointcuts pick out arbitrarily large numbers of join points of a
- program. But they pick out only a small number of
- <emphasis>kinds</emphasis> of join points. Those kinds of join
- points correspond to some of the most important concepts in
- Java. Here is an incomplete list: method call, method execution,
- exception handling, instantiation, constructor execution, and
- field access. Each kind of join point can be picked out by its
- own specialized pointcut that you will learn about in other parts
- of this guide.
- </para>
- </sect2>
-
-<!-- ============================== -->
-
-<!-- ============================== -->
-
- <sect2 id="advice" xreflabel="advice">
- <title>Advice</title>
-
- <para>
- A piece of advice brings together a pointcut and a body of code to
- define aspect implementation that runs at join points picked out by
- the pointcut. For example, the advice in lines 15-17 specifies that
- the following piece of code
- </para>
-
-<programlisting><![CDATA[
-{
- if (s.disabled) throw new DisabledException();
-}
-]]></programlisting>
-
- <para>
- is executed when instances of the <literal>Server</literal> class
- have their public methods called, as specified by the pointcut
- <literal>services</literal>. More specifically, it runs when those
- calls are made, just before the corresponding methods are executed.
- </para>
-
- <para>
- The advice in lines 19-22 defines another piece of implementation
- that is executed on the same pointcut:
- </para>
-
-<programlisting><![CDATA[
-{
- s.disabled = true;
- reportFault();
-}
-]]></programlisting>
-
- <para>
- But this second method executes after those operations throw
- exception of type <literal>FaultException</literal>.
- </para>
-
- <para>
- There are two other variations of after advice: upon successful
- return and upon return, either successful or with an exception.
- There is also a third kind of advice called around. You will see
- those in other parts of this guide.
- </para>
- </sect2>
-
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="language-joinPoints">
- <title>Join Points and Pointcuts</title>
-
- <para>
- Consider the following Java class:
- </para>
-
-<programlisting><![CDATA[
-class Point {
- private int x, y;
-
- Point(int x, int y) { this.x = x; this.y = y; }
-
- void setX(int x) { this.x = x; }
- void setY(int y) { this.y = y; }
-
- int getX() { return x; }
- int getY() { return y; }
-}
-]]></programlisting>
-
- <para>
- In order to get an intuitive understanding of AspectJ's join points
- and pointcuts, let's go back to some of the basic principles of
- Java. Consider the following a method declaration in class Point:
- </para>
-
-<programlisting><![CDATA[
-void setX(int x) { this.x = x; }
-]]></programlisting>
-
- <para>
- This piece of program says that when method named
- <literal>setX</literal> with an <literal>int</literal> argument
- called on an object of type <literal>Point</literal>, then the method
- body <literal>{ this.x = x; }</literal> is executed. Similarly, the
- constructor of the class states that when an object of type
- <literal>Point</literal> is instantiated through a constructor with
- two <literal>int</literal> arguments, then the constructor body
- <literal>{ this.x = x; this.y = y; }</literal> is executed.
- </para>
-
- <para>
- One pattern that emerges from these descriptions is
-
- <blockquote>
- When something happens, then something gets executed.
- </blockquote>
-
- In object-oriented programs, there are several kinds of "things that
- happen" that are determined by the language. We call these the join
- points of Java. Join points consist of things like method calls,
- method executions, object instantiations, constructor executions,
- field references and handler executions. (See the <xref
- linkend="quick" /> for a complete listing.)
- </para>
-
- <para>
- Pointcuts pick out these join points. For example, the pointcut
- </para>
-
-<programlisting><![CDATA[
-pointcut setter(): target(Point) &&
- (call(void setX(int)) ||
- call(void setY(int)));
-]]></programlisting>
-
- <para>
- picks out each call to <literal>setX(int)</literal> or
- <literal>setY(int)</literal> when called on an instance of
- <literal>Point</literal>. Here's another example:
- </para>
-
-<programlisting><![CDATA[
-pointcut ioHandler(): within(MyClass) && handler(IOException);
-]]></programlisting>
-
- <para>
- This pointcut picks out each the join point when exceptions of type
- <literal>IOException</literal> are handled inside the code defined by
- class <literal>MyClass</literal>.
- </para>
-
- <para>
- Pointcut definitions consist of a left-hand side and a right-hand side,
- separated by a colon. The left-hand side consists of the pointcut name
- and the pointcut parameters (i.e. the data available when the events
- happen). The right-hand side consists of the pointcut itself.
- </para>
-
- <sect2 id="some-example-pointcuts" xreflabel="some-example-pointcuts">
- <title>Some Example Pointcuts</title>
-
- <para>
- Here are examples of pointcuts picking out
- </para>
-
- <variablelist>
- <varlistentry>
- <term>when a particular method body executes</term>
- <listitem>
- <para>
- <literal>execution(void Point.setX(int))</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>when a method is called</term>
- <listitem>
- <para>
- <literal>call(void Point.setX(int))</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>when an exception handler executes</term>
- <listitem>
- <para>
- <literal>handler(ArrayOutOfBoundsException)</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- when the object currently executing
- (i.e. <literal>this</literal>) is of type
- <literal>SomeType</literal>
- </term>
- <listitem>
- <para>
- <literal>this(SomeType)</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- when the target object is of type <literal>SomeType</literal>
- </term>
- <listitem>
- <para>
- <literal>target(SomeType)</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- when the executing code belongs to
- class <literal>MyClass</literal>
- </term>
- <listitem>
- <para>
- <literal>within(MyClass)</literal>
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- when the join point is in the control flow of a call to a
- <literal>Test</literal>'s no-argument <literal>main</literal>
- method
- </term>
- <listitem>
- <para>
- <literal>cflow(call(void Test.main()))</literal>
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Pointcuts compose through the operations <literal>or</literal>
- ("<literal>||</literal>"), <literal>and</literal>
- ("<literal><![CDATA[&&]]></literal>") and <literal>not</literal>
- ("<literal>!</literal>").
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- It is possible to use wildcards. So
-
- <orderedlist>
- <listitem>
- <para>
- <literal>execution(* *(..))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>call(* set(..))</literal>
- </para>
- </listitem>
- </orderedlist>
-
- means (1) the execution of any method regardless of return or
- parameter types, and (2) the call to any method named
- <literal>set</literal> regardless of return or parameter types
- -- in case of overloading there may be more than one such
- <literal>set</literal> method; this pointcut picks out calls to
- all of them.
- </para>
- </listitem>
-
- <listitem>
- <para>
- You can select elements based on types. For example,
- <orderedlist>
- <listitem>
- <para>
- <literal>execution(int *())</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>call(* setY(long))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>call(* Point.setY(int))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>call(*.new(int, int))</literal>
- </para>
- </listitem>
-
- </orderedlist>
-
- means (1) the execution of any method with no parameters that
- returns an <literal>int</literal>, (2) the call to any
- <literal>setY</literal> method that takes a
- <literal>long</literal> as an argument, regardless of return
- type or declaring type, (3) the call to any of
- <literal>Point</literal>'s <literal>setY</literal> methods that
- take an <literal>int</literal> as an argument, regardless of
- return type, and (4) the call to any classes' constructor, so
- long as it takes exactly two <literal>int</literal>s as
- arguments.
- </para>
- </listitem>
-
- <listitem>
- <para>
- You can compose pointcuts. For example,
- <orderedlist>
- <listitem>
- <para>
- <literal>target(Point) <![CDATA[&&]]> call(int *())</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>call(* *(..)) <![CDATA[&&]]> (within(Line) || within(Point))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>within(*) <![CDATA[&&]]> execution(*.new(int))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>
- !this(Point) <![CDATA[&&]]> call(int *(..))
- </literal>
- </para>
- </listitem>
- </orderedlist>
-
- means (1) any call to an <literal>int</literal> method with no
- arguments on an instance of <literal>Point</literal>,
- regardless of its name, (2) any call to any method where the
- call is made from the code in <literal>Point</literal>'s or
- <literal>Line</literal>'s type declaration, (3) the execution of
- any constructor taking exactly one <literal>int</literal>
- argument, regardless of where the call is made from, and
- (4) any method call to an <literal>int</literal> method when
- the executing object is any type except <literal>Point</literal>.
- </para>
- </listitem>
-
- <listitem>
- <para>
- You can select methods and constructors based on their
- modifiers and on negations of modifiers. For example, you can
- say:
- <orderedlist>
- <listitem>
- <para>
- <literal>call(public * *(..))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal>execution(!static * *(..))</literal>
- </para>
- </listitem>
-
- <listitem>
- <para>
- <literal> execution(public !static * *(..))</literal>
- </para>
- </listitem>
-
- </orderedlist>
- which means (1) any call to a public method, (2) any
- execution of a non-static method, and (3) any execution of a
- public, non-static method.
- </para>
- </listitem>
-
- <listitem>
- <para>
- Pointcuts can also deal with interfaces. For example, given the
- interface </para>
-
-<programlisting><![CDATA[
-interface MyInterface { ... }
-]]></programlisting>
-
- <para>
- the pointcut <literal>call(* MyInterface.*(..))</literal> picks
- out any call to a method in <literal>MyInterface</literal>'s
- signature -- that is, any method defined by
- <literal>MyInterface</literal> or inherited by one of its a
- supertypes.
- </para>
- </listitem>
-
- </itemizedlist>
- </sect2>
-
- <sect2 id="call-vs-execution" xreflabel="call-vs-execution">
- <title>call vs. execution</title>
-
- <para>
- When methods and constructors run, there are two interesting times
- associated with them. That is when they are called, and when they
- actually execute.
- </para>
-
- <para>
- AspectJ exposes these times as call and execution join points,
- respectively, and allows them to be picked out specifically by
- <literal>call</literal> and <literal>execution</literal> pointcuts.
- </para>
-
- <para>
- So what's the difference between these join points? Well, there are a
- number of differences:
- </para>
-
- <para>
- Firstly, the lexical pointcut declarations
- <literal>within</literal> and <literal>withincode</literal> match
- differently. At a call join point, the enclosing code is that of
- the call site. This means that <literal>call(void m())
- <![CDATA[&&]]> withincode(void m())</literal> will only capture
- directly recursive calls, for example. At an execution join point,
- however, the program is already executing the method, so the
- enclosing code is the method itself: <literal>execution(void m())
- <![CDATA[&&]]> withincode(void m())</literal> is the same as
- <literal>execution(void m())</literal>.
- </para>
-
- <para>
- Secondly, the call join point does not capture super calls to
- non-static methods. This is because such super calls are different in
- Java, since they don't behave via dynamic dispatch like other calls to
- non-static methods.
- </para>
-
- <para>
- The rule of thumb is that if you want to pick a join point that
- runs when an actual piece of code runs (as is often the case for
- tracing), use <literal>execution</literal>, but if you want to pick
- one that runs when a particular <emphasis>signature</emphasis> is
- called (as is often the case for production aspects), use
- <literal>call</literal>.
- </para>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="pointcut-composition" xreflabel="pointcut-composition">
- <title>Pointcut composition</title>
-
- <para>
- Pointcuts are put together with the operators and (spelled
- <literal>&amp;&amp;</literal>), or (spelled <literal>||</literal>),
- and not (spelled <literal>!</literal>). This allows the creation
- of very powerful pointcuts from the simple building blocks of
- primitive pointcuts. This composition can be somewhat confusing
- when used with primitive pointcuts like <literal>cflow</literal>
- and <literal>cflowbelow</literal>. Here's an example:
- </para>
-
- <para>
- <literal>cflow(<replaceable>P</replaceable>)</literal> picks out
- each join point in the control flow of the join points picked out
- by <replaceable>P</replaceable>. So, pictorially:
- </para>
-
-<programlisting>
-P ---------------------
- \
- \ cflow of P
- \
-</programlisting>
-
-
- <para>
- What does <literal>cflow(<replaceable>P</replaceable>) &amp;&amp;
- cflow(<replaceable>Q</replaceable>)</literal> pick out? Well, it
- picks out each join point that is in both the control flow of
- <replaceable>P</replaceable> and in the control flow of
- <replaceable>Q</replaceable>. So...
- </para>
-
-<programlisting>
- P ---------------------
- \
- \ cflow of P
- \
- \
- \
-Q -------------\-------
- \ \
- \ cflow of Q \ cflow(P) &amp;&amp; cflow(Q)
- \ \
-</programlisting>
-
- <para>
- Note that <replaceable>P</replaceable> and
- <replaceable>Q</replaceable> might not have any join points in
- common... but their control flows might have join points in common.
- </para>
-
- <para>
- But what does <literal>cflow(<replaceable>P</replaceable>
- &amp;&amp; <replaceable>Q</replaceable>)</literal> mean? Well, it
- means the control flow of those join points that are both picked
- out by <replaceable>P</replaceable> and picked out by
- <replaceable>Q</replaceable>.
- </para>
-
-<programlisting>
-P &amp;&amp; Q -------------------
- \
- \ cflow of (P &amp;&amp; Q)
- \
-</programlisting>
-
- <para>
- and if there are <emphasis>no</emphasis> join points that are both
- picked by <replaceable>P</replaceable> and picked out by
- <replaceable>Q</replaceable>, then there's no chance that there are
- any join points in the control flow of
- <literal>(<replaceable>P</replaceable> &amp;&amp;
- <replaceable>Q</replaceable>)</literal>.
- </para>
-
- <para>
- Here's some code that expresses this.
- </para>
-
-<programlisting><![CDATA[
-public class Test {
- public static void main(String[] args) {
- foo();
- }
- static void foo() {
- goo();
- }
- static void goo() {
- System.out.println("hi");
- }
-}
-
-aspect A {
- pointcut fooPC(): execution(void Test.foo());
- pointcut gooPC(): execution(void Test.goo());
- pointcut printPC(): call(void java.io.PrintStream.println(String));
-
- before(): cflow(fooPC()) && cflow(gooPC()) && printPC() && !within(A) {
- System.out.println("should occur");
- }
-
- before(): cflow(fooPC() && gooPC()) && printPC() && !within(A) {
- System.out.println("should not occur");
- }
-}
-]]></programlisting>
-
- <para>
- The <literal>!within(<replaceable>A</replaceable>)</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.
- (See <xref linkend="pitfalls-infiniteLoops"/> for more details.)
- </para>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="pointcut-parameters" xreflabel="pointcut-parameters">
- <title>Pointcut Parameters</title>
-
- <para>
- Consider again the first pointcut definition in this chapter:
- </para>
-
-<programlisting><![CDATA[
-pointcut setter(): target(Point) &&
- (call(void setX(int)) ||
- call(void setY(int)));
-]]></programlisting>
-
- <para>
- As we've seen, this pointcut picks out each call to
- <literal>setX(int)</literal> or <literal>setY(int)</literal>
- methods where the target is an instance of
- <literal>Point</literal>. The pointcut is given the name
- <literal>setters</literal> and no parameters on the left-hand
- side. An empty parameter list means that none of the context from
- the join points is published from this pointcut. But consider
- another version of version of this pointcut definition:
- </para>
-
-<programlisting><![CDATA[
-pointcut setter(Point p): target(p) &&
- (call(void setX(int)) ||
- call(void setY(int)));
-]]></programlisting>
-
- <para>
- This version picks out exactly the same join points. But in this
- version, the pointcut has one parameter of type
- <literal>Point</literal>. This means that any advice that uses this
- pointcut has access to a <literal>Point</literal> from each join
- point picked out by the pointcut. Inside the pointcut definition
- this <literal>Point</literal> is named <literal>p</literal> is
- available, and according to the right-hand side of the definition,
- that <literal>Point p</literal> comes from the
- <literal>target</literal> of each matched join point.
- </para>
-
- <para>
- Here's another example that illustrates the flexible mechanism for
- defining pointcut parameters:
- </para>
-
-<programlisting><![CDATA[
-pointcut testEquality(Point p): target(Point) &&
- args(p) &&
- call(boolean equals(Object));
-]]></programlisting>
-
- <para>
- This pointcut also has a parameter of type
- <literal>Point</literal>. Similar to the
- <literal>setters</literal> pointcut, this means that anyone using
- this pointcut has access to a <literal>Point</literal> from each
- join point. But in this case, looking at the right-hand side we
- find that the object named in the parameters is not the target
- <literal>Point</literal> object that receives the call; it's the
- argument (also of type <literal>Point</literal>) passed to the
- <literal>equals</literal> method when some other
- <literal>Point</literal> is the target. If we wanted access to both
- <literal>Point</literal>s, then the pointcut definition that would
- expose target <literal>Point p1</literal> and argument
- <literal>Point p2</literal> would be
- </para>
-
-<programlisting><![CDATA[
-pointcut testEquality(Point p1, Point p2): target(p1) &&
- args(p2) &&
- call(boolean equals(Object));
-]]></programlisting>
-
- <para>
- Let's look at another variation of the <literal>setters</literal> pointcut:
- </para>
-
-<programlisting><![CDATA[
-pointcut setter(Point p, int newval): target(p) &&
- args(newval) &&
- (call(void setX(int)) ||
- call(void setY(int)));
-]]></programlisting>
-
- <para>
- In this case, a <literal>Point</literal> object and an
- <literal>int</literal> value are exposed by the named
- pointcut. Looking at the the right-hand side of the definition, we
- find that the <literal>Point</literal> object is the target object,
- and the <literal>int</literal> value is the called method's
- argument.
- </para>
-
- <para>
- The use of pointcut parameters is relatively flexible. The most
- important rule is that all the pointcut parameters must be bound at
- every join point picked out by the pointcut. So, for example, the
- 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)));
-]]></programlisting>
-
- because <literal>p1</literal> is only bound when calling
- <literal>setX</literal>, and <literal>p2</literal> is only bound
- when calling <literal>setY</literal>, but the pointcut picks out
- all of these join points and tries to bind both
- <literal>p1</literal> and <literal>p2</literal>.
- </para>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="example" xreflabel="example">
- <title>Example: <literal>HandleLiveness</literal></title>
-
- <para>
- The example below consists of two object classes (plus an exception
- class) and one aspect. Handle objects delegate their public,
- non-static operations to their <literal>Partner</literal>
- objects. The aspect <literal>HandleLiveness</literal> ensures that,
- before the delegations, the partner exists and is alive, or else it
- throws an exception.
- </para>
-
-<programlisting><![CDATA[
-class Handle {
- Partner partner = new Partner();
-
- 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);
- }
-}
-
-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();
- }
- }
-}
-
-class DeadPartnerException extends RuntimeException {}
-]]></programlisting>
-
- </sect2>
-
- <sect2 id="pointcut-best-practice" xreflabel="pointcut-best-practice">
- <title>Writing good pointcuts</title>
-
- <para>
- During compilation, AspectJ processes pointcuts in order to try and optimize matching performance. Examining code and determining
- if each join point matches (statically or dynamically) a given pointcut is a costly process.
- (A dynamic match means the match cannot be fully determined from static analysis and a test will be placed in the code
- to determine if there is an actual match when the code is running).
- On first encountering a pointcut declaration, AspectJ will rewrite it into an optimal form for the matching process.
- What does this mean? Basically pointcuts are rewritten in DNF (Disjunctive Normal Form) and the components of the pointcut
- are sorted such that those components that are cheaper to evaluate are checked first. This means users do not have to worry
- about understanding the performance of various pointcut designators and may supply them in any order in their
- pointcut declarations.
- </para>
- <para>
- However, AspectJ can only work with what it is told, and for optimal performance of matching the user should think
- about what they are trying to achieve and narrow the search space for matches as much as they can in the definition.
- Basically there are three kinds of pointcut designator: kinded, scoping and context:
- </para>
- <itemizedlist>
- <listitem>
- Kinded designators are those which select a particular kind of join point. For example: execution, get, set, call, handler
- </listitem>
- <listitem>
- Scoping designators are those which select a group of join points of interest (of probably many kinds). For example: within, withincode
- </listitem>
- <listitem>
- Contextual designators are those that match (and optionally bind) based on context. For example: this, target, @annotation
- </listitem>
- </itemizedlist>
- <para>
- 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
- processed - that is why a good pointcut should always include one if possible.
- </para>
-
- </sect2>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="language-advice">
- <title>Advice</title>
-
- <para>
- Advice defines pieces of aspect implementation that execute at
- well-defined points in the execution of the program. Those points can
- be given either by named pointcuts (like the ones you've seen above)
- or by anonymous pointcuts. Here is an example of an advice on a named
- pointcut:
- </para>
-
-<programlisting><![CDATA[
-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);
-}
-]]></programlisting>
-
- <para>
- And here is exactly the same example, but using an anonymous
- pointcut:
- </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);
-}
-]]></programlisting>
-
- <para>
- Here are examples of the different advice:
- </para>
-
- <para>
- This before advice runs just before the join points picked out by the
- (anonymous) pointcut:
- </para>
-
-<programlisting><![CDATA[
-before(Point p, int x): target(p) && args(x) && call(void setX(int)) {
- if (!p.assertX(x)) return;
-}
-]]></programlisting>
-
- <para>
- This after advice runs just after each join point picked out by the
- (anonymous) pointcut, regardless of whether it returns normally or throws
- an exception:
- </para>
-
-<programlisting><![CDATA[
-after(Point p, int x): target(p) && args(x) && call(void setX(int)) {
- if (!p.assertX(x)) throw new PostConditionViolation();
-}
-]]></programlisting>
-
- <para>
- This after returning advice runs just after each join point picked
- out by the (anonymous) pointcut, but only if it returns normally.
- The return value can be accessed, and is named <literal>x</literal>
- here. After the advice runs, the return value is returned:
- </para>
-
-<programlisting><![CDATA[
-after(Point p) returning(int x): target(p) && call(int getX()) {
- System.out.println("Returning int value " + x + " for p = " + p);
-}
-]]></programlisting>
-
- <para>
- This after throwing advice runs just after each join point picked out by
- the (anonymous) pointcut, but only when it throws an exception of type
- <literal>Exception</literal>. Here the exception value can be accessed
- with the name <literal>e</literal>. The advice re-raises the exception
- after it's done:
- </para>
-
-<programlisting><![CDATA[
-after() throwing(Exception e): target(Point) && call(void setX(int)) {
- System.out.println(e);
-}
-]]></programlisting>
-
- <para>
- This around advice traps the execution of the join point; it runs
- <emphasis>instead</emphasis> of the join point. The original action
- associated with the join point can be invoked through the special
- <literal>proceed</literal> call:
- </para>
-
-<programlisting><![CDATA[
-void around(Point p, int x): target(p)
- && args(x)
- && call(void setX(int)) {
- if (p.assertX(x)) proceed(p, x);
- p.releaseResources();
-}
-]]></programlisting>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="language-interType">
- <title>Inter-type declarations</title>
-
- <para>
- Aspects can declare members (fields, methods, and constructors) that
- are owned by other types. These are called inter-type members.
- Aspects can also declare that other types implement new interfaces or
- extend a new class. Here are examples of some such inter-type
- declarations:
- </para>
-
- <para>
- This declares that each <literal>Server</literal> has a
- <literal>boolean</literal> field named <literal>disabled</literal>,
- initialized to <literal>false</literal>:
-
-<programlisting><![CDATA[
-private boolean Server.disabled = false;
-]]></programlisting>
-
- It is declared <literal>private</literal>, which means that it is
- private <emphasis>to the aspect</emphasis>: only code in the aspect
- can see the field. And even if <literal>Server</literal> has
- another private field named <literal>disabled</literal> (declared in
- <literal>Server</literal> or in another aspect) there won't be a name
- collision, since no reference to <literal>disabled</literal> will be
- ambiguous.
- </para>
-
- <para>
- This declares that each <literal>Point</literal> has an
- <literal>int</literal> method named <literal>getX</literal> with no
- arguments that returns whatever <literal>this.x</literal> is:
-
-<programlisting><![CDATA[
-public int Point.getX() { return this.x; }
-]]></programlisting>
-
- Inside the body, <literal>this</literal> is the
- <literal>Point</literal> object currently executing. Because the
- method is publically declared any code can call it, but if there is
- some other <literal>Point.getX()</literal> declared there will be a
- compile-time conflict.
- </para>
-
- <para>
- This publically declares a two-argument constructor for
- <literal>Point</literal>:
-
-<programlisting><![CDATA[
-public Point.new(int x, int y) { this.x = x; this.y = y; }
-]]></programlisting>
-
- </para>
-
- <para>
- This publicly declares that each <literal>Point</literal> has an
- <literal>int</literal> field named <literal>x</literal>, initialized
- to zero:
-
-<programlisting><![CDATA[
-public int Point.x = 0;
-]]></programlisting>
-
- Because this is publically declared, it is an error if
- <literal>Point</literal> already has a field named
- <literal>x</literal> (defined by <literal>Point</literal> or by
- another aspect).
- </para>
-
- <para>
- This declares that the <literal>Point</literal> class implements the
- <literal>Comparable</literal> interface:
-
-<programlisting><![CDATA[
-declare parents: Point implements Comparable;
-]]></programlisting>
-
- Of course, this will be an error unless <literal>Point</literal>
- defines the methods required by <literal>Comparable</literal>.
- </para>
-
- <para>
- This declares that the <literal>Point</literal> class extends the
- <literal>GeometricObject</literal> class.
-
-<programlisting><![CDATA[
-declare parents: Point extends GeometricObject;
-]]></programlisting>
- </para>
-
- <para>
- An aspect can have several inter-type declarations. For example, the
- following declarations
-
-<programlisting><![CDATA[
-public String Point.name;
-public void Point.setName(String name) { this.name = name; }
-]]></programlisting>
-
- publicly declare that Point has both a String field
- <literal>name</literal> and a <literal>void</literal> method
- <literal>setName(String)</literal> (which refers to the
- <literal>name</literal> field declared by the aspect).
- </para>
-
- <para>
- An inter-type member can only have one target type, but often you may
- wish to declare the same member on more than one type. This can be
- done by using an inter-type member in combination with a private
- interface:
-
-<programlisting><![CDATA[
-aspect A {
- private interface HasName {}
- declare parents: (Point || Line || Square) implements HasName;
-
- private String HasName.name;
- public String HasName.getName() { return name; }
-}
-]]></programlisting>
-
- This declares a marker interface <literal>HasName</literal>, and also declares that any
- type that is either <literal>Point</literal>,
- <literal>Line</literal>, or <literal>Square</literal> implements that
- interface. It also privately declares that all <literal>HasName</literal>
- object have a <literal>String</literal> field called
- <literal>name</literal>, and publically declares that all
- <literal>HasName</literal> objects have a <literal>String</literal>
- method <literal>getName()</literal> (which refers to the privately
- declared <literal>name</literal> field).
- </para>
-
- <para>
- As you can see from the above example, an aspect can declare that
- interfaces have fields and methods, even non-constant fields and
- methods with bodies.
- </para>
-
-<!-- ============================== -->
-
- <sect2 id="inter-type-scope" xreflabel="inter-type-scope">
- <title>Inter-type Scope</title>
-
- <para>
- AspectJ allows private and package-protected (default) inter-type declarations in
- addition to public inter-type declarations. Private means private in
- relation to the aspect, not necessarily the target type. So, if an
- aspect makes a private inter-type declaration of a field
-
-<programlisting><![CDATA[
-private int Foo.x;
-]]></programlisting>
-
- Then code in the aspect can refer to <literal>Foo</literal>'s
- <literal>x</literal> field, but nobody else can. Similarly, if an
- aspect makes a package-protected introduction,
- </para>
-
-<programlisting><![CDATA[
- int Foo.x;
-]]></programlisting>
-
- <para>
- then everything in the aspect's package (which may or may not be
- <literal>Foo</literal>'s package) can access <literal>x</literal>.
- </para>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="example-pointassertions" xreflabel="example-pointassertions">
- <title>Example: <literal>PointAssertions</literal></title>
-
- <para>
- The example below consists of one class and one aspect. The aspect
- privately declares the assertion methods of
- <literal>Point</literal>, <literal>assertX</literal> and
- <literal>assertY</literal>. It also guards calls to
- <literal>setX</literal> and <literal>setY</literal> with calls to
- these assertion methods. The assertion methods are declared
- privately because other parts of the program (including the code in
- <literal>Point</literal>) have no business accessing the assert
- methods. Only the code inside of the aspect can call those
- methods.
- </para>
-
-<programlisting><![CDATA[
-class Point {
- int x, 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);
- }
-}
-
-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>
- </sect1>
-
-<!-- ================================================== -->
-
- <sect1 id="language-thisJoinPoint">
- <title>thisJoinPoint</title>
-
- <para>
- AspectJ provides a special reference variable,
- <literal>thisJoinPoint</literal>, that contains reflective
- information about the current join point for the advice to use. The
- <literal>thisJoinPoint</literal> variable can only be used in the
- context of advice, just like <literal>this</literal> can only be used
- in the context of non-static methods and variable initializers. In
- advice, <literal>thisJoinPoint</literal> is an object of type <ulink
- url="../api/org/aspectj/lang/JoinPoint.html"><literal>org.aspectj.lang.JoinPoint</literal></ulink>.
- </para>
-
- <para>
- One way to use it is simply to print it out. Like all Java objects,
- <literal>thisJoinPoint</literal> has a <literal>toString()</literal>
- method that makes quick-and-dirty tracing easy:
- </para>
-
-<programlisting><![CDATA[
-aspect TraceNonStaticMethods {
- before(Point p): target(p) && call(* *(..)) {
- System.out.println("Entering " + thisJoinPoint + " in " + p);
- }
-}
-]]></programlisting>
-
- <para>
- The type of <literal>thisJoinPoint</literal> includes a rich
- reflective class hierarchy of signatures, and can be used to access
- both static and dynamic information about join points such as the
- arguments of the join point:
-
-<programlisting><![CDATA[
-thisJoinPoint.getArgs()
-]]></programlisting>
-
- In addition, it holds an object consisting of all the static
- information about the join point such as corresponding line number
- and static signature:
-
-<programlisting><![CDATA[
-thisJoinPoint.getStaticPart()
-]]></programlisting>
-
- If you only need the static information about the join point, you may
- access the static part of the join point directly with the special
- variable <literal>thisJoinPointStaticPart</literal>. Using
- <literal>thisJoinPointStaticPart</literal> will avoid the run-time
- creation of the join point object that may be necessary when using
- <literal>thisJoinPoint</literal> directly.
- </para>
-
- <para>It is always the case that
- </para>
-
-<programlisting><![CDATA[
-thisJoinPointStaticPart == thisJoinPoint.getStaticPart()
-
-thisJoinPoint.getKind() == thisJoinPointStaticPart.getKind()
-thisJoinPoint.getSignature() == thisJoinPointStaticPart.getSignature()
-thisJoinPoint.getSourceLocation() == thisJoinPointStaticPart.getSourceLocation()
-]]></programlisting>
-
- <para>
- One more reflective variable is available:
- <literal>thisEnclosingJoinPointStaticPart</literal>. This, like
- <literal>thisJoinPointStaticPart</literal>, only holds the static
- part of a join point, but it is not the current but the enclosing
- join point. So, for example, it is possible to print out the calling
- source location (if available) with
- </para>
-
-<programlisting><![CDATA[
- before() : execution (* *(..)) {
- System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation())
- }
-]]></programlisting>
-
- </sect1>
-</chapter>
-
diff --git a/docs/progguide/pitfalls.xml b/docs/progguide/pitfalls.xml
deleted file mode 100644
index daf08f801..000000000
--- a/docs/progguide/pitfalls.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<chapter id="pitfalls" xreflabel="Pitfalls">
- <title>Pitfalls</title>
-
- <sect1 id="pitfalls-intro">
- <title>Introduction</title>
-
- <para>
- This chapter consists of a few AspectJ programs that may lead to
- surprising behavior and how to understand them.
- </para>
-
- </sect1>
-
- <sect1 id="pitfalls-infiniteLoops">
- <title>Infinite loops</title>
-
- <para>
- Here is a Java program with peculiar behavior
- </para>
-
-<programlisting><![CDATA[
-public class Main {
- public static void main(String[] args) {
- foo();
- System.out.println("done with call to foo");
- }
-
- static void foo() {
- try {
- foo();
- } finally {
- foo();
- }
- }
-}
-]]></programlisting>
-
- <para>
- This program will never reach the println call, but when it aborts
- may have no stack trace.
- </para>
-
- <para>
- This silence is caused by multiple StackOverflowExceptions. First
- the infinite loop in the body of the method generates one, which the
- finally clause tries to handle. But this finally clause also
- generates an infinite loop which the current JVMs can't handle
- gracefully leading to the completely silent abort.
- </para>
-
- <para>
- The following short aspect will also generate this behavior:
- </para>
-
-<programlisting><![CDATA[
-aspect A {
- before(): call(* *(..)) { System.out.println("before"); }
- after(): call(* *(..)) { System.out.println("after"); }
-}
-]]></programlisting>
-
- <para>
- Why? Because the call to println is also a call matched by the
- pointcut <literal>call (* *(..))</literal>. We get no output because
- we used simple after() advice. If the aspect were changed to
- </para>
-
-<programlisting><![CDATA[
-aspect A {
- before(): call(* *(..)) { System.out.println("before"); }
- after() returning: call(* *(..)) { System.out.println("after"); }
-}
-]]></programlisting>
-
- <para>
- Then at least a StackOverflowException with a stack trace would be
- seen. In both cases, though, the overall problem is advice applying
- within its own body.
- </para>
-
- <para>
- There's a simple idiom to use if you ever have a worry that your
- advice might apply in this way. Just restrict the advice from occurring in
- join points caused within the aspect. So:
- </para>
-
-<programlisting><![CDATA[
-aspect A {
- before(): call(* *(..)) && !within(A) { System.out.println("before"); }
- after() returning: call(* *(..)) && !within(A) { System.out.println("after"); }
-}
-]]></programlisting>
-
- <para>
- Other solutions might be to more closely restrict the pointcut in
- other ways, for example:
- </para>
-
-<programlisting><![CDATA[
-aspect A {
- before(): call(* MyObject.*(..)) { System.out.println("before"); }
- after() returning: call(* MyObject.*(..)) { System.out.println("after"); }
-}
-]]></programlisting>
-
- <para>
- The moral of the story is that unrestricted generic pointcuts can
- pick out more join points than intended.
- </para>
-
- </sect1>
-</chapter>
diff --git a/docs/progguide/preface.xml b/docs/progguide/preface.xml
deleted file mode 100644
index 5484fe5b3..000000000
--- a/docs/progguide/preface.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<preface id="preface">
- <title>Preface</title>
-
- <para>
- This programming guide does three things. It
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>introduces the AspectJ language</para>
- </listitem>
-
- <listitem>
- <para>
- defines each of AspectJ's constructs and their semantics, and
- </para>
- </listitem>
-
- <listitem>
- <para>
- provides examples of their use.
- </para>
- </listitem>
- </itemizedlist>
-
- It includes appendices that give a reference to the syntax of AspectJ,
- a more formal description of AspectJ's semantics, and a description of
- notes about the AspectJ implementation.
- </para>
-
- <para>
- The first section, <xref linkend="starting" />, provides a gentle
- overview of writing AspectJ programs. It also shows how one can
- introduce AspectJ into an existing development effort in stages,
- reducing the associated risk. You should read this section if this is
- your first exposure to AspectJ and you want to get a sense of what
- AspectJ is all about.
- </para>
-
- <para>
- The second section, <xref linkend="language" />, covers the features of
- the language in more detail, using code snippets as examples. All the
- basics of the language is covered, and after reading this section, you
- should be able to use the language correctly.
- </para>
-
- <para>
- The next section, <xref linkend="examples" />, comprises a set of
- complete programs that not only show the features being used, but also
- try to illustrate recommended practice. You should read this section
- after you are familiar with the elements of AspectJ.
- </para>
-
- <para>
- Finally, there are two short chapters, one on <xref linkend="idioms" />
- and one on <xref linkend="pitfalls" />.
- </para>
-
- <para>
- The back matter contains several appendices that cover a <xref
- linkend="quick">quick reference</xref> to the language's syntax, a more
- in depth coverage of its <xref linkend="semantics">semantics</xref>,
- and a description of the latitude enjoyed by its <xref
- linkend="implementation">implementations</xref>.
- </para>
-
-</preface>
diff --git a/docs/progguide/progguide.html.xsl b/docs/progguide/progguide.html.xsl
deleted file mode 100644
index 7f6a669fb..000000000
--- a/docs/progguide/progguide.html.xsl
+++ /dev/null
@@ -1,9 +0,0 @@
-<xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-<xsl:import href="../../lib/docbook/docbook-xsl/html/chunk.xsl"/>
-
-<xsl:param name="base.dir" select="'html/'"/>
-<xsl:param name="html.ext" select="'.html'"/>
-
-</xsl:stylesheet>
diff --git a/docs/progguide/progguide.xml b/docs/progguide/progguide.xml
deleted file mode 100644
index 433d71585..000000000
--- a/docs/progguide/progguide.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "../../lib/docbook/docbook-dtd/docbookx.dtd"
-[
-<!ENTITY preface SYSTEM "preface.xml">
-<!ENTITY gettingstarted SYSTEM "gettingstarted.xml">
-<!ENTITY language SYSTEM "language.xml">
-<!ENTITY examples SYSTEM "examples.xml">
-<!ENTITY idioms SYSTEM "idioms.xml">
-<!ENTITY pitfalls SYSTEM "pitfalls.xml">
-<!ENTITY quickreference SYSTEM "quickreference.xml">
-<!ENTITY semantics SYSTEM "semantics.xml">
-<!ENTITY implementation SYSTEM "implementation.xml">
-]>
-
-<book>
- <bookinfo>
- <title>The AspectJ<superscript>TM</superscript> Programming Guide</title>
-
- <authorgroup>
- <author>
- <othername>the AspectJ Team</othername>
- </author>
- </authorgroup>
-
- <legalnotice>
- <para>
- Copyright (c) 1998-2001 Xerox Corporation,
- 2002-2003 Palo Alto Research Center, Incorporated.
- All rights reserved.
- </para>
- </legalnotice>
-
- <abstract>
- <para>
- This programming guide describes the AspectJ language. A
- companion guide describes the tools which are part of the
- AspectJ development environment.
- </para>
-
- <para>
- If you are completely new to AspectJ, you should first read
- <xref linkend="starting"/> for a broad overview of programming
- in AspectJ. If you are already familiar with AspectJ, but want a deeper
- understanding, you should read <xref linkend="language"/> and
- look at the examples in the chapter. If you want a more formal
- definition of AspectJ, you should read <xref linkend="semantics"/>.
- </para>
- </abstract>
- </bookinfo>
-
- &preface;
- &gettingstarted;
- &language;
- &examples;
- &idioms;
- &pitfalls;
- &quickreference;
- &semantics;
- &implementation;
-
-</book>
diff --git a/docs/progguide/quickreference.xml b/docs/progguide/quickreference.xml
deleted file mode 100644
index ef5c3cb80..000000000
--- a/docs/progguide/quickreference.xml
+++ /dev/null
@@ -1,773 +0,0 @@
-<appendix id="quick" xreflabel="AspectJ Quick Reference">
- <title>AspectJ Quick Reference</title>
-
- <sect1 id="quick-pointcuts">
- <title>Pointcuts</title>
-
- <informaltable frame="none">
- <tgroup cols="2" align="left">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
-
- <tbody valign="top">
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Methods and Constructors</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>call(<replaceable>Signature</replaceable>)</literal>
- </entry>
-
- <entry>
- every call to any method or constructor matching
- <replaceable>Signature</replaceable> at the call site
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>execution(<replaceable>Signature</replaceable>)</literal>
- </entry>
-
- <entry>
- every execution of any method or constructor matching
- <replaceable>Signature</replaceable>
- </entry>
- </row>
-
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Fields</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>get(<replaceable>Signature</replaceable>)</literal>
- </entry>
- <entry>
- every reference to any field matching <replaceable>Signature</replaceable>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>set(<replaceable>Signature</replaceable>)</literal>
- </entry>
- <entry>
- every assignment to any field matching
- <replaceable>Signature</replaceable>. The assigned value can
- be exposed with an <literal>args</literal> pointcut
- </entry>
- </row>
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Exception Handlers</emphasis>
- </entry>
- </row>
-
- <row rowsep="1">
- <entry>
- <literal>handler(<replaceable>TypePattern</replaceable>)</literal>
- </entry>
- <entry>
- every exception handler for any <literal>Throwable</literal>
- type in <replaceable>TypePattern</replaceable>. The exception
- value can be exposed with an <literal>args</literal> pointcut
- </entry>
- </row>
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Advice</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>adviceexecution()</literal>
- </entry>
- <entry>
- every execution of any piece of advice
- </entry>
- </row>
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Initialization</emphasis>
- </entry>
- </row>
-
- <row rowsep="1">
- <entry>
- <literal>staticinitialization(<replaceable>TypePattern</replaceable>)</literal>
- </entry>
- <entry>
- every execution of a static initializer for any type in
- <replaceable>TypePattern</replaceable>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>initialization(<replaceable>Signature</replaceable>)</literal>
- </entry>
- <entry>
- every initialization of an object when the first constructor
- called in the type matches
- <replaceable>Signature</replaceable>, encompassing the return
- from the super constructor call to the return of the
- first-called constructor
- </entry>
- </row>
- <row>
- <entry>
- <literal>preinitialization(<replaceable>Signature</replaceable>)</literal>
- </entry>
- <entry>
- every pre-initialization of an object when the first
- constructor called in the type matches
- <replaceable>Signature</replaceable>, encompassing the entry
- of the first-called constructor to the call to the super
- constructor
- </entry>
- </row>
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Lexical</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>within(<replaceable>TypePattern</replaceable>)</literal>
- </entry>
- <entry>
- every join point from code defined in a type in
- <replaceable>TypePattern</replaceable>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>withincode(<replaceable>Signature</replaceable>)</literal>
- </entry>
- <entry>
- every join point from code defined in a method or constructor
- matching <replaceable>Signature</replaceable>
- </entry>
- </row>
- </tbody>
- </tgroup>
-
- <tgroup cols="2" align="left">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
- <tbody valign="top">
- <row>
- <entry namest="c1" nameend="c2" >
- <emphasis role="bold">Instanceof checks and context exposure</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>this(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal>
- </entry>
- <entry>
- every join point when the currently executing object is an
- instance of <replaceable>Type</replaceable> or
- <replaceable>Id</replaceable>'s type
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>target(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal>
- </entry>
- <entry>
- every join point when the target executing object is an
- instance of <replaceable>Type</replaceable> or
- <replaceable>Id</replaceable>'s type
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>args(<replaceable>Type</replaceable> or
- <replaceable>Id</replaceable>, ...)</literal>
- </entry>
- <entry>
- every join point when the arguments are instances of
- <replaceable>Type</replaceable>s or the types of the
- <replaceable>Id</replaceable>s
- </entry>
- </row>
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Control Flow</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>cflow(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- <entry>
- every join point in the control flow of each join point
- <replaceable>P</replaceable> picked out by
- <replaceable>Pointcut</replaceable>, including
- <replaceable>P</replaceable> itself
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>cflowbelow(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- <entry>
- every join point below the control flow of each join point
- <replaceable>P</replaceable> picked out by
- <replaceable>Pointcut</replaceable>; does not include
- <replaceable>P</replaceable> itself
- </entry>
- </row>
-
- <!-- ===== -->
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Conditional</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>if(<replaceable>Expression</replaceable>)</literal>
- </entry>
- <entry>
- every join point when the boolean
- <replaceable>Expression</replaceable> is
- <literal>true</literal>
- </entry>
- </row>
- </tbody>
- </tgroup>
-
- <tgroup cols="2" align="left">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
-
- <tbody valign="top">
- <row>
- <entry namest="c1" nameend="c2">
- <emphasis role="bold">Combination</emphasis>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>! <replaceable>Pointcut</replaceable></literal>
- </entry>
- <entry>
- every join point not picked out by
- <replaceable>Pointcut</replaceable>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal><replaceable>Pointcut0</replaceable> <![CDATA[&&]]> <replaceable>Pointcut1</replaceable></literal>
- </entry>
- <entry>
- each join point picked out by both
- <replaceable>Pointcut0</replaceable> and
- <replaceable>Pointcut1</replaceable>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal><replaceable>Pointcut0</replaceable> || <replaceable>Pointcut1</replaceable></literal>
- </entry>
- <entry>
- each join point picked out by either
- <replaceable>Pointcut0</replaceable> or
- <replaceable>Pointcut1</replaceable>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>( <replaceable>Pointcut</replaceable> )</literal>
- </entry>
- <entry>
- each join point picked out by
- <replaceable>Pointcut</replaceable>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="quick-typePatterns">
- <title>Type Patterns</title>
-
- <para>
- A type pattern is one of
- </para>
-
- <informaltable frame="none">
- <tgroup cols="2" >
- <tbody valign="top">
- <row>
- <entry><replaceable>TypeNamePattern</replaceable></entry>
- <entry>all types in <replaceable>TypeNamePattern</replaceable></entry>
- </row>
- <row>
- <entry><replaceable>SubtypePattern</replaceable></entry>
- <entry>all types in <replaceable>SubtypePattern</replaceable>, a
- pattern with a +. </entry>
- </row>
- <row>
- <entry><replaceable>ArrayTypePattern</replaceable></entry>
- <entry>all types in <replaceable>ArrayTypePattern</replaceable>,
- a pattern with one or more []s. </entry>
- </row>
- <row>
- <entry><literal>!<replaceable>TypePattern</replaceable></literal></entry>
- <entry>all types not in <replaceable>TypePattern</replaceable></entry>
- </row>
- <row>
- <entry><literal><replaceable>TypePattern0</replaceable>
- <![CDATA[&&]]> <replaceable>TypePattern1</replaceable></literal></entry>
- <entry>all types in both
- <replaceable>TypePattern0</replaceable> and <replaceable>TypePattern1</replaceable></entry>
- </row>
- <row>
- <entry><literal><replaceable>TypePattern0</replaceable> || <replaceable>TypePattern1</replaceable></literal></entry>
- <entry>all types in either
- <replaceable>TypePattern0</replaceable> or <replaceable>TypePattern1</replaceable></entry>
- </row>
- <row>
- <entry><literal>( <replaceable>TypePattern</replaceable> )</literal></entry>
- <entry>all types in <replaceable>TypePattern</replaceable></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>
- where <replaceable>TypeNamePattern</replaceable> can either be a
- plain type name, the wildcard <literal>*</literal> (indicating all
- types), or an identifier with embedded <literal>*</literal> and
- <literal>..</literal> wildcards.
- </para>
-
- <para>
- An embedded <literal>*</literal> in an identifier matches any
- sequence of characters, but does not match the package (or
- inner-type) separator ".".
- </para>
-
- <para>
- An embedded <literal>..</literal> in an identifier matches any
- sequence of characters that starts and ends with the package (or
- inner-type) separator ".".
- </para>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="quick-advice">
- <title>Advice</title>
-
- <para>
- Each piece of advice is of the form
-
- <blockquote>
- <literal>[ strictfp ] <replaceable>AdviceSpec</replaceable>
- [ throws <replaceable>TypeList</replaceable> ] :
- <replaceable>Pointcut</replaceable> {
- <replaceable>Body</replaceable> } </literal>
- </blockquote>
-
- where <replaceable>AdviceSpec</replaceable> is one of
- </para>
-
- <variablelist>
- <varlistentry>
- <term>
- <literal>before( <replaceable>Formals</replaceable> ) </literal>
- </term>
- <listitem>
- runs before each join point
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>after( <replaceable>Formals</replaceable> ) returning
- [ ( <replaceable>Formal</replaceable> ) ] </literal>
- </term>
- <listitem>
- runs after each join point that returns normally. The
- optional formal gives access to the returned value
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>after( <replaceable>Formals</replaceable> ) throwing [
- ( <replaceable>Formal</replaceable> ) ] </literal>
- </term>
- <listitem>
- runs after each join point that throws a
- <literal>Throwable</literal>. If the optional formal is
- present, runs only after each join point that throws a
- <literal>Throwable</literal> of the type of
- <replaceable>Formal</replaceable>, and
- <replaceable>Formal</replaceable> gives access to the
- <literal>Throwable</literal> exception value
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <literal>after( <replaceable>Formals</replaceable> ) </literal>
- </term>
- <listitem>
- runs after each join point regardless of whether it returns
- normally or throws a <literal>Throwable</literal>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal><replaceable>Type</replaceable>
- around( <replaceable>Formals</replaceable> ) </literal>
- </term>
- <listitem>
- runs in place of each join point. The join point can be
- executed by calling <literal>proceed</literal>, which takes
- the same number and types of arguments as the around advice.
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Three special variables are available inside of advice bodies:
- </para>
-
- <variablelist>
- <varlistentry>
- <term>
- <literal>thisJoinPoint</literal>
- </term>
- <listitem>
- an object of type <ulink
- url="../api/org/aspectj/lang/JoinPoint.html"><literal>org.aspectj.lang.JoinPoint</literal></ulink>
- representing the join point at which the advice is executing.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>thisJoinPointStaticPart</literal>
- </term>
- <listitem>
- equivalent to <literal>thisJoinPoint.getStaticPart()</literal>,
- but may use fewer runtime resources.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>thisEnclosingJoinPointStaticPart</literal>
- </term>
- <listitem>
- the static part of the dynamically enclosing join point.
- </listitem>
- </varlistentry>
- </variablelist>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="quick-interType">
- <title>Inter-type member declarations</title>
-
- <para>
- Each inter-type member is one of
- </para>
-
- <variablelist>
- <varlistentry>
- <term>
- <literal>
- <replaceable>Modifiers ReturnType OnType . Id</replaceable>
- ( <replaceable>Formals</replaceable> )
- [ throws <replaceable>TypeList</replaceable> ]
- { <replaceable>Body</replaceable> }
- </literal>
- </term>
- <listitem>
- a method on <replaceable>OnType</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- abstract <replaceable>Modifiers ReturnType OnType . Id</replaceable>
- ( <replaceable>Formals</replaceable> )
- [ throws <replaceable>TypeList</replaceable> ] ;
- </literal>
- </term>
- <listitem>
- an abstract method on <replaceable>OnType</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- <replaceable>Modifiers OnType . </replaceable> new
- ( <replaceable>Formals</replaceable> )
- [ throws <replaceable>TypeList</replaceable> ]
- { <replaceable>Body</replaceable> }
- </literal>
- </term>
- <listitem>
- a constructor on <replaceable>OnType</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- <replaceable>Modifiers Type OnType . Id </replaceable>
- [ = <replaceable>Expression</replaceable> ] ;
- </literal>
- </term>
- <listitem>
- a field on <replaceable>OnType</replaceable>.
- </listitem>
- </varlistentry>
- </variablelist>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="quick-other">
- <title>Other declarations</title>
-
- <variablelist>
- <varlistentry>
- <term>
- <literal>
- declare parents :
- <replaceable>TypePattern</replaceable> extends
- <replaceable>Type</replaceable> ;
- </literal>
- </term>
- <listitem>
- the types in <replaceable>TypePattern</replaceable> extend
- <replaceable>Type</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- declare parents : <replaceable>TypePattern</replaceable>
- implements <replaceable>TypeList</replaceable> ;
- </literal>
- </term>
- <listitem>
- the types in <replaceable>TypePattern</replaceable>
- implement the types in <replaceable>TypeList</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- declare warning : <replaceable>Pointcut</replaceable> :
- <replaceable>String</replaceable> ;
- </literal>
- </term>
- <listitem>
- if any of the join points in <replaceable>Pointcut</replaceable>
- possibly exist in the program, the compiler emits the warning
- <replaceable>String</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- declare error : <replaceable>Pointcut</replaceable> :
- <replaceable>String</replaceable> ;
- </literal>
- </term>
- <listitem>
- if any of the join points in <replaceable>Pointcut</replaceable>
- could possibly exist in the program, the compiler emits the
- error <replaceable>String</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <literal>
- declare soft :
- <replaceable>Type</replaceable> :
- <replaceable>Pointcut</replaceable> ;
- </literal>
- </term>
- <listitem>
- any <replaceable>Type</replaceable> exception
- that gets thrown at any join point picked out by
- <replaceable>Pointcut</replaceable> is wrapped in <ulink
- url="../api/org/aspectj/lang/SoftException.html"><literal>org.aspectj.lang.SoftException</literal></ulink>.
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <literal>
- declare precedence :
- <replaceable>TypePatternList</replaceable> ;
- </literal>
- </term>
- <listitem>
- at any join point where multiple pieces of advice
- apply, the advice precedence at that join point is in
- <replaceable>TypePatternList</replaceable> order.
- </listitem>
- </varlistentry>
- </variablelist>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="quick-aspectAssociations">
- <title>Aspects</title>
-
- <para>
- Each aspect is of the form
-
- <blockquote>
- <literal>
- [ privileged ] <replaceable>Modifiers</replaceable>
- aspect <replaceable>Id</replaceable>
- [ extends <replaceable>Type</replaceable> ]
- [ implements <replaceable>TypeList</replaceable> ]
- [ <replaceable>PerClause</replaceable> ]
- { <replaceable>Body</replaceable> }
- </literal>
- </blockquote>
- where <replaceable>PerClause</replaceable> defines how the aspect is
- instantiated and associated (<literal>issingleton()</literal> by
- default):
- </para>
-
- <informaltable frame="none">
- <tgroup cols="3" align="left">
- <thead>
- <row>
- <entry align="left">PerClause</entry>
- <entry align="left">Description</entry>
- <entry align="left">Accessor</entry>
- </row>
- </thead>
-
- <tbody valign="top">
- <row>
- <entry>
- [ <literal>issingleton()</literal> ]
- </entry>
- <entry>
- One instance of the aspect is made. This is
- the default.
- </entry>
- <entry>
- <literal>aspectOf()</literal> at all join points
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>perthis(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- <entry>
- An instance is associated with each object that is the
- currently executing object at any join point in
- <replaceable>Pointcut</replaceable>.
- </entry>
- <entry>
- <literal>aspectOf(Object)</literal> at all join points
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>pertarget(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- <entry>
- An instance is associated with each object that is the
- target object at any join point in
- <replaceable>Pointcut</replaceable>.
- </entry>
- <entry>
- <literal>aspectOf(Object)</literal> at all join points
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>percflow(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- <entry>
- The aspect is defined for each entrance to the control flow of
- the join points defined by <replaceable>Pointcut</replaceable>. </entry>
- <entry>
- <literal>aspectOf()</literal> at join points in
- <literal>cflow(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>percflowbelow(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- <entry>
- The aspect is defined for each entrance to the control flow
- below the join points defined by <replaceable>Pointcut</replaceable>.
- </entry>
- <entry>
- <literal>aspectOf()</literal> at join points in
- <literal>cflowbelow(<replaceable>Pointcut</replaceable>)</literal>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect1>
-
-</appendix>
-
diff --git a/docs/progguide/semantics.xml b/docs/progguide/semantics.xml
deleted file mode 100644
index 6bba37818..000000000
--- a/docs/progguide/semantics.xml
+++ /dev/null
@@ -1,3271 +0,0 @@
-<appendix id="semantics" xreflabel="Semantics">
-
- <title>Language Semantics</title>
-
- <sect1 id="semantics-intro">
- <title>Introduction</title>
-
- <para>
- AspectJ extends Java by overlaying a concept of join points onto the
- existing Java semantics and adding a few new program elements to Java:
- </para>
-
- <para>
- A join point is a well-defined point in the execution of a
- program. These include method and constructor calls, field accesses and
- others described below.
- </para>
-
- <para>
- A pointcut picks out join points, and exposes some of the values in the
- execution context of those join points. There are several primitive
- pointcut designators, and others can be named and defined by the
- <literal>pointcut</literal> declaration.
- </para>
-
- <para>
- A piece of advice is code that executes at each join point in a
- pointcut. Advice has access to the values exposed by the
- pointcut. Advice is defined by <literal>before</literal>,
- <literal>after</literal>, and <literal>around</literal> declarations.
- </para>
-
- <para>
- Inter-type declarations form AspectJ's static crosscutting features,
- that is, is code that may change the type structure of a program, by
- adding to or extending interfaces and classes with new fields,
- constructors, or methods. Some inter-type declarations are defined
- through an extension of usual method, field, and constructor
- declarations, and other declarations are made with a new
- <literal>declare</literal> keyword.
- </para>
-
- <para>
- An aspect is a crosscutting type that encapsulates pointcuts, advice,
- and static crosscutting features. By type, we mean Java's notion: a
- modular unit of code, with a well-defined interface, about which it is
- possible to do reasoning at compile time. Aspects are defined by the
- <literal>aspect</literal> declaration.
- </para>
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="semantics-joinPoints">
- <title>Join Points</title>
-
- <para>
- While aspects define types that crosscut, the AspectJ system does not
- allow completely arbitrary crosscutting. Rather, aspects define types
- that cut across principled points in a program's execution. These
- principled points are called join points.
- </para>
-
- <para>
- A join point is a well-defined point in the execution of a
- program. The join points defined by AspectJ are:
- </para>
-
- <variablelist>
- <varlistentry>
- <term>Method call</term>
- <listitem>
- When a method is called, not including super calls of
- non-static methods.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Method execution</term>
- <listitem>
- When the body of code for an actual method executes.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Constructor call</term>
- <listitem>
- When an object is built and that object's initial constructor is
- called (i.e., not for "super" or "this" constructor calls). The
- object being constructed is returned at a constructor call join
- point, so its return type is considered to be the type of the
- object, and the object itself may be accessed with <literal>after
- returning</literal> advice.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Constructor execution</term>
- <listitem>
- When the body of code for an actual constructor executes, after
- its this or super constructor call. The object being constructed
- is the currently executing object, and so may be accessed with
- the <literal>this</literal> pointcut. The constructor execution
- join point for a constructor that calls a super constructor also
- includes any non-static initializers of enclosing class. No
- value is returned from a constructor execution join point, so its
- return type is considered to be void.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Static initializer execution</term>
- <listitem>
- When the static initializer for a class executes. No value is
- returned from a static initializer execution join point, so its
- return type is considered to be void.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Object pre-initialization</term>
- <listitem>
- Before the object initialization code for a particular class runs.
- This encompasses the time between the start of its first called
- constructor and the start of its parent's constructor. Thus, the
- execution of these join points encompass the join points of the
- evaluation of the arguments of <literal>this()</literal> and
- <literal>super()</literal> constructor calls. No value is
- returned from an object pre-initialization join point, so its
- return type is considered to be void.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Object initialization</term>
- <listitem>
- When the object initialization code for a particular class runs.
- This encompasses the time between the return of its parent's
- constructor and the return of its first called constructor. It
- includes all the dynamic initializers and constructors used to
- create the object. The object being constructed is the currently
- executing object, and so may be accessed with the
- <literal>this</literal> pointcut. No value is returned from a
- constructor execution join point, so its return type is
- considered to be void.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Field reference</term>
- <listitem>
- When a non-constant field is referenced. [Note that references
- to constant fields (static final fields bound to a constant
- string object or primitive value) are not join points, since Java
- requires them to be inlined.]
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Field set</term>
- <listitem>
- When a field is assigned to.
- Field set join points are considered to have one argument,
- the value the field is being set to.
- No value is returned from a field set join point, so
- its return type is considered to be void.
- [Note that the initializations of constant fields (static
- final fields where the initializer is a constant string object or
- primitive value) are not join points, since Java requires their
- references to be inlined.]
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Handler execution</term>
- <listitem>
- When an exception handler executes.
- Handler execution join points are considered to have one argument,
- the exception being handled.
- No value is returned from a field set join point, so
- its return type is considered to be void.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Advice execution</term>
- <listitem>
- When the body of code for a piece of advice executes.
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Each join point potentially has three pieces of state associated
- with it: the currently executing object, the target object, and
- an object array of arguments. These are exposed by the three
- state-exposing pointcuts, <literal>this</literal>,
- <literal>target</literal>, and <literal>args</literal>,
- respectively.
- </para>
-
- <para>
- Informally, the currently executing object is the object that a
- <literal>this</literal> expression would pick out at the join
- point. The target object is where control or attention is
- transferred to by the join point. The arguments are those
- values passed for that transfer of control or attention.
- </para>
-
- <informaltable frame="1">
- <tgroup cols="4" align="left">
- <thead valign="top">
- <row>
- <entry><emphasis role="bold">Join Point</emphasis></entry>
- <entry><emphasis role="bold">Current Object</emphasis></entry>
- <entry><emphasis role="bold">Target Object</emphasis></entry>
- <entry><emphasis role="bold">Arguments</emphasis></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>Method Call</entry>
- <entry>executing object*</entry>
- <entry>target object**</entry>
- <entry>method arguments</entry>
- </row>
-
- <row>
- <entry>Method Execution</entry>
- <entry>executing object*</entry>
- <entry>executing object*</entry>
- <entry>method arguments</entry>
- </row>
- <row>
- <entry>Constructor Call</entry>
- <entry>executing object*</entry>
- <entry>None</entry>
- <entry>constructor arguments</entry>
- </row>
-
- <row>
- <entry>Constructor Execution</entry>
- <entry>executing object</entry>
- <entry>executing object</entry>
- <entry>constructor arguments</entry>
- </row>
-
- <row>
- <entry>Static initializer execution</entry>
- <entry>None</entry>
- <entry>None</entry>
- <entry>None</entry>
- </row>
- <row>
- <entry>Object pre-initialization</entry>
- <entry>None</entry>
- <entry>None</entry>
- <entry>constructor arguments</entry>
- </row>
- <row>
- <entry>Object initialization</entry>
- <entry>executing object</entry>
- <entry>executing object</entry>
- <entry>constructor arguments</entry>
- </row>
- <row>
- <entry>Field reference</entry>
- <entry>executing object*</entry>
- <entry>target object**</entry>
- <entry>None</entry>
- </row>
- <row>
- <entry>Field assignment</entry>
- <entry>executing object*</entry>
- <entry>target object**</entry>
- <entry>assigned value</entry>
- </row>
- <row>
- <entry>Handler execution</entry>
- <entry>executing object*</entry>
- <entry>executing object*</entry>
- <entry>caught exception</entry>
- </row>
- <row>
- <entry>Advice execution</entry>
- <entry>executing aspect</entry>
- <entry>executing aspect</entry>
- <entry>advice arguments</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>* There is no executing object in static contexts such as
- static method bodies or static initializers.
- </para>
-
- <para>** There is no target object for join points associated
- with static methods or fields.
- </para>
-
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="semantics-pointcuts">
- <title>Pointcuts</title>
-
- <para>
- A pointcut is a program element that picks out join points and
- exposes data from the execution context of those join points.
- Pointcuts are used primarily by advice. They can be composed with
- boolean operators to build up other pointcuts. The primitive
- pointcuts and combinators provided by the language are:
- </para>
-
- <variablelist>
- <varlistentry>
- <term><literal>call(<replaceable>MethodPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each method call join point whose signature matches
- <replaceable>MethodPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>execution(<replaceable>MethodPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each method execution join point whose signature matches
- <replaceable>MethodPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>get(<replaceable>FieldPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each field reference join point whose signature matches
- <replaceable>FieldPattern</replaceable>.
- [Note that references to constant fields (static final
- fields bound to a constant string object or primitive value) are not
- join points, since Java requires them to be inlined.]
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>set(<replaceable>FieldPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each field set join point whose signature matches
- <replaceable>FieldPattern</replaceable>.
- [Note that the initializations of constant fields (static
- final fields where the initializer is a constant string object or
- primitive value) are not join points, since Java requires their
- references to be inlined.]
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>call(<replaceable>ConstructorPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each constructor call join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>execution(<replaceable>ConstructorPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each constructor execution join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>initialization(<replaceable>ConstructorPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each object initialization join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>preinitialization(<replaceable>ConstructorPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each object pre-initialization join point whose signature matches
- <replaceable>ConstructorPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>staticinitialization(<replaceable>TypePattern</replaceable>)</literal></term>
- <listitem>
- Picks out each static initializer execution join point whose signature matches
- <replaceable>TypePattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>handler(<replaceable>TypePattern</replaceable>)</literal></term>
- <listitem>
- Picks out each exception handler join point whose signature matches
- <replaceable>TypePattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>adviceexecution()</literal></term>
- <listitem>
- Picks out all advice execution join points.
- </listitem>
- </varlistentry>
-
-
- <varlistentry>
- <term><literal>within(<replaceable>TypePattern</replaceable>)</literal></term>
- <listitem>
- Picks out each join point where the executing code is defined
- in a type matched by <replaceable>TypePattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>withincode(<replaceable>MethodPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each join point where the executing code is defined in
- a method whose signature matches
- <replaceable>MethodPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>withincode(<replaceable>ConstructorPattern</replaceable>)</literal></term>
- <listitem>
- Picks out each join point where the executing code is defined
- in a constructor whose signature matches
- <replaceable>ConstructorPattern</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>cflow(<replaceable>Pointcut</replaceable>)</literal></term>
- <listitem>
- Picks out each join point in the control flow of any join point
- <replaceable>P</replaceable> picked out by
- <replaceable>Pointcut</replaceable>, including
- <replaceable>P</replaceable> itself.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>cflowbelow(<replaceable>Pointcut</replaceable>)</literal></term>
- <listitem>
- Picks out each join point in the control flow of any join point
- <replaceable>P</replaceable> picked out by
- <replaceable>Pointcut</replaceable>, but not
- <replaceable>P</replaceable> itself.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>this(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal></term>
- <listitem>
- Picks out each join point where the currently executing object
- (the object bound to <literal>this</literal>) is an instance of
- <replaceable>Type</replaceable>, or of the type of the
- identifier <replaceable>Id</replaceable> (which must be bound in the enclosing
- advice or pointcut definition).
- Will not match any join points from static contexts.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>target(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal></term>
- <listitem>
- Picks out each join point where the target object (the object
- on which a call or field operation is applied to) is an instance of
- <replaceable>Type</replaceable>, or of the type of the identifier
- <replaceable>Id</replaceable> (which must be bound in the enclosing
- advice or pointcut definition).
- Will not match any calls, gets, or sets of static members.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>args(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>, ...)</literal></term>
- <listitem>
- Picks out each join point where the arguments are instances of
- the appropriate type (or type of the identifier if using that form). A
- <literal>null</literal> argument is matched iff the static type of the
- argument (declared parameter type or field type) is the same as, or a subtype of,
- the specified args type.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal><replaceable>PointcutId</replaceable>(<replaceable>TypePattern</replaceable> or <replaceable>Id</replaceable>, ...)</literal></term>
- <listitem>
- Picks out each join point that is picked out by the
- user-defined pointcut designator named by
- <replaceable>PointcutId</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>if(<replaceable>BooleanExpression</replaceable>)</literal></term>
- <listitem>
- Picks out each join point where the boolean expression
- evaluates to <literal>true</literal>. The boolean expression used
- can only access static members, parameters exposed by the enclosing
- pointcut or advice, and <literal>thisJoinPoint</literal> forms. In
- particular, it cannot call non-static methods on the aspect or
- use return values or exceptions exposed by after advice.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>! <replaceable>Pointcut</replaceable></literal></term>
- <listitem>
- Picks out each join point that is not picked out by
- <replaceable>Pointcut</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal><replaceable>Pointcut0</replaceable> <![CDATA[&&]]> <replaceable>Pointcut1</replaceable></literal></term>
- <listitem>
- Picks out each join points that is picked out by both
- <replaceable>Pointcut0</replaceable> and
- <replaceable>Pointcut1</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal><replaceable>Pointcut0</replaceable> || <replaceable>Pointcut1</replaceable></literal></term>
- <listitem>
- Picks out each join point that is picked out by either
- pointcuts. <replaceable>Pointcut0</replaceable> or
- <replaceable>Pointcut1</replaceable>.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>( <replaceable>Pointcut</replaceable> )</literal></term>
- <listitem>
- Picks out each join points picked out by
- <replaceable>Pointcut</replaceable>.
- </listitem>
- </varlistentry>
- </variablelist>
-
- <sect2 id="pointcut-definition" xreflabel="pointcut-definition">
- <title>Pointcut definition</title>
-
- <para>
- Pointcuts are defined and named by the programmer with the
- <literal>pointcut</literal> declaration.
- </para>
-
-<programlisting>
-pointcut publicIntCall(int i):
- call(public * *(int)) <![CDATA[&&]]> args(i);
-</programlisting>
-
- <para>
- A named pointcut may be defined in either a class or aspect, and is
- treated as a member of the class or aspect where it is found. As a
- member, it may have an access modifier such as
- <literal>public</literal> or <literal>private</literal>.
- </para>
-
-<programlisting>
-class C {
- pointcut publicCall(int i):
- call(public * *(int)) <![CDATA[&&]]> args(i);
-}
-
-class D {
- pointcut myPublicCall(int i):
- C.publicCall(i) <![CDATA[&&]]> within(SomeType);
-}
-</programlisting>
-
- <para>
- Pointcuts that are not final may be declared abstract, and defined
- without a body. Abstract pointcuts may only be declared within
- abstract aspects.
- </para>
-
-<programlisting>
-abstract aspect A {
- abstract pointcut publicCall(int i);
-}
-</programlisting>
-
- <para>
- In such a case, an extending aspect may override the abstract
- pointcut.
- </para>
-
-<programlisting>
-aspect B extends A {
- pointcut publicCall(int i): call(public Foo.m(int)) <![CDATA[&&]]> args(i);
-}
-</programlisting>
-
- <para>
- For completeness, a pointcut with a declaration may be declared
- <literal>final</literal>.
- </para>
-
- <para>
- Though named pointcut declarations appear somewhat like method
- declarations, and can be overridden in subaspects, they cannot be
- overloaded. It is an error for two pointcuts to be named with the
- same name in the same class or aspect declaration.
- </para>
-
- <para>
- The scope of a named pointcut is the enclosing class declaration.
- This is different than the scope of other members; the scope of
- other members is the enclosing class <emphasis>body</emphasis>.
- This means that the following code is legal:
- </para>
-
-<programlisting>
-aspect B percflow(publicCall()) {
- pointcut publicCall(): call(public Foo.m(int));
-}
-</programlisting>
- </sect2>
-
- <sect2 id="context-exposure" xreflabel="context-exposure">
- <title>Context exposure</title>
-
- <para>
- Pointcuts have an interface; they expose some parts of the
- execution context of the join points they pick out. For example,
- the PublicIntCall above exposes the first argument from the
- receptions of all public unary integer methods. This context is
- exposed by providing typed formal parameters to named pointcuts and
- advice, like the formal parameters of a Java method. These formal
- parameters are bound by name matching.
- </para>
-
- <para>
- On the right-hand side of advice or pointcut declarations, in
- certain pointcut designators, a Java identifier is allowed in place
- of a type or collection of types. The pointcut designators that
- allow this are <literal>this</literal>, <literal>target</literal>,
- and <literal>args</literal>. In all such cases, using an
- identifier rather than a type does two things. First, it selects
- join points as based on the type of the formal parameter. So the
- pointcut
- </para>
-
-<programlisting>
-pointcut intArg(int i): args(i);
-</programlisting>
-
- <para>
- picks out join points where an <literal>int</literal> (or
- a <literal>byte</literal>, <literal>short</literal>, or
- <literal>char</literal>; anything assignable to an
- <literal>int</literal>) is being passed as an argument.
- Second, though, it makes the value of that argument
- available to the enclosing advice or pointcut.
- </para>
-
- <para>
- Values can be exposed from named pointcuts as well, so
- </para>
-
-<programlisting>
-pointcut publicCall(int x): call(public *.*(int)) <![CDATA[&&]]> intArg(x);
-pointcut intArg(int i): args(i);
-</programlisting>
-
- <para>
- is a legal way to pick out all calls to public methods accepting an
- int argument, and exposing that argument.
- </para>
-
- <para>
- There is one special case for this kind of exposure. Exposing an
- argument of type Object will also match primitive typed arguments,
- and expose a "boxed" version of the primitive. So,
- </para>
-
-<programlisting>
-pointcut publicCall(): call(public *.*(..)) <![CDATA[&&]]> args(Object);
-</programlisting>
-
- <para>
- will pick out all unary methods that take, as their only argument,
- subtypes of Object (i.e., not primitive types like
- <literal>int</literal>), but
- </para>
-
-<programlisting>
-pointcut publicCall(Object o): call(public *.*(..)) <![CDATA[&&]]> args(o);
-</programlisting>
-
- <para>
- will pick out all unary methods that take any argument: And if the
- argument was an <literal>int</literal>, then the value passed to
- advice will be of type <literal>java.lang.Integer</literal>.
- </para>
-
- <para>
- The "boxing" of the primitive value is based on the
- <emphasis>original</emphasis> primitive type. So in the
- following program
- </para>
-
-<programlisting>
-public class InstanceOf {
-
- public static void main(String[] args) {
- doInt(5);
- }
-
- static void doInt(int i) { }
-}
-
-aspect IntToLong {
- pointcut el(long l) :
- execution(* doInt(..)) <![CDATA[&&]]> args(l);
-
- before(Object o) : el(o) {
- System.out.println(o.getClass());
- }
-}
-</programlisting>
-
- <para>
- The pointcut will match and expose the integer argument,
- but it will expose it as an <literal>Integer</literal>,
- not a <literal>Long</literal>.
- </para>
-
- </sect2>
-
- <sect2 id="primitive-pointcuts" xreflabel="primitive-pointcuts">
- <title>Primitive pointcuts</title>
-
- <sect3>
- <title>Method-related pointcuts</title>
-
- <para>AspectJ provides two primitive pointcut designators designed to
- capture method call and execution join points. </para>
-
- <itemizedlist>
- <listitem><literal>call(<replaceable>MethodPattern</replaceable>)</literal></listitem>
- <listitem><literal>execution(<replaceable>MethodPattern</replaceable>)</literal></listitem>
- </itemizedlist>
- </sect3>
-
- <sect3>
- <title>Field-related pointcuts</title>
-
- <para>
- AspectJ provides two primitive pointcut designators designed to
- capture field reference and set join points:
- </para>
-
- <itemizedlist>
- <listitem><literal>get(<replaceable>FieldPattern</replaceable>)</literal></listitem>
- <listitem><literal>set(<replaceable>FieldPattern</replaceable>)</literal></listitem>
- </itemizedlist>
-
- <para>
- All set join points are treated as having one argument, the value the
- field is being set to, so at a set join point, that value can be
- accessed with an <literal>args</literal> pointcut. So an aspect
- guarding a static integer variable x declared in type T might be written as
- </para>
-
-<programlisting><![CDATA[
-aspect GuardedX {
- static final int MAX_CHANGE = 100;
- before(int newval): set(static int T.x) && args(newval) {
- if (Math.abs(newval - T.x) > MAX_CHANGE)
- throw new RuntimeException();
- }
-}
-]]></programlisting>
-
- </sect3>
-
- <sect3>
- <title>Object creation-related pointcuts</title>
-
- <para>
- AspectJ provides primitive pointcut designators designed to
- capture the initializer execution join points of objects.
- </para>
-
- <itemizedlist>
- <listitem><literal>call(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- <listitem><literal>execution(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- <listitem><literal>initialization(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- <listitem><literal>preinitialization(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- </itemizedlist>
-
- </sect3>
-
- <sect3>
- <title>Class initialization-related pointcuts</title>
-
- <para>
- AspectJ provides one primitive pointcut designator to pick out
- static initializer execution join points.
- </para>
-
- <itemizedlist>
- <listitem><literal>staticinitialization(<replaceable>TypePattern</replaceable>)</literal></listitem>
- </itemizedlist>
-
- </sect3>
-
- <sect3>
- <title>Exception handler execution-related pointcuts</title>
-
- <para>
- AspectJ provides one primitive pointcut designator to capture
- execution of exception handlers:
- </para>
-
- <itemizedlist>
- <listitem><literal>handler(<replaceable>TypePattern</replaceable>)</literal></listitem>
- </itemizedlist>
-
- <para>
- All handler join points are treated as having one argument, the value
- of the exception being handled. That value can be accessed with an
- <literal>args</literal> pointcut. So an aspect used to put
- <literal>FooException</literal> objects into some normal form before
- they are handled could be written as
- </para>
-
-<programlisting>
-aspect NormalizeFooException {
- before(FooException e): handler(FooException) <![CDATA[&&]]> args(e) {
- e.normalize();
- }
-}
-</programlisting>
-
- </sect3>
-
- <sect3>
- <title>Advice execution-related pointcuts</title>
-
- <para>
- AspectJ provides one primitive pointcut designator to capture
- execution of advice
- </para>
-
- <itemizedlist>
- <listitem><literal>adviceexecution()</literal></listitem>
- </itemizedlist>
-
- <para>
- This can be used, for example, to filter out any join point in the
- control flow of advice from a particular aspect.
- </para>
-
-<programlisting>
-aspect TraceStuff {
- pointcut myAdvice(): adviceexecution() <![CDATA[&&]]> within(TraceStuff);
-
- before(): call(* *(..)) <![CDATA[&&]]> !cflow(myAdvice) {
- // do something
- }
-}
-</programlisting>
-
- </sect3>
-
- <sect3>
- <title>State-based pointcuts</title>
-
- <para>
- Many concerns cut across the dynamic times when an object of a
- particular type is executing, being operated on, or being passed
- around. AspectJ provides primitive pointcuts that capture join
- points at these times. These pointcuts use the dynamic types of
- their objects to pick out join points. They may also be used to
- expose the objects used for discrimination.
- </para>
-
- <itemizedlist>
- <listitem><literal>this(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal></listitem>
- <listitem><literal>target(<replaceable>Type</replaceable> or <replaceable>Id</replaceable>)</literal></listitem>
- </itemizedlist>
-
- <para>
- The <literal>this</literal> pointcut picks out each join point where
- the currently executing object (the object bound to
- <literal>this</literal>) is an instance of a particular type. The
- <literal>target</literal> pointcut picks out each join point where
- the target object (the object on which a method is called or a field
- is accessed) is an instance of a particular type. Note that
- <literal>target</literal> should be understood to be the object the
- current join point is transfering control to. This means that the
- target object is the same as the current object at a method execution
- join point, for example, but may be different at a method call join
- point.
- </para>
-
- <itemizedlist>
- <listitem><literal>args(<replaceable>Type</replaceable> or <replaceable>Id</replaceable> or "..", ...)</literal></listitem>
- </itemizedlist>
-
- <para>
- The args pointcut picks out each join point where the arguments are
- instances of some types. Each element in the comma-separated list is
- one of four things. If it is a type name, then the argument in that
- position must be an instance of that type. If it is an identifier,
- then that identifier must be bound in the enclosing advice or
- pointcut declaration, and so the argument in that position must be an
- instance of the type of the identifier (or of any type if the
- identifier is typed to Object). If it is the "*" wildcard, then any
- argument will match, and if it is the special wildcard "..", then any
- number of arguments will match, just like in signature patterns. So the
- pointcut
- </para>
-
-<programlisting>
-args(int, .., String)
-</programlisting>
-
- <para>
- will pick out all join points where the first argument is an
- <literal>int</literal> and the last is a <literal>String</literal>.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Control flow-based pointcuts</title>
-
- <para>
- Some concerns cut across the control flow of the program. The
- <literal>cflow</literal> and <literal>cflowbelow</literal> primitive
- pointcut designators capture join points based on control flow.
- </para>
-
- <itemizedlist>
- <listitem><literal>cflow(<replaceable>Pointcut</replaceable>)</literal></listitem>
- <listitem><literal>cflowbelow(<replaceable>Pointcut</replaceable>)</literal></listitem>
- </itemizedlist>
-
- <para>
- The <literal>cflow</literal> pointcut picks out all join points that
- occur between entry and exit of each join point
- <replaceable>P</replaceable> picked out by
- <replaceable>Pointcut</replaceable>, including
- <replaceable>P</replaceable> itself. Hence, it picks out the join
- points <emphasis>in</emphasis> the control flow of the join points
- picked out by <replaceable>Pointcut</replaceable>.
- </para>
-
- <para>
- The <literal>cflowbelow</literal> pointcut picks out all join points
- that occur between entry and exit of each join point
- <replaceable>P</replaceable> picked out by
- <replaceable>Pointcut</replaceable>, but not including
- <replaceable>P</replaceable> itself. Hence, it picks out the join
- points <emphasis>below</emphasis> the control flow of the join points
- picked out by <replaceable>Pointcut</replaceable>.
- </para>
-
- <sect4>
- <title>Context exposure from control flows</title>
-
- <para>
- The <literal>cflow</literal> and
- <literal>cflowbelow</literal> pointcuts may expose context
- state through enclosed <literal>this</literal>,
- <literal>target</literal>, and <literal>args</literal>
- pointcuts.
- </para>
-
- <para>
- Anytime such state is accessed, it is accessed through the
- <emphasis>most recent</emphasis> control flow that
- matched. So the "current arg" that would be printed by
- the following program is zero, even though it is in many
- control flows.
- </para>
-
-<programlisting>
-class Test {
- public static void main(String[] args) {
- fact(5);
- }
- static int fact(int x) {
- if (x == 0) {
- System.err.println("bottoming out");
- return 1;
- }
- else return x * fact(x - 1);
- }
-}
-
-aspect A {
- pointcut entry(int i): call(int fact(int)) <![CDATA[&&]]> args(i);
- pointcut writing(): call(void println(String)) <![CDATA[&&]]> ! within(A);
-
- before(int i): writing() <![CDATA[&&]]> cflow(entry(i)) {
- System.err.println("Current arg is " + i);
- }
-}
-</programlisting>
-
- <para>
- It is an error to expose such state through
- <emphasis>negated</emphasis> control flow pointcuts, such
- as within <literal>!
- cflowbelow(<replaceable>P</replaceable>)</literal>.
- </para>
-
- </sect4>
- </sect3>
-
- <sect3>
- <title>Program text-based pointcuts</title>
-
- <para>
- While many concerns cut across the runtime structure of the program,
- some must deal with the lexical structure. AspectJ allows aspects to
- pick out join points based on where their associated code is defined.
- </para>
-
- <itemizedlist>
- <listitem><literal>within(<replaceable>TypePattern</replaceable>)</literal></listitem>
- <listitem><literal>withincode(<replaceable>MethodPattern</replaceable>)</literal></listitem>
- <listitem><literal>withincode(<replaceable>ConstructorPattern</replaceable>)</literal></listitem>
- </itemizedlist>
-
- <para>
- The <literal>within</literal> pointcut picks out each join point
- where the code executing is defined in the declaration of one of the
- types in <replaceable>TypePattern</replaceable>. This includes the
- class initialization, object initialization, and method and
- constructor execution join points for the type, as well as any join
- points associated with the statements and expressions of the type.
- It also includes any join points that are associated with code in a
- type's nested types, and that type's default constructor, if there is
- one.
- </para>
-
- <para>
- The <literal>withincode</literal> pointcuts picks out each join point
- where the code executing is defined in the declaration of a
- particular method or constructor. This includes the method or
- constructor execution join point as well as any join points
- associated with the statements and expressions of the method or
- constructor. It also includes any join points that are associated
- with code in a method or constructor's local or anonymous types.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Expression-based pointcuts</title>
-
- <itemizedlist>
- <listitem><literal>if(<replaceable>BooleanExpression</replaceable>)</literal></listitem>
- </itemizedlist>
-
- <para>
- The if pointcut picks out join points based on a dynamic property.
- its syntax takes an expression, which must evaluate to a boolean
- true or false. Within this expression, the
- <literal>thisJoinPoint</literal> object is available. So one
- (extremely inefficient) way of picking out all call join points would
- be to use the pointcut
- </para>
-
-<programlisting>
-if(thisJoinPoint.getKind().equals("call"))
-</programlisting>
-
- <para>
- Note that the order of evaluation for pointcut expression
- components at a join point is undefined. Writing <literal>if</literal>
- pointcuts that have side-effects is considered bad style and may also
- lead to potentially confusing or even changing behavior with regard
- to when or if the test code will run.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="signatures" xreflabel="signatures">
- <title>Signatures</title>
-
- <para>
- One very important property of a join point is its signature, which is
- used by many of AspectJ's pointcut designators to select particular
- join points.
- </para>
-
- <sect3>
- <title>Methods</title>
-
- <para>
- Join points associated with methods typically have method signatures,
- consisting of a method name, parameter types, return type, the types of
- the declared (checked) exceptions, and some type that the method could
- be called on (below called the "qualifying type").
- </para>
-
- <para>
- At a method call join point, the signature is a method signature whose
- qualifying type is the static type used to <emphasis>access</emphasis>
- the method. This means that the signature for the join point created
- from the call <literal>((Integer)i).toString()</literal> is different
- than that for the call <literal>((Object)i).toString()</literal>, even
- if <literal>i</literal> is the same variable.
- </para>
-
- <para>
- At a method execution join point, the signature is a method signature
- whose qualifying type is the declaring type of the method.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Fields</title>
-
- <para>
- Join points associated with fields typically have field signatures,
- consisting of a field name and a field type. A field reference join
- point has such a signature, and no parameters. A field set join point
- has such a signature, but has a has a single parameter whose type is
- the same as the field type.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Constructors</title>
-
- <para>
- Join points associated with constructors typically have constructor
- signatures, consisting of a parameter types, the types of the declared
- (checked) exceptions, and the declaring type.
- </para>
-
- <para>
- At a constructor call join point, the signature is the constructor
- signature of the called constructor. At a constructor execution join
- point, the signature is the constructor signature of the currently
- executing constructor.
- </para>
-
- <para>
- At object initialization and pre-initialization join points, the
- signature is the constructor signature for the constructor that started
- this initialization: the first constructor entered during this type's
- initialization of this object.
- </para>
- </sect3>
-
- <sect3>
- <title>Others</title>
-
- <para>
- At a handler execution join point, the signature is composed of the
- exception type that the handler handles.
- </para>
-
- <para>
- At an advice execution join point, the signature is composed of the
- aspect type, the parameter types of the advice, the return type (void
- for all but around advice) and the types of the declared (checked)
- exceptions.
- </para>
- </sect3>
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="matching" xreflabel="matching">
- <title>Matching</title>
-
- <para>
- The <literal>withincode</literal>, <literal>call</literal>,
- <literal>execution</literal>, <literal>get</literal>, and
- <literal>set</literal> primitive pointcut designators all use signature
- patterns to determine the join points they describe. A signature
- pattern is an abstract description of one or more join-point
- signatures. Signature patterns are intended to match very closely the
- same kind of things one would write when declaring individual members
- and constructors.
- </para>
-
- <para>
- Method declarations in Java include method names, method parameters,
- return types, modifiers like static or private, and throws clauses,
- while constructor declarations omit the return type and replace the
- method name with the class name. The start of a particular method
- declaration, in class <literal>Test</literal>, for example, might be
- </para>
-
-
-<programlisting>
-class C {
- public final void foo() throws ArrayOutOfBoundsException { ... }
-}
-</programlisting>
-
- <para>
- In AspectJ, method signature patterns have all these, but most elements
- can be replaced by wildcards. So
- </para>
-
-
-<programlisting>
-call(public final void C.foo() throws ArrayOutOfBoundsException)
-</programlisting>
-
- <para>
- picks out call join points to that method, and the pointcut
- </para>
-
-<programlisting>
-call(public final void *.*() throws ArrayOutOfBoundsException)
-</programlisting>
-
-
- <para>
- picks out all call join points to methods, regardless of their name
- name or which class they are defined on, so long as they take no
- arguments, return no value, are both <literal>public</literal> and
- <literal>final</literal>, and are declared to throw
- <literal>ArrayOutOfBounds</literal> exceptions.
- </para>
-
- <para>
- The defining type name, if not present, defaults to *, so another way
- of writing that pointcut would be
- </para>
-
-<programlisting>
-call(public final void *() throws ArrayOutOfBoundsException)
-</programlisting>
-
- <para>
- The wildcard <literal>..</literal> indicates zero or more
- parameters, so
- </para>
-
-<programlisting>
-execution(void m(..))
-</programlisting>
-
- <para>
- picks out execution join points for void methods named
- <literal>m</literal>, of any number of arguments, while
- </para>
-
-<programlisting>
-execution(void m(.., int))
-</programlisting>
-
- <para>
- picks out execution join points for void methods named
- <literal>m</literal> whose last parameter is of type
- <literal>int</literal>.
- </para>
-
- <para>
- The modifiers also form part of the signature pattern. If an AspectJ
- signature pattern should match methods without a particular modifier,
- such as all non-public methods, the appropriate modifier should be
- negated with the <literal>!</literal> operator. So,
- </para>
-
-<programlisting>
-withincode(!public void foo())
-</programlisting>
-
- <para>
- picks out all join points associated with code in null non-public
- void methods named <literal>foo</literal>, while
- </para>
-
-<programlisting>
-withincode(void foo())
-</programlisting>
-
- <para>
- picks out all join points associated with code in null void methods
- named <literal>foo</literal>, regardless of access modifier.
- </para>
-
- <para>
- Method names may contain the * wildcard, indicating any number of
- characters in the method name. So
- </para>
-
-<programlisting>
-call(int *())
-</programlisting>
-
- <para>
- picks out all call join points to <literal>int</literal> methods
- regardless of name, but
- </para>
-
-<programlisting>
-call(int get*())
-</programlisting>
-
- <para>
- picks out all call join points to <literal>int</literal> methods
- where the method name starts with the characters "get".
- </para>
-
- <para>
- AspectJ uses the <literal>new</literal> keyword for constructor
- signature patterns rather than using a particular class name. So the
- execution join points of private null constructor of a class C
- defined to throw an ArithmeticException can be picked out with
- </para>
-
-<programlisting>
-execution(private C.new() throws ArithmeticException)
-</programlisting>
-
- <sect3>
- <title>Matching based on the declaring type</title>
-
- <para>
- The signature-matching pointcuts all specify a declaring type,
- but the meaning varies slightly for each join point signature,
- in line with Java semantics.
- </para>
-
- <para>
- When matching for pointcuts <literal>withincode</literal>,
- <literal>get</literal>, and <literal>set</literal>, the declaring
- type is the class that contains the declaration.
- </para>
-
- <para>
- When matching method-call join points, the
- declaring type is the static type used to access the method.
- A common mistake is to specify a declaring type for the
- <literal>call</literal> pointcut that is a subtype of the
- originally-declaring type. For example, given the class
- </para>
-
-<programlisting>
-class Service implements Runnable {
- public void run() { ... }
-}
-</programlisting>
-
- <para>
- the following pointcut
- </para>
-
-<programlisting>
-call(void Service.run())
-</programlisting>
-
- <para>
- would fail to pick out the join point for the code
- </para>
-
-<programlisting>
-((Runnable) new Service()).run();
-</programlisting>
-
- <para>
- Specifying the originally-declaring type is correct, but would
- pick out any such call (here, calls to the <literal>run()</literal>
- method of any Runnable).
- In this situation, consider instead picking out the target type:
- </para>
-
-<programlisting>
-call(void run()) &amp;&amp; target(Service)
-</programlisting>
-
- <para>
- When matching method-execution join points,
- if the execution pointcut method signature specifies a declaring type,
- the pointcut will only match methods declared in that type, or methods
- that override methods declared in or inherited by that type.
- So the pointcut
- </para>
-
-<programlisting>
-execution(public void Middle.*())
-</programlisting>
-
- <para>
- picks out all method executions for public methods returning void
- and having no arguments that are either declared in, or inherited by,
- Middle, even if those methods are overridden in a subclass of Middle.
- So the pointcut would pick out the method-execution join point
- for Sub.m() in this code:
- </para>
-
-<programlisting>
-class Super {
- protected void m() { ... }
-}
-class Middle extends Super {
-}
-class Sub extends Middle {
- public void m() { ... }
-}
-</programlisting>
-
- </sect3>
-
- <sect3>
- <title>Matching based on the throws clause</title>
-
- <para>
- Type patterns may be used to pick out methods and constructors
- based on their throws clauses. This allows the following two
- kinds of extremely wildcarded pointcuts:
- </para>
-
-<programlisting>
-pointcut throwsMathlike():
- // each call to a method with a throws clause containing at least
- // one exception exception with "Math" in its name.
- call(* *(..) throws *..*Math*);
-
-pointcut doesNotThrowMathlike():
- // each call to a method with a throws clause containing no
- // exceptions with "Math" in its name.
- call(* *(..) throws !*..*Math*);
-</programlisting>
-
- <para>
- A <replaceable>ThrowsClausePattern</replaceable> is a comma-separated list of
- <replaceable>ThrowsClausePatternItem</replaceable>s, where
-
- <variablelist>
- <varlistentry>
- <term><replaceable>ThrowsClausePatternItem</replaceable> :</term>
- <listitem>
- <literal>[ ! ]
- <replaceable>TypeNamePattern</replaceable></literal>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- <para>
- A <replaceable>ThrowsClausePattern</replaceable> matches the
- throws clause of any code member signature. To match, each
- <literal>ThrowsClausePatternItem</literal> must
- match the throws clause of the member in question. If any item
- doesn't match, then the whole pattern doesn't match.
- </para>
-
- <para>
- If a ThrowsClausePatternItem begins with "!", then it matches a
- particular throws clause if and only if <emphasis>none</emphasis>
- of the types named in the throws clause is matched by the
- <literal>TypeNamePattern</literal>.
- </para>
-
- <para>
- If a <replaceable>ThrowsClausePatternItem</replaceable> does not
- begin with "!", then it matches a throws clause if and only if
- <emphasis>any</emphasis> of the types named in the throws clause
- is matched by the <emphasis>TypeNamePattern</emphasis>.
- </para>
-
- <para>
- The rule for "!" matching has one potentially surprising
- property, in that these two pointcuts
-
- <itemizedlist>
- <listitem> call(* *(..) throws !IOException) </listitem>
- <listitem> call(* *(..) throws (!IOException)) </listitem>
- </itemizedlist>
-
- will match differently on calls to
-
- <blockquote>
- <literal>
- void m() throws RuntimeException, IOException {}
- </literal>
- </blockquote>
- </para>
-
- <para>
- [1] will NOT match the method m(), because method m's throws
- clause declares that it throws IOException. [2] WILL match the
- method m(), because method m's throws clause declares the it
- throws some exception which does not match IOException,
- i.e. RuntimeException.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="type-patterns" xreflabel="type-patterns">
- <title>Type patterns</title>
-
- <para>
- Type patterns are a way to pick out collections of types and use them
- in places where you would otherwise use only one type. The rules for
- using type patterns are simple.
- </para>
-
- <sect3>
- <title>Exact type pattern</title>
-
- <para>
- First, all type names are also type patterns. So
- <literal>Object</literal>, <literal>java.util.HashMap</literal>,
- <literal>Map.Entry</literal>, <literal>int</literal> are all type
- patterns.
- </para>
-
- <para>
- If a type pattern is an exact type - if it doesn't
- include a wildcard - then the matching works just
- like normal type lookup in Java: </para>
-
- <itemizedlist>
- <listitem>Patterns that have the same names as
- primitive types (like <literal>int</literal>) match
- those primitive types.</listitem>
-
- <listitem>Patterns that are qualified by package names
- (like <literal>java.util.HashMap</literal>) match types
- in other packages.
- </listitem>
-
- <listitem>Patterns that are not qualified (like
- <literal>HashMap</literal>) match types that are
- resolved by Java's normal scope rules. So, for
- example, <literal>HashMap</literal> might match a
- package-level type in the same package or a type that
- have been imported with java's
- <literal>import</literal> form. But it would not match
- <literal>java.util.HashMap</literal> unless the aspect
- were in <literal>java.util</literal> or the type had
- been imported.
- </listitem>
- </itemizedlist>
-
- <para>
- So exact type patterns match based on usual Java scope
- rules.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Type name patterns</title>
-
- <para>
- There is a special type name, *, which is also a type pattern. * picks out all
- types, including primitive types. So
- </para>
-
-<programlisting>
-call(void foo(*))
-</programlisting>
-
- <para>
- picks out all call join points to void methods named foo, taking one
- argument of any type.
- </para>
-
- <para>
- Type names that contain the two wildcards "*" and
- "<literal>..</literal>" are also type patterns. The * wildcard matches
- zero or more characters characters except for ".", so it can be used
- when types have a certain naming convention. So
- </para>
-
-<programlisting>
-handler(java.util.*Map)
-</programlisting>
-
- <para>
- picks out the types java.util.Map and java.util.java.util.HashMap,
- among others, and
- </para>
-
-<programlisting>
-handler(java.util.*)
-</programlisting>
-
- <para>
- picks out all types that start with "<literal>java.util.</literal>" and
- don't have any more "."s, that is, the types in the
- <literal>java.util</literal> package, but not inner types
- (such as java.util.Map.Entry).
- </para>
-
- <para>
- The "<literal>..</literal>" wildcard matches any sequence of
- characters that start and end with a ".", so it can be used
- to pick out all types in any subpackage, or all inner types. So
- </para>
-
-<programlisting>
-within(com.xerox..*)
-</programlisting>
-
- <para>
- picks out all join points where the code is in any
- declaration of a type whose name begins with "<literal>com.xerox.</literal>".
- </para>
-
- <para>
- Type patterns with wildcards do not depend on Java's
- usual scope rules - they match against all types
- available to the weaver, not just those that are
- imported into an Aspect's declaring file.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Subtype patterns</title>
-
- <para>
- It is possible to pick out all subtypes of a type (or a collection of
- types) with the "+" wildcard. The "+" wildcard follows immediately a
- type name pattern. So, while
- </para>
-
-<programlisting>
-call(Foo.new())
-</programlisting>
-
- <para>
- picks out all constructor call join points where an instance of exactly
- type Foo is constructed,
- </para>
-
-<programlisting>
-call(Foo+.new())
-</programlisting>
-
- <para>
- picks out all constructor call join points where an instance of any
- subtype of Foo (including Foo itself) is constructed, and the unlikely
- </para>
-
-<programlisting>
-call(*Handler+.new())
-</programlisting>
-
- <para>
- picks out all constructor call join points where an instance of any
- subtype of any type whose name ends in "Handler" is constructed.
- </para>
-
- </sect3>
-
- <sect3>
- <title>Array type patterns</title>
-
- <para>
- A type name pattern or subtype pattern can be followed by one or more
- sets of square brackets to make array type patterns. So
- <literal>Object[]</literal> is an array type pattern, and so is
- <literal>com.xerox..*[][]</literal>, and so is
- <literal>Object+[]</literal>.
- </para>
- </sect3>
-
- <sect3>
- <title>Type patterns</title>
-
- <para>
- Type patterns are built up out of type name patterns, subtype patterns,
- and array type patterns, and constructed with boolean operators
- <literal><![CDATA[&&]]></literal>, <literal>||</literal>, and
- <literal>!</literal>. So
- </para>
-
-<programlisting>
-staticinitialization(Foo || Bar)
-</programlisting>
-
- <para>
- picks out the static initializer execution join points of either Foo or Bar,
- and
- </para>
-
-<programlisting>
-call((Foo+ <![CDATA[&&]]> ! Foo).new(..))
-</programlisting>
-
- <para>
- picks out the constructor call join points when a subtype of Foo, but
- not Foo itself, is constructed.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="pattern-summary" xreflabel="pattern-summary">
- <title>Pattern Summary</title>
-
- <para>
- Here is a summary of the pattern syntax used in AspectJ:
- </para>
-
-<programlisting>
-MethodPattern =
- [ModifiersPattern] TypePattern
- [TypePattern . ] IdPattern (TypePattern | ".." , ... )
- [ throws ThrowsPattern ]
-ConstructorPattern =
- [ModifiersPattern ]
- [TypePattern . ] new (TypePattern | ".." , ...)
- [ throws ThrowsPattern ]
-FieldPattern =
- [ModifiersPattern] TypePattern [TypePattern . ] IdPattern
-ThrowsPattern =
- [ ! ] TypePattern , ...
-TypePattern =
- IdPattern [ + ] [ [] ... ]
- | ! TypePattern
- | TypePattern <![CDATA[&&]]> TypePattern
- | TypePattern || TypePattern
- | ( TypePattern )
-IdPattern =
- Sequence of characters, possibly with special * and .. wildcards
-ModifiersPattern =
- [ ! ] JavaModifier ...
-</programlisting>
-
- </sect2>
-
- </sect1>
-
-<!-- ============================== -->
-
- <sect1 id="semantics-advice">
- <title>Advice</title>
-
- <para>
- Each piece of advice is of the form
-
- <blockquote>
- <literal>[ strictfp ] <replaceable>AdviceSpec</replaceable> [
- throws <replaceable>TypeList</replaceable> ] :
- <replaceable>Pointcut</replaceable> {
- <replaceable>Body</replaceable> } </literal>
- </blockquote>
-
- where <replaceable>AdviceSpec</replaceable> is one of
- </para>
-
- <itemizedlist>
- <listitem>
- <literal>before( <replaceable>Formals</replaceable> ) </literal>
- </listitem>
- <listitem>
- <literal>after( <replaceable>Formals</replaceable> ) returning
- [ ( <replaceable>Formal</replaceable> ) ] </literal>
- </listitem>
- <listitem>
- <literal>after( <replaceable>Formals</replaceable> ) throwing [
- ( <replaceable>Formal</replaceable> ) ] </literal>
- </listitem>
- <listitem>
- <literal>after( <replaceable>Formals</replaceable> ) </literal>
- </listitem>
- <listitem>
- <literal><replaceable>Type</replaceable>
- around( <replaceable>Formals</replaceable> )</literal>
- </listitem>
- </itemizedlist>
- <para>
- and where <replaceable>Formal</replaceable> refers to a
- variable binding like those used for method parameters,
- of the form
- <literal><replaceable>Type</replaceable></literal>
- <literal><replaceable>Variable-Name</replaceable></literal>,
- and <replaceable>Formals</replaceable> refers to a comma-delimited
- list of <replaceable>Formal</replaceable>.
- </para>
-
-
- <para>
- Advice defines crosscutting behavior. It is defined in terms of
- pointcuts. The code of a piece of advice runs at every join point
- picked out by its pointcut. Exactly how the code runs depends on the
- kind of advice.
- </para>
-
- <para>
- AspectJ supports three kinds of advice. The kind of advice determines how
- it interacts with the join points it is defined over. Thus AspectJ
- divides advice into that which runs before its join points, that which
- runs after its join points, and that which runs in place of (or "around")
- its join points.
- </para>
-
- <para>
- While before advice is relatively unproblematic, there can be three
- interpretations of after advice: After the execution of a join point
- completes normally, after it throws an exception, or after it does either
- one. AspectJ allows after advice for any of these situations.
- </para>
-
-<programlisting>
-aspect A {
- pointcut publicCall(): call(public Object *(..));
- after() returning (Object o): publicCall() {
- System.out.println("Returned normally with " + o);
- }
- after() throwing (Exception e): publicCall() {
- System.out.println("Threw an exception: " + e);
- }
- after(): publicCall(){
- System.out.println("Returned or threw an Exception");
- }
-}
-</programlisting>
-
- <para>
- After returning advice may not care about its returned object, in which
- case it may be written
- </para>
-
-<programlisting>
-after() returning: call(public Object *(..)) {
- System.out.println("Returned normally");
-}
-</programlisting>
-
- <para>
- If after returning does expose its returned object, then the
- type of the parameter is considered to be an
- <literal>instanceof</literal>-like constraint on the advice: it
- will run only when the return value is of the appropriate type.
- </para>
-
- <para>
- A value is of the appropriate type if it would be assignable to
- a variable of that type, in the Java sense. That is, a
- <literal>byte</literal> value is assignable to a
- <literal>short</literal> parameter but not vice-versa, an
- <literal>int</literal> is assignable to a
- <literal>float</literal> parameter, <literal>boolean</literal>
- values are only assignable to <literal>boolean</literal>
- parameters, and reference types work by instanceof.
- </para>
-
- <para>
- There are two special cases: If the exposed value is typed to
- <literal>Object</literal>, then the advice is not constrained by
- that type: the actual return value is converted to an object
- type for the body of the advice: <literal>int</literal> values
- are represented as <literal>java.lang.Integer</literal> objects,
- etc, and no value (from void methods, for example) is
- represented as <literal>null</literal>.
- </para>
-
- <para>
- Secondly, the <literal>null</literal> value is assignable to a
- parameter <literal>T</literal> if the join point
- <emphasis>could</emphasis> return something of type
- <literal>T</literal>.
- </para>
-
- <para>
- Around advice runs in place of the join point it operates over, rather
- than before or after it. Because around is allowed to return a value, it
- must be declared with a return type, like a method.
- </para>
-
- <para>
- Thus, a simple use of around advice is to make a particular method
- constant:
- </para>
-
-<programlisting>
-aspect A {
- int around(): call(int C.foo()) {
- return 3;
- }
-}
-</programlisting>
-
- <para>
- Within the body of around advice, though, the computation of the original
- join point can be executed with the special syntax
- </para>
-
-<programlisting>
-proceed( ... )
-</programlisting>
-
- <para>
- The proceed form takes as arguments the context exposed by the around's
- pointcut, and returns whatever the around is declared to return. So the
- following around advice will double the second argument to
- <literal>foo</literal> whenever it is called, and then halve its result:
- </para>
-
-
-<programlisting>
-aspect A {
- int around(int i): call(int C.foo(Object, int)) <![CDATA[&&]]> args(i) {
- int newi = proceed(i*2)
- return newi/2;
- }
-}
-</programlisting>
-
- <para>
- If the return value of around advice is typed to
- <literal>Object</literal>, then the result of proceed is converted to an
- object representation, even if it is originally a primitive value. And
- when the advice returns an Object value, that value is converted back to
- whatever representation it was originally. So another way to write the
- doubling and halving advice is:
- </para>
-
-<programlisting>
-aspect A {
- Object around(int i): call(int C.foo(Object, int)) <![CDATA[&&]]> args(i) {
- Integer newi = (Integer) proceed(i*2)
- return new Integer(newi.intValue() / 2);
- }
-}
-</programlisting>
-
- <para>
- Any occurence of <literal>proceed(..)</literal> within the body of around
- advice is treated as the special proceed form (even if the
- aspect defines a method named <literal>proceed</literal>), unless a
- target other than the aspect instance is specified as the recipient of
- the call.
- For example, in the following program the first
- call to proceed will be treated as a method call to
- the <literal>ICanProceed</literal> instance, whereas the second call to
- proceed is treated as the special proceed form.
- </para>
-
-<programlisting>
-aspect A {
- Object around(ICanProceed canProceed) : execution(* *(..)) <![CDATA[&&]]> this(canProceed) {
- canProceed.proceed(); // a method call
- return proceed(canProceed); // the special proceed form
- }
-
- private Object proceed(ICanProceed canProceed) {
- // this method cannot be called from inside the body of around advice in
- // the aspect
- }
-}
-</programlisting>
-
- <para>
- In all kinds of advice, the parameters of the advice behave exactly like
- method parameters. In particular, assigning to any parameter affects
- only the value of the parameter, not the value that it came from. This
- means that
- </para>
-
-<programlisting>
-aspect A {
- after() returning (int i): call(int C.foo()) {
- i = i * 2;
- }
-}
-</programlisting>
-
- <para>
- will <emphasis>not</emphasis> double the returned value of the advice.
- Rather, it will double the local parameter. Changing the values of
- parameters or return values of join points can be done by using around
- advice.
- </para>
- <para>
- With <literal>proceed(..)</literal> it is possible to change the values
- used by less-precedent advice and the underlying join point by supplying
- different values for the variables. For example, this aspect replaces
- the string bound to <literal>s</literal> in the named pointcut
- <literal>privateData</literal>:
- </para>
-
-<programlisting>
-aspect A {
- Object around(String s): MyPointcuts.privateData(s) {
- return proceed("private data");
- }
-}
-</programlisting>
- <para>
- If you replace an argument to <literal>proceed(..)</literal>, you can cause
- a <literal>ClassCastException</literal> at runtime when the argument
- refers to a supertype of the actual type and you do not supply a
- reference of the actual type. In the following aspect, the
- around advice replaces the declared target <literal>List</literal>
- with an <literal>ArrayList</literal>. This is valid code at
- compile-time since the types match.
- </para>
-<programlisting>
-import java.util.*;
-
-aspect A {
- Object around(List list): call(* List+.*()) <![CDATA[&&]]> target(list) {
- return proceed(new ArrayList());
- }
-}
-</programlisting>
- <para>
- But imagine a simple program where the actual target is
- <literal>LinkedList</literal>. In this case, the advice would cause a
- <literal>ClassCastException</literal> at runtime, and
- <literal>peek()</literal> is not declared in <literal>ArrayList</literal>.
- </para>
-<programlisting>
-public class Test {
- public static void main(String[] args) {
- new LinkedList().peek();
- }
-}
-</programlisting>
- <para>
- The <literal>ClassCastException</literal> can occur even in situations
- where it appears to be unnecessary, e.g., if the program is changed to
- call <literal>size()</literal>, declared in <literal>List</literal>:
- </para>
-<programlisting>
-public class Test {
- public static void main(String[] args) {
- new LinkedList().size();
- }
-}
-</programlisting>
- <para>
- There will still be a <literal>ClassCastException</literal> because
- it is impossible to prove that there won't be a runtime binary-compatible
- change in the hierarchy of <literal>LinkedList</literal> or some
- other advice on the join point that requires a
- <literal>LinkedList</literal>.
- </para>
-
- <sect2 id="advice-modifiers" xreflabel="advice-modifiers">
- <title>Advice modifiers</title>
-
- <para>
- The <literal>strictfp</literal> modifier is the only modifier allowed
- on advice, and it has the effect of making all floating-point
- expressions within the advice be FP-strict.
- </para>
- </sect2>
-
- <sect2 id="advice-and-checked-exceptions" xreflabel="advice-and-checked-exceptions">
- <title>Advice and checked exceptions</title>
-
- <para>
- An advice declaration must include a <literal>throws</literal> clause
- listing the checked exceptions the body may throw. This list of
- checked exceptions must be compatible with each target join point
- of the advice, or an error is signalled by the compiler.
- </para>
-
- <para>
- For example, in the following declarations:
- </para>
-
-<programlisting>
-import java.io.FileNotFoundException;
-
-class C {
- int i;
-
- int getI() { return i; }
-}
-
-aspect A {
- before(): get(int C.i) {
- throw new FileNotFoundException();
- }
- before() throws FileNotFoundException: get(int C.i) {
- throw new FileNotFoundException();
- }
-}
-</programlisting>
-
- <para>
- both pieces of advice are illegal. The first because the body throws
- an undeclared checked exception, and the second because field get join
- points cannot throw <literal>FileNotFoundException</literal>s.
- </para>
-
- <para> The exceptions that each kind of join point in AspectJ may throw are:
- </para>
-
- <variablelist>
- <varlistentry>
- <term>method call and execution</term>
- <listitem>
- the checked exceptions declared by the target method's
- <literal>throws</literal> clause.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>constructor call and execution</term>
- <listitem>
- the checked exceptions declared by the target constructor's
- <literal>throws</literal> clause.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>field get and set</term>
- <listitem>
- no checked exceptions can be thrown from these join points.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>exception handler execution</term>
- <listitem>
- the exceptions that can be thrown by the target exception handler.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>static initializer execution</term>
- <listitem>
- no checked exceptions can be thrown from these join points.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>pre-initialization and initialization</term>
- <listitem>
- any exception that is in the throws clause of
- <emphasis>all</emphasis> constructors of the initialized class.
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>advice execution</term>
- <listitem>
- any exception that is in the throws clause of the advice.
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect2>
-
- <sect2 id="advice-precedence" xreflabel="advice-precedence">
- <title>Advice precedence</title>
-
- <para>
- Multiple pieces of advice may apply to the same join point. In such
- cases, the resolution order of the advice is based on advice
- precedence.
- </para>
-
- <sect3>
- <title>Determining precedence</title>
-
- <para>There are a number of rules that determine whether a particular
- piece of advice has precedence over another when they advise the same
- join point. </para>
-
- <para>If the two pieces of advice are defined in different aspects,
- then there are three cases: </para>
-
- <itemizedlist>
- <listitem>If aspect A is matched earlier than aspect B in some
- <literal>declare precedence</literal> form, then all advice in
- concrete aspect A has precedence over all advice in concrete aspect B
- when they are on the same join point. </listitem>
-
- <listitem>
- Otherwise, if aspect A is a subaspect of aspect B, then all advice
- defined in A has precedence over all advice defined in
- B. So, unless otherwise specified with
- <literal>declare precedence</literal>, advice in a subaspect
- has precedence over advice in a superaspect.
- </listitem>
-
- <listitem>
- Otherwise, if two pieces of advice are defined in two different
- aspects, it is undefined which one has precedence.
- </listitem>
-
- </itemizedlist>
-
- <para>If the two pieces of advice are defined in the same aspect, then
- there are two cases: </para>
-
- <itemizedlist>
- <listitem>If either are <literal>after</literal> advice, then the one that
- appears later in the aspect has precedence over the one that appears
- earlier. </listitem>
-
- <listitem>Otherwise, then the one that appears earlier in the aspect
- has precedence over the one that appears later.
- </listitem>
-
- </itemizedlist>
-
- <para>These rules can lead to circularity, such as</para>
-
-<programlisting>
-aspect A {
- before(): execution(void main(String[] args)) {}
- after(): execution(void main(String[] args)) {}
- before(): execution(void main(String[] args)) {}
-}
-</programlisting>
-
- <para>such circularities will result in errors signalled by the compiler. </para>
- </sect3>
-
- <sect3>
- <title>Effects of precedence</title>
-
- <para>At a particular join point, advice is ordered by precedence.</para>
-
- <para>A piece of <literal>around</literal> advice controls whether
- advice of lower precedence will run by calling
- <literal>proceed</literal>. The call to <literal>proceed</literal>
- will run the advice with next precedence, or the computation under the
- join point if there is no further advice. </para>
-
- <para>A piece of <literal>before</literal> advice can prevent advice of
- lower precedence from running by throwing an exception. If it returns
- normally, however, then the advice of the next precedence, or the
- computation under the join pint if there is no further advice, will run.
- </para>
-
- <para>Running <literal>after returning</literal> advice will run the
- advice of next precedence, or the computation under the join point if
- there is no further advice. Then, if that computation returned
- normally, the body of the advice will run. </para>
-
- <para>Running <literal>after throwing</literal> advice will run the
- advice of next precedence, or the computation under the join
- point if there is no further advice. Then, if that computation threw
- an exception of an appropriate type, the body of the advice will
- run. </para>
-
- <para>Running <literal>after</literal> advice will run the advice of
- next precedence, or the computation under the join point if
- there is no further advice. Then the body of the advice will
- run. </para>
- </sect3>
- </sect2>
-
- <sect2 id="reflective-access-to-the-join-point" xreflabel="reflective-access-to-the-join-point">
- <title>Reflective access to the join point</title>
-
- <para>
- Three special variables are visible within bodies of advice
- and within <literal>if()</literal> pointcut expressions:
- <literal>thisJoinPoint</literal>,
- <literal>thisJoinPointStaticPart</literal>, and
- <literal>thisEnclosingJoinPointStaticPart</literal>. Each is bound to
- an object that encapsulates some of the context of the advice's current
- or enclosing join point. These variables exist because some pointcuts
- may pick out very large collections of join points. For example, the
- pointcut
- </para>
-
-
-<programlisting>
-pointcut publicCall(): call(public * *(..));
-</programlisting>
-
-
- <para>
- picks out calls to many methods. Yet the body of advice over this
- pointcut may wish to have access to the method name or parameters of a
- particular join point.
- </para>
-
- <para>
- <literal>thisJoinPoint</literal> is bound to a complete join point
- object.
-
- </para>
-
- <para>
- <literal>thisJoinPointStaticPart</literal> is bound to a part of the
- join point object that includes less information, but for which no
- memory allocation is required on each execution of the advice. It is
- equivalent to <literal>thisJoinPoint.getStaticPart()</literal>.
- </para>
-
- <para>
- <literal>thisEnclosingJoinPointStaticPart</literal> is bound to the
- static part of the join point enclosing the current join point. Only
- the static part of this enclosing join point is available through this
- mechanism.
- </para>
-
- <para>
- Standard Java reflection uses objects from the
- <literal>java.lang.reflect</literal> hierarchy to build up its
- reflective objects. Similarly, AspectJ join point objects have types
- in a type hierarchy. The type of objects bound to
- <literal>thisJoinPoint</literal> is
- <literal>org.aspectj.lang.JoinPoint</literal>, while
- <literal>thisStaticJoinPoint</literal> is bound to objects of interface
- type <literal>org.aspectj.lang.JoinPoint.StaticPart</literal>.
- </para>
- </sect2>
-
- </sect1>
-
- <sect1 id="semantics-declare">
- <title>Static crosscutting</title>
-
- <para>
- Advice declarations change the behavior of classes they crosscut, but do
- not change their static type structure. For crosscutting concerns that do
- operate over the static structure of type hierarchies, AspectJ provides
- inter-type member declarations and other <literal>declare</literal> forms.
- </para>
-
- <sect2 id="inter-type-member-declarations" xreflabel="inter-type-member-declarations">
- <title>Inter-type member declarations</title>
-
- <para>
- AspectJ allows the declaration of members by aspects that are
- associated with other types.
- </para>
-
- <para>
- An inter-type method declaration looks like
- </para>
-
- <itemizedlist>
- <listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>Type</replaceable> <replaceable>OnType</replaceable>
- .
- <replaceable>Id</replaceable>(<replaceable>Formals</replaceable>)
- [ <replaceable>ThrowsClause</replaceable> ]
- { <replaceable>Body</replaceable> }</literal></listitem>
-
- <listitem><literal>abstract
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>Type</replaceable> <replaceable>OnType</replaceable>
- . <replaceable>Id</replaceable>(<replaceable>Formals</replaceable>)
- [ <replaceable>ThrowsClause</replaceable> ]
- ;
- </literal></listitem>
- </itemizedlist>
-
- <para>
- The effect of such a declaration is to make <replaceable>OnType</replaceable>
- support the new method. Even if <replaceable>OnType</replaceable> is
- an interface. Even if the method is neither public nor abstract. So the
- following is legal AspectJ code:
- </para>
-
-<programlisting>
-interface Iface {}
-
-aspect A {
- private void Iface.m() {
- System.err.println("I'm a private method on an interface");
- }
- void worksOnI(Iface iface) {
- // calling a private method on an interface
- iface.m();
- }
-}
-</programlisting>
-
- <para>
- An inter-type constructor declaration looks like
- </para>
-
- <itemizedlist>
- <listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>OnType</replaceable> . new (
- <replaceable>Formals</replaceable> )
- [ <replaceable>ThrowsClause</replaceable> ]
- { <replaceable>Body</replaceable> }</literal></listitem>
- </itemizedlist>
-
- <para>
- The effect of such a declaration is to make
- <replaceable>OnType</replaceable> support the new constructor. It is
- an error for <replaceable>OnType</replaceable> to be an interface.
- </para>
-
- <para>
- Inter-type declared constructors cannot be used to assign a
- value to a final variable declared in <replaceable>OnType</replaceable>.
- This limitation significantly increases the ability to both understand
- and compile the <replaceable>OnType</replaceable> class and the
- declaring aspect separately.
- </para>
-
- <para>
- Note that in the Java language, classes that define no constructors
- have an implicit no-argument constructor that just calls
- <literal>super()</literal>. This means that attempting to declare
- a no-argument inter-type constructor on such a class may result in
- a conflict, even though it <emphasis>looks</emphasis> like no
- constructor is defined.
- </para>
-
- <para>
- An inter-type field declaration looks like one of
- </para>
-
- <itemizedlist>
- <listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>Type</replaceable>
- <replaceable>OnType</replaceable> . <replaceable>Id</replaceable>
- = <replaceable>Expression</replaceable>;</literal></listitem>
-
- <listitem><literal>
- [ <replaceable>Modifiers</replaceable> ]
- <replaceable>Type</replaceable>
- <replaceable>OnType</replaceable> . <replaceable>Id</replaceable>;</literal></listitem>
- </itemizedlist>
-
- <para>
- The effect of such a declaration is to make
- <replaceable>OnType</replaceable> support the new field. Even if
- <replaceable>OnType</replaceable> is an interface. Even if the field is
- neither public, nor static, nor final.
- </para>
-
- <para>
- The initializer, if any, of an inter-type field declaration runs
- before the class-local initializers defined in its target class.
- </para>
-
- </sect2>
-
- <para>
- Any occurrence of the identifier <literal>this</literal> in the body of
- an inter-type constructor or method declaration, or in the initializer
- of an inter-type field declaration, refers to the
- <replaceable>OnType</replaceable> object rather than to the aspect
- type; it is an error to access <literal>this</literal> in such a
- position from a <literal>static</literal> inter-type member
- declaration.
- </para>
-
- <sect2 id="access-modifiers" xreflabel="access-modifiers">
- <title>Access modifiers</title>
-
- <para>
- Inter-type member declarations may be public or private, or have
- default (package-protected) visibility. AspectJ does not provide
- protected inter-type members.
- </para>
-
- <para>
- The access modifier applies in relation to the aspect, not in relation
- to the target type. So a private inter-type member is visible only from
- code that is defined within the declaring aspect. A default-visibility
- inter-type member is visible only from code that is defined within the
- declaring aspect's package.
- </para>
-
- <para>
- Note that a declaring a private inter-type method (which AspectJ
- supports) is very different from inserting a private method declaration
- into another class. The former allows access only from the declaring
- aspect, while the latter would allow access only from the target type.
- Java serialization, for example, uses the presense of a private method
- <literal>void writeObject(ObjectOutputStream)</literal> for the
- implementation of <literal>java.io.Serializable</literal>. A private
- inter-type declaration of that method would not fulfill this
- requirement, since it would be private to the aspect, not private to
- the target type.
- </para>
-
- <para>
- The access modifier of abstract inter-type methods has
- one constraint: It is illegal to declare an abstract
- non-public inter-type method on a public interface. This
- is illegal because it would say that a public interface
- has a constraint that only non-public implementors must
- fulfill. This would not be compatible with Java's type
- system.
- </para>
- </sect2>
-
- <sect2 id="conflicts" xreflabel="conflicts">
- <title>Conflicts</title>
-
- <para>
- Inter-type declarations raise the possibility of conflicts among
- locally declared members and inter-type members. For example, assuming
- <literal>otherPackage</literal> is not the package containing the
- aspect <classname>A</classname>, the code
- </para>
-
-<programlisting>
-aspect A {
- private Registry otherPackage.onType.r;
- public void otherPackage.onType.register(Registry r) {
- r.register(this);
- this.r = r;
- }
-}
-</programlisting>
-
- <para>
- declares that <literal>onType</literal> in <literal>otherPackage</literal> has a field
- <literal>r</literal>. This field, however, is only accessible from the
- code inside of aspect <literal>A</literal>. The aspect also declares
- that <literal>onType</literal> has a method
- "<literal>register</literal>", but makes this method accessible from
- everywhere.
- </para>
-
- <para>
- If <literal>onType</literal> already defines a
- private or package-protected field "<literal>r</literal>", there is no
- conflict: The aspect cannot see such a field, and no code in
- <literal>otherPackage</literal> can see the inter-type
- "<literal>r</literal>".
- </para>
-
- <para>
- If <literal>onType</literal> defines a public field
- "<literal>r</literal>", there is a conflict: The expression
- </para>
-
-<programlisting>
-this.r = r
-</programlisting>
-
- <para>
- is an error, since it is ambiguous whether the private inter-type
- "<literal>r</literal>" or the public locally-defined
- "<literal>r</literal>" should be used.
- </para>
-
- <para>
- If <literal>onType</literal> defines a method
- "<literal>register(Registry)</literal>" there is a conflict, since it
- would be ambiguous to any code that could see such a defined method
- which "<literal>register(Registry)</literal>" method was applicable.
- </para>
-
- <para>
- Conflicts are resolved as much as possible as per Java's conflict
- resolution rules:
- </para>
-
- <itemizedlist>
- <listitem>A subclass can inherit multiple <emphasis>fields</emphasis> from its superclasses,
- all with the same name and type. However, it is an error to have an ambiguous
- <emphasis>reference</emphasis> to a field.</listitem>
-
- <listitem>A subclass can only inherit multiple
- <emphasis>methods</emphasis> with the same name and argument types from
- its superclasses if only zero or one of them is concrete (i.e., all but
- one is abstract, or all are abstract).
- </listitem>
- </itemizedlist>
-
- <para>
- Given a potential conflict between inter-type member declarations in
- different aspects, if one aspect has precedence over the other its
- declaration will take effect without any conflict notice from compiler.
- This is true both when the precedence is declared explicitly with
- <literal>declare precedence</literal> as well as when when sub-aspects
- implicitly have precedence over their super-aspect.
- </para>
-
- </sect2>
-
- <sect2 id="extension-and-implementation" xreflabel="extension-and-implementation">
- <title>Extension and Implementation</title>
-
- <para>
- An aspect may change the inheritance hierarchy of a system by changing
- the superclass of a type or adding a superinterface onto a type, with
- the <literal>declare parents</literal> form.
- </para>
-
- <itemizedlist>
- <listitem><literal>declare parents: <replaceable>TypePattern</replaceable> extends <replaceable>Type</replaceable>;</literal></listitem>
- <listitem><literal>declare parents: <replaceable>TypePattern</replaceable> implements <replaceable>TypeList</replaceable>;</literal></listitem>
- </itemizedlist>
-
- <para>
- For example, if an aspect wished to make a particular class runnable,
- it might define appropriate inter-type <literal>void
- run()</literal> method, but it should also declare that the class
- fulfills the <literal>Runnable</literal> interface. In order to
- implement the methods in the <literal>Runnable</literal> interface, the
- inter-type <literal>run()</literal> method must be public:
- </para>
-
-<programlisting>
-aspect A {
- declare parents: SomeClass implements Runnable;
- public void SomeClass.run() { ... }
-}
-</programlisting>
-
- </sect2>
-
- <sect2 id="interfaces-with-members" xreflabel="interfaces-with-members">
- <title>Interfaces with members</title>
-
- <para>
- Through the use of inter-type members, interfaces may now carry
- (non-public-static-final) fields and (non-public-abstract) methods that
- classes can inherit. Conflicts may occur from ambiguously inheriting
- members from a superclass and multiple superinterfaces.
- </para>
-
- <para>
- Because interfaces may carry non-static initializers, each interface
- behaves as if it has a zero-argument constructor containing its
- initializers. The order of super-interface instantiation is
- observable. We fix this order with the following properties: A
- supertype is initialized before a subtype, initialized code runs only
- once, and the initializers for a type's superclass are run before the
- initializers for its superinterfaces. Consider the following hierarchy
- where {<literal>Object</literal>, <literal>C</literal>,
- <literal>D</literal>, <literal>E</literal>} are classes,
- {<literal>M</literal>, <literal>N</literal>, <literal>O</literal>,
- <literal>P</literal>, <literal>Q</literal>} are interfaces.
- </para>
-
-<programlisting>
- Object M O
- \ / \ /
- C N Q
- \ / /
- D P
- \ /
- E
-</programlisting>
-
- <para>
- when a new <literal>E</literal> is instantiated, the initializers run in this order:
- </para>
-
-<programlisting>
-Object M C O N D Q P E
-</programlisting>
-
- </sect2>
-
-<!-- ============================== -->
-
- <sect2 id="warnings-and-errors" xreflabel="warnings-and-errors">
- <title>Warnings and Errors</title>
-
- <para>An aspect may specify that a particular join point should never be
- reached. </para>
-
- <itemizedlist>
- <listitem><literal>declare error: <replaceable>Pointcut</replaceable>: <replaceable>String</replaceable>;</literal></listitem>
- <listitem><literal>declare warning: <replaceable>Pointcut</replaceable>: <replaceable>String</replaceable>;</literal></listitem>
- </itemizedlist>
-
- <para>If the compiler determines that a join point in
- <replaceable>Pointcut</replaceable> could possibly be reached, then it
- will signal either an error or warning, as declared, using the
- <replaceable>String</replaceable> for its message. </para>
-
- </sect2>
-
- <sect2 id="softened-exceptions" xreflabel="softened-exceptions">
- <title>Softened exceptions</title>
-
- <para>An aspect may specify that a particular kind of exception, if
- thrown at a join point, should bypass Java's usual static exception
- checking system and instead be thrown as a
- <literal>org.aspectj.lang.SoftException</literal>, which is subtype of
- <literal>RuntimeException</literal> and thus does not need to be
- declared. </para>
-
- <itemizedlist>
- <listitem><literal>declare soft: <replaceable>Type</replaceable>: <replaceable>Pointcut</replaceable>;</literal></listitem>
- </itemizedlist>
-
- <para>For example, the aspect</para>
-
-<programlisting>
-aspect A {
- declare soft: Exception: execution(void main(String[] args));
-}
-</programlisting>
-
- <para>Would, at the execution join point, catch any
- <literal>Exception</literal> and rethrow a
- <literal>org.aspectj.lang.SoftException</literal> containing
- original exception. </para>
-
- <para>This is similar to what the following advice would do</para>
-
-<programlisting>
-aspect A {
- void around() execution(void main(String[] args)) {
- try { proceed(); }
- catch (Exception e) {
- throw new org.aspectj.lang.SoftException(e);
- }
- }
-}
-</programlisting>
-
- <para>except, in addition to wrapping the exception, it also affects
- Java's static exception checking mechanism. </para>
-
- <para> Like advice, the declare soft form has no effect in an
- abstract aspect that is not extended by a concreate aspect. So
- the following code will not compile unless it is compiled with an
- extending concrete aspect:</para>
-
-<programlisting>
-abstract aspect A {
- abstract pointcut softeningPC();
-
- before() : softeningPC() {
- Class.forName("FooClass"); // error: uncaught ClassNotFoundException
- }
-
- declare soft : ClassNotFoundException : call(* Class.*(..));
-}
-</programlisting>
-
- </sect2>
-
- <sect2 id="advice-precedence-cross" xreflabel="advice-precedence-cross">
- <title>Advice Precedence</title>
-
- <para>
- An aspect may declare a precedence relationship between concrete
- aspects with the <literal>declare precedence</literal> form:
- </para>
-
- <itemizedlist>
- <listitem><literal>declare precedence :
- <replaceable>TypePatternList</replaceable> ; </literal></listitem>
- </itemizedlist>
-
- <para>This signifies that if any join point has advice from two
- concrete aspects matched by some pattern in
- <replaceable>TypePatternList</replaceable>, then the precedence of
- the advice will be the order of in the list. </para>
-
- <para>In <replaceable>TypePatternList</replaceable>, the wildcard "*" can
- appear at most once, and it means "any type not matched by any other
- pattern in the list". </para>
-
- <para>For example, the constraints that (1) aspects that have
- Security as part of their name should have precedence over all other
- aspects, and (2) the Logging aspect (and any aspect that extends it)
- should have precedence over all non-security aspects, can be
- expressed by:</para>
-
-<programlisting>
-declare precedence: *..*Security*, Logging+, *;
-</programlisting>
-
- <para>
- For another example, the CountEntry aspect might want to count the
- entry to methods in the current package accepting a Type object as
- its first argument. However, it should count all entries, even
- those that the aspect DisallowNulls causes to throw exceptions.
- This can be accomplished by stating that CountEntry has precedence
- over DisallowNulls. This declaration could be in either aspect, or
- in another, ordering aspect:
- </para>
-
-<programlisting>
-aspect Ordering {
- declare precedence: CountEntry, DisallowNulls;
-}
-aspect DisallowNulls {
- pointcut allTypeMethods(Type obj): call(* *(..)) <![CDATA[&&]]> args(obj, ..);
- before(Type obj): allTypeMethods(obj) {
- if (obj == null) throw new RuntimeException();
- }
-}
-aspect CountEntry {
- pointcut allTypeMethods(Type obj): call(* *(..)) <![CDATA[&&]]> args(obj, ..);
- static int count = 0;
- before(): allTypeMethods(Type) {
- count++;
- }
-}
-</programlisting>
-
- <sect3>
- <title>Various cycles</title>
-
- <para>
- It is an error for any aspect to be matched by more than one
- TypePattern in a single decare precedence, so:
- </para>
-
-<programlisting>
-declare precedence: A, B, A ; // error
-</programlisting>
-
- <para>
- However, multiple declare precedence forms may legally have this
- kind of circularity. For example, each of these declare
- precedence is perfectly legal:
- </para>
-
-<programlisting>
-declare precedence: B, A;
-declare precedence: A, B;
-</programlisting>
-
- <para>
- And a system in which both constraints are active may also be
- legal, so long as advice from A and B don't share a join
- point. So this is an idiom that can be used to enforce that A and
- B are strongly independent.
- </para>
- </sect3>
-
- <sect3>
- <title>Applies to concrete aspects</title>
-
- <para>
- Consider the following library aspects:
- </para>
-
-<programlisting>
-abstract aspect Logging {
- abstract pointcut logged();
-
- before(): logged() {
- System.err.println("thisJoinPoint: " + thisJoinPoint);
- }
-}
-
-abstract aspect MyProfiling {
- abstract pointcut profiled();
-
- Object around(): profiled() {
- long beforeTime = System.currentTimeMillis();
- try {
- return proceed();
- } finally {
- long afterTime = System.currentTimeMillis();
- addToProfile(thisJoinPointStaticPart,
- afterTime - beforeTime);
- }
- }
- abstract void addToProfile(
- org.aspectj.JoinPoint.StaticPart jp,
- long elapsed);
-}
-</programlisting>
-
- <para>
- In order to use either aspect, they must be extended with
- concrete aspects, say, MyLogging and MyProfiling. Because advice
- only applies from concrete aspects, the declare precedence form
- only matters when declaring precedence with concrete aspects. So
- </para>
-
-<programlisting>
-declare precedence: Logging, Profiling;
-</programlisting>
-
- <para>
- has no effect, but both
- </para>
-
-<programlisting>
-declare precedence: MyLogging, MyProfiling;
-declare precedence: Logging+, Profiling+;
-</programlisting>
-
- <para>
- are meaningful.
- </para>
- </sect3>
- </sect2>
-
-
- <sect2 id="statically-determinable-pointcuts" xreflabel="statically-determinable-pointcuts">
- <title>Statically determinable pointcuts</title>
-
- <para>Pointcuts that appear inside of <literal>declare</literal> forms
- have certain restrictions. Like other pointcuts, these pick out join
- points, but they do so in a way that is statically determinable. </para>
-
- <para>Consequently, such pointcuts may not include, directly or
- indirectly (through user-defined pointcut declarations) pointcuts that
- discriminate based on dynamic (runtime) context. Therefore, such
- pointcuts may not be defined in terms of</para>
-
- <itemizedlist>
- <listitem>cflow</listitem>
- <listitem>cflowbelow</listitem>
- <listitem>this</listitem>
- <listitem>target</listitem>
- <listitem>args</listitem>
- <listitem>if</listitem>
- </itemizedlist>
-
- <para> all of which can discriminate on runtime information. </para>
- </sect2>
- </sect1>
-
- <sect1 id="semantics-aspects">
- <title>Aspects</title>
-
- <para>
- An aspect is a crosscutting type defined by the <literal>aspect</literal>
- declaration.
- </para>
-
- <sect2 id="aspect-declaration" xreflabel="aspect-declaration">
- <title>Aspect Declaration</title>
-
- <para>
- The <literal>aspect</literal> declaration is similar to the
- <literal>class</literal> declaration in that it defines a type and an
- implementation for that type. It differs in a number of
- ways:
- </para>
-
- <sect3>
- <title>Aspect implementation can cut across other types</title>
-
- <para> In addition to normal Java class declarations such as
- methods and fields, aspect declarations can include AspectJ
- declarations such as advice, pointcuts, and inter-type
- declarations. Thus, aspects contain implementation
- declarations that can can cut across other types (including those defined by
- other aspect declarations).
- </para>
- </sect3>
-
- <sect3>
- <title>Aspects are not directly instantiated</title>
-
- <para> Aspects are not directly instantiated with a new
- expression, with cloning, or with serialization. Aspects may
- have one constructor definition, but if so it must be of a
- constructor taking no arguments and throwing no checked
- exceptions.
- </para>
- </sect3>
-
- <sect3>
- <title>Nested aspects must be <literal>static</literal></title>
-
- <para>
- Aspects may be defined either at the package level, or as a static nested
- aspect -- that is, a static member of a class, interface, or aspect. If it
- is not at the package level, the aspect <emphasis>must</emphasis> be
- defined with the static keyword. Local and anonymous aspects are not
- allowed.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="aspect-extension" xreflabel="aspect-extension">
- <title>Aspect Extension</title>
-
- <para>
- To support abstraction and composition of crosscutting concerns,
- aspects can be extended in much the same way that classes can. Aspect
- extension adds some new rules, though.
- </para>
-
- <sect3>
- <title>Aspects may extend classes and implement interfaces</title>
-
- <para>
- An aspect, abstract or concrete, may extend a class and may implement
- a set of interfaces. Extending a class does not provide the ability
- to instantiate the aspect with a new expression: The aspect may still
- only define a null constructor.
- </para>
- </sect3>
-
- <sect3>
- <title>Classes may not extend aspects</title>
-
- <para>
- It is an error for a class to extend or implement an aspect.
- </para>
- </sect3>
-
- <sect3>
- <title>Aspects extending aspects
- </title>
- <para>
- Aspects may extend other aspects, in which case not only are fields
- and methods inherited but so are pointcuts. However, aspects may only
- extend abstract aspects. It is an error for a concrete aspect to
- extend another concrete aspect.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="aspect-instantiation" xreflabel="aspect-instantiation">
- <title>Aspect instantiation</title>
-
- <para>
- Unlike class expressions, aspects are not instantiated with
- <literal>new</literal> expressions. Rather, aspect instances are
- automatically created to cut across programs. A program
- can get a reference to an aspect instance using the static
- method <literal>aspectOf(..)</literal>.
- </para>
-
- <para>
- Because advice only runs in the context of an aspect instance, aspect
- instantiation indirectly controls when advice runs.
- </para>
-
- <para>
- The criteria used to determine how an aspect is instantiated
- is inherited from its parent aspect. If the aspect has no parent
- aspect, then by default the aspect is a singleton aspect.
- How an aspect is instantiated controls the form of the
- <literal>aspectOf(..)</literal> method defined on the
- concrete aspect class.
- </para>
-
- <sect3>
- <title>Singleton Aspects</title>
-
- <itemizedlist>
- <listitem><literal>aspect <replaceable>Id</replaceable> { ... }</literal></listitem>
- <listitem><literal>aspect <replaceable>Id</replaceable> issingleton() { ... }</literal></listitem>
- </itemizedlist>
-
- <para>
- By default (or by using the modifier <literal>issingleton()</literal>)
- an aspect has exactly one instance that cuts across the entire
- program. That instance is available at any time during program
- execution from the static method <literal>aspectOf()</literal>
- automatically defined on all concrete aspects
- -- so, in the above examples, <literal>A.aspectOf()</literal> will
- return A's instance. This aspect instance is created as the aspect's
- classfile is loaded.
- </para>
-
- <para>
- Because the an instance of the aspect exists at all join points in
- the running of a program (once its class is loaded), its advice will
- have a chance to run at all such join points.
- </para>
-
- <para>
- (In actuality, one instance of the aspect A is made for each version
- of the aspect A, so there will be one instantiation for each time A
- is loaded by a different classloader.)
- </para>
- </sect3>
-
- <sect3>
- <title>Per-object aspects</title>
-
- <itemizedlist>
- <listitem><literal>aspect <replaceable>Id</replaceable> perthis(<replaceable>Pointcut</replaceable>) { ... }</literal></listitem>
- <listitem><literal>aspect <replaceable>Id</replaceable> pertarget(<replaceable>Pointcut</replaceable>) { ... }</literal></listitem>
- </itemizedlist>
-
- <para>
- If an aspect A is defined
- <literal>perthis(<replaceable>Pointcut</replaceable>)</literal>, then
- one object of type A is created for every object that is the
- executing object (i.e., "this") at any of the join points picked out
- by <replaceable>Pointcut</replaceable>.
- The advice defined in A will run only at a join point where the
- currently executing object has been associated with an instance of
- A.
- </para>
-
- <para> Similarly, if an aspect A is defined
- <literal>pertarget(<replaceable>Pointcut</replaceable>)</literal>,
- then one object of type A is created for every object that is the
- target object of the join points picked out by
- <replaceable>Pointcut</replaceable>.
- The advice defined in A will run only at a join point where the
- target object has been associated with an instance of
- A.
- </para>
-
- <para>
- In either case, the static method call
- <literal>A.aspectOf(Object)</literal> can be used to get the aspect
- instance (of type A) registered with the object. Each aspect
- instance is created as early as possible, but not before reaching a
- join point picked out by <replaceable>Pointcut</replaceable> where
- there is no associated aspect of type A.
- </para>
-
- <para> Both <literal>perthis</literal> and <literal>pertarget</literal>
- aspects may be affected by code the AspectJ compiler controls, as
- discussed in the <xref linkend="implementation"/> appendix. </para>
- </sect3>
-
- <sect3>
- <title>Per-control-flow aspects</title>
-
- <itemizedlist>
- <listitem><literal>aspect <replaceable>Id</replaceable> percflow(<replaceable>Pointcut</replaceable>) { ... }</literal></listitem>
- <listitem><literal>aspect <replaceable>Id</replaceable> percflowbelow(<replaceable>Pointcut</replaceable>) { ... }</literal></listitem>
- </itemizedlist>
-
- <para>
- If an aspect A is defined
- <literal>percflow(<replaceable>Pointcut</replaceable>)</literal> or
- <literal>percflowbelow(<replaceable>Pointcut</replaceable>)</literal>,
- then one object of type A is created for each flow of control of the
- join points picked out by <replaceable>Pointcut</replaceable>, either
- as the flow of control is entered, or below the flow of control,
- respectively. The advice defined in A may run at any join point in
- or under that control flow. During each such flow of control, the
- static method <literal>A.aspectOf()</literal> will return an object
- of type
- A. An instance of the aspect is created upon entry into each such
- control flow.
- </para>
- </sect3>
-
- <sect3>
- <title>Aspect instantiation and advice</title>
-
- <para>
- All advice runs in the context of an aspect instance,
- but it is possible to write a piece of advice with a pointcut
- that picks out a join point that must occur before asopect
- instantiation. For example:
- </para>
-
-<programlisting>
-public class Client
-{
- public static void main(String[] args) {
- Client c = new Client();
- }
-}
-
-aspect Watchcall {
- pointcut myConstructor(): execution(new(..));
-
- before(): myConstructor() {
- System.err.println("Entering Constructor");
- }
-}
-</programlisting>
-
- <para>
- The before advice should run before the execution of all
- constructors in the system. It must run in the context of an
- instance of the Watchcall aspect. The only way to get such an
- instance is to have Watchcall's default constructor execute. But
- before that executes, we need to run the before advice...
- </para>
-
- <para>
- There is no general way to detect these kinds of circularities at
- compile time. If advice runs before its aspect is instantiated,
- AspectJ will throw a <ulink
- url="../api/org/aspectj/lang/NoAspectBoundException.html">
- <literal>org.aspectj.lang.NoAspectBoundException</literal></ulink>.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="aspect-privilege" xreflabel="aspect-privilege">
- <title>Aspect privilege</title>
-
- <itemizedlist>
- <listitem><literal>privileged aspect <replaceable>Id</replaceable> { ... }</literal></listitem>
- </itemizedlist>
-
- <para>
- Code written in aspects is subject to the same access control rules as
- Java code when referring to members of classes or aspects. So, for
- example, code written in an aspect may not refer to members with
- default (package-protected) visibility unless the aspect is defined in
- the same package.
- </para>
-
- <para>
- While these restrictions are suitable for many aspects, there may be
- some aspects in which advice or inter-type members needs to access private
- or protected resources of other types. To allow this, aspects may be
- declared <literal>privileged</literal>. Code in priviliged aspects has
- access to all members, even private ones.
- </para>
-
-<programlisting>
-class C {
- private int i = 0;
- void incI(int x) { i = i+x; }
-}
-privileged aspect A {
- static final int MAX = 1000;
- before(int x, C c): call(void C.incI(int)) <![CDATA[&&]]> target(c) <![CDATA[&&]]> args(x) {
- if (c.i+x &gt; MAX) throw new RuntimeException();
- }
-}
-</programlisting>
-
- <para>
- In this case, if A had not been declared privileged, the field reference
- c.i would have resulted in an error signaled by the compiler.
- </para>
-
- <para>
- If a privileged aspect can access multiple versions of a particular
- member, then those that it could see if it were not privileged take
- precedence. For example, in the code
- </para>
-
-<programlisting>
-class C {
- private int i = 0;
- void foo() { }
-}
-
-privileged aspect A {
- private int C.i = 999;
- before(C c): call(void C.foo()) target(c) {
- System.out.println(c.i);
- }
-}
-</programlisting>
-
- <para>
- A's private inter-type field C.i, initially bound to 999, will be
- referenced in the body of the advice in preference to C's privately
- declared field, since the A would have access to its own inter-type
- fields even if it were not privileged.
- </para>
-
- <para>
- Note that a privileged aspect can access private inter-type
- declarations made by other aspects, since they are simply
- considered private members of that other aspect.
- </para>
- </sect2>
- </sect1>
-</appendix>
-
-
-