aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB/language.xml
diff options
context:
space:
mode:
Diffstat (limited to 'docs/progGuideDB/language.xml')
-rw-r--r--docs/progGuideDB/language.xml878
1 files changed, 477 insertions, 401 deletions
diff --git a/docs/progGuideDB/language.xml b/docs/progGuideDB/language.xml
index 6a7a5dda3..709b5c764 100644
--- a/docs/progGuideDB/language.xml
+++ b/docs/progGuideDB/language.xml
@@ -1,29 +1,34 @@
-<chapter id="aspectjlanguage" xreflabel="The AspectJ Language">
+<chapter id="language" xreflabel="The AspectJ Language">
<title>The AspectJ Language</title>
- <sect1>
+ <sect1 id="language-intro">
<title>Introduction</title>
- <para>The previous chapter, <xref linkend="gettingstarted"/>, was a brief
+ <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.
+ 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
+ <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>
-
+ example aspect will gives us something concrete to talk about.
+ </para>
</sect1>
- <sect1 id="AnatomyOfAnAspect">
+<!-- ============================== -->
+
+ <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.
+ 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>
@@ -60,18 +65,19 @@
]]></programlisting>
<para>
- The <literal>FaultHandler</literal> consists of one variable introduced
- onto <literal>Server</literal> (line 03), two methods (lines 05-07
- and 09-11), one pointcut (line 13), and two pieces of advice (lines
- 15-17 and 19-22).
+ 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 with other program entities, ordinary
- variables and methods, pointcuts, introductions, and advice, where
- advice may be before, after or around advice. The remainder of this
- lesson focuses on those crosscut-related constructs.
+ 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>
@@ -79,11 +85,12 @@
<title>Pointcuts</title>
<para>
- AspectJ's pointcuts define collections of events, i.e. interesting
- points in the execution of a program. These events, or points in the
- execution, can be method or constructor invocations and executions,
- handling of exceptions, field assignments and accesses, etc. Take, for
- example, the pointcut declaration in line 13:
+ 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[
@@ -91,59 +98,65 @@ 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 instances of the
- <literal>Server</literal> class have their public methods called.
+ 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
+ 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 server. 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 public.
+ 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>
- <sect3>
- <title>What else?</title>
-
- <para>
- Pointcuts define arbitrarily large sets of points in the execution
- of a program. But they use only a finite number of
- <emphasis>kinds</emphasis> of points. Those kinds of points
- correspond to some of the most important concepts in Java. Here is
- an incomplete list: method invocation, method execution, exception
- handling, instantiation, constructor execution. Each of these has a
- specific syntax that you will learn about in other parts of this
- guide.
- </para>
- </sect3>
+ <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>
<title>Advice</title>
<para>
- Advice defines pieces of aspect implementation that execute at join
- points picked out by a pointcut. For example, the advice in lines 15-17
- specifies that the following piece of code
+ 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[
@@ -153,10 +166,10 @@ pointcut services(Server s): target(s) && call(public * *(..))
]]></programlisting>
<para>
- is executed when instances of the Server class have their public
- methods called, as specified by the pointcut services. More
- specifically, it runs when those calls are made, just before the
- corresponding methods are executed.
+ 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>
@@ -172,24 +185,23 @@ pointcut services(Server s): target(s) && call(public * *(..))
]]></programlisting>
<para>
- But this second method executes whenever those operations throw
+ But this second method executes after those operations throw
exception of type <literal>FaultException</literal>.
</para>
- <sect3>
- <title>What else?</title>
- <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>
- </sect3>
+ <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>
+<!-- ============================== -->
+
+ <sect1 id="language-joinPoints">
<title>Join Points and Pointcuts</title>
<para>
@@ -211,9 +223,9 @@ class Point {
]]></programlisting>
<para>
- In order to get an intuitive understanding of AspectJ's pointcuts, let's
- go back to some of the basic principles of Java. Consider the following a
- method declaration in class Point:
+ 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[
@@ -221,22 +233,29 @@ void setX(int x) { this.x = x; }
]]></programlisting>
<para>
- What this piece of program states is that when an object of type Point
- has a method called setX with an integer as the argument called on it,
- then the method body { this.x = x; } is executed. Similarly, the
- constructor given in that class states that when an object of type Point
- is instantiated through a constructor with two integers as arguments,
- then the constructor body { this.x = x; this.y = y; } is executed.
+ This piece of program says that 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 when something
- happens, then something gets executed. 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 comprised
- method calls, method executions, instantiations, constructor executions,
- field references and handler executions. (See the quick reference for
- complete listing.)
+ 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>
@@ -250,9 +269,9 @@ pointcut setter(): target(Point) &&
]]></programlisting>
<para>
- describes the calls to <literal>setX(int)</literal> or
- <literal>setY(int)</literal> methods of any instance of Point. Here's
- another example:
+ 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[
@@ -260,31 +279,26 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
]]></programlisting>
<para>
- This pointcut picks out the join points at which exceptions of type
- IOException are handled inside the code defined by class MyClass.
- </para>
-
- <para>
- Pointcuts consist of a left-hand side and a right-hand side, separated by
- a colon. The left-hand side defines the pointcut name and the pointcut
- parameters (i.e. the data available when the events happen). The
- right-hand side defines the events in the pointcut.
+ 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>
- Pointcuts can then be used to define aspect code in advice, as we will
- see later. But first let's see what types of events can be captured and
- how they are described in AspectJ.
+ 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>
- <title>Designators</title>
+ <title>Some Example Pointcuts</title>
<para>
- Here are examples of designators of
+ Here are examples of pointcuts picking out
</para>
- <variablelist>
+ <variablelist>
<varlistentry>
<term>when a particular method body executes</term>
<listitem>
@@ -313,8 +327,11 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</varlistentry>
<varlistentry>
- <term>when the object currently executing
- (i.e. <literal>this</literal>) is of type <literal>SomeType</literal></term>
+ <term>
+ when the object currently executing
+ (i.e. <literal>this</literal>) is of type
+ <literal>SomeType</literal>
+ </term>
<listitem>
<para>
<literal>this(SomeType)</literal>
@@ -323,8 +340,9 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</varlistentry>
<varlistentry>
- <term>when the target object is of type
- <literal>SomeType</literal></term>
+ <term>
+ when the target object is of type <literal>SomeType</literal>
+ </term>
<listitem>
<para>
<literal>target(SomeType)</literal>
@@ -333,8 +351,10 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</varlistentry>
<varlistentry>
- <term>when the executing code belongs to
- class <literal>MyClass</literal></term>
+ <term>
+ when the executing code belongs to
+ class <literal>MyClass</literal>
+ </term>
<listitem>
<para>
<literal>within(MyClass)</literal>
@@ -343,9 +363,11 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</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>
+ <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(void Test.main())</literal>
@@ -355,7 +377,7 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</variablelist>
<para>
- Designators compose through the operations <literal>or</literal>
+ Pointcuts compose through the operations <literal>or</literal>
("<literal>||</literal>"), <literal>and</literal>
("<literal><![CDATA[&&]]></literal>") and <literal>not</literal>
("<literal>!</literal>").
@@ -365,6 +387,7 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
<listitem>
<para>
It is possible to use wildcards. So
+
<orderedlist>
<listitem>
<para>
@@ -378,10 +401,13 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</para>
</listitem>
</orderedlist>
- means (1) all the executions of methods with any return and
- parameter types and (2) method calls of set methods with any
- return and parameter types -- in case of overloading there may be
- more than one; this designator picks out all of them.
+
+ 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>
@@ -414,21 +440,23 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</listitem>
</orderedlist>
- means (1) all executions of methods with no parameters, returning
- an <literal>int</literal> (2) the calls of
- <literal>setY</literal> methods that take a
- <literal>long</literal> as an argument, regardless of their return
- type or defining type, (3) the calls of class
+
+ 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 the
- return type, and (4) the calls of all classes' constructors that
- take two <literal>int</literal>s as arguments.
+ 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 designators. For example,
+ You can compose pointcuts. For example,
<orderedlist>
<listitem>
<para>
@@ -450,30 +478,30 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
<listitem>
<para>
- <literal>this(*) <![CDATA[&&]]> !this(Point) <![CDATA[&&]]>
- call(int *(..))</literal>
+ <literal>
+ !this(Point) <![CDATA[&&]]> call(int *(..))
+ </literal>
</para>
</listitem>
</orderedlist>
- means (1) all calls to methods received by instances of class
- <literal>Point</literal>, with no parameters, returning an
- <literal>int</literal>, (2) calls to any method where the call is
- made from the code in <literal>Point</literal>'s or
- <literal>Line</literal>'s type declaration, (3) executions of
- constructors of all classes, that take an <literal>int</literal> as
- an argument, and
- (4) all method calls of any method returning an
- <literal>int</literal>, from all objects except
- <literal>Point</literal> objects to any other objects.
-
+ 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:
+ You can select methods and constructors based on their
+ modifiers and on negations of modifiers. For example, you can
+ say:
<orderedlist>
<listitem>
<para>
@@ -494,23 +522,27 @@ pointcut ioHandler(): within(MyClass) && handler(IOException);
</listitem>
</orderedlist>
- which means (1) all invocation of public methods, (2) all
- executions of non-static methods, and (3) all signatures of
- the public, non-static methods.
+ 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>
- Designators can also deal with interfaces. For example, given the
+ Pointcuts can also deal with interfaces. For example, given the
interface </para>
- <programlisting><![CDATA[
-interface MyInterface { ... }]]></programlisting>
+<programlisting><![CDATA[
+interface MyInterface { ... }
+]]></programlisting>
- <para> the designator <literal>call(* MyInterface.*(..))</literal>
- picks out the call join points for methods defined by the interface
- <literal>MyInterface</literal> (or its superinterfaces).
+ <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>
@@ -528,55 +560,64 @@ interface MyInterface { ... }]]></programlisting>
<para>
AspectJ exposes these times as call and execution join points,
- respectively, and allows them to be picked out specifically by call and
- execution pointcuts.
+ 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 times? Well, there are a number
- of differences:
+ 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 text is that of the call site. This means that
- This means that <literal>call(void m()) <![CDATA[&&]]> within(void m())</literal>
- will only capture recursive calls, for example. At an execution join
- point, however, the control is already executing the method.
+ 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.
+ 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, pick an execution, but if you want
- to pick one that runs when a particular signature is called, pick a
- call.
+ 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>
<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 cflow and cflowbelow. Here's an example:
+ <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
- the join points in the control flow of the join points picked out by
- <replaceable>P</replaceable>. So, pictorially:
+ <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>
@@ -587,11 +628,12 @@ interface MyInterface { ... }]]></programlisting>
</programlisting>
- <para>What does <literal>cflow(<replaceable>P</replaceable>) &amp;&amp;
- cflow(<replaceable>Q</replaceable>)</literal> pick out? Well, it picks
- out those join points that are in both the control flow of
- <replaceable>P</replaceable> and in the control flow of
- <replaceable>Q</replaceable>. So...
+ <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>
@@ -607,15 +649,18 @@ interface MyInterface { ... }]]></programlisting>
\ \
</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>
+ 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> picked out by <replaceable>Q</replaceable>.
+ <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>
@@ -625,21 +670,24 @@ interface MyInterface { ... }]]></programlisting>
\
</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>
+ 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>
+ Here's some code that expresses this.
</para>
<programlisting><![CDATA[
public class Test {
public static void main(String[] args) {
foo();
- }
+ }
static void foo() {
goo();
}
@@ -649,7 +697,6 @@ public class Test {
}
aspect A {
-
pointcut fooPC(): execution(void Test.foo());
pointcut gooPC(): execution(void Test.goo());
pointcut printPC(): call(void java.io.PrintStream.println(String));
@@ -661,17 +708,18 @@ aspect A {
before(): cflow(fooPC() && gooPC()) && printPC() {
System.out.println("should not occur");
}
-
}
]]></programlisting>
</sect2>
+<!-- ============================== -->
+
<sect2>
<title>Pointcut Parameters</title>
<para>
- Consider, for example, the first pointcut you've seen here,
+ Consider again the first pointcut definition in this chapter:
</para>
<programlisting><![CDATA[
@@ -681,13 +729,14 @@ aspect A {
]]></programlisting>
<para>
- As we've seen before, the right-hand side of the pointcut picks out the
- calls to <literal>setX(int)</literal> or <literal>setY(int)</literal>
- methods where the target is any object of type
- <literal>Point</literal>. On the left-hand side, the pointcut is given
- the name "setters" and no parameters. An empty parameter list means
- that when those events happen no context is immediately available. But
- consider this other version of the same pointcut:
+ 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[
@@ -697,13 +746,15 @@ aspect A {
]]></programlisting>
<para>
- This version picks out exactly the same calls. But in this version, the
- pointcut has one parameter of type <literal>Point</literal>. This means
- that when the events described on the right-hand side happen, a
- <literal>Point</literal> object, named by a parameter named "p", is
- available. According to the right-hand side of the pointcut, that
- <literal>Point</literal> object in the pointcut parameters is the
- object that receives the calls.
+ 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>
@@ -718,16 +769,19 @@ aspect A {
]]></programlisting>
<para>
- This pointcut also has a parameter of type <literal>Point</literal>.
- Similarly to the "setters" pointcut, this means that when the events
- described on the right-hand side happen, a <literal>Point</literal>
- object, named by a parameter named "p", is available. 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 (of type Point) passed to the "equals" method on some other
- target Point object. If we wanted access to both objects, then the pointcut
- definition that would define target <literal>Point p1</literal>
- and argument <literal>Point p2</literal> would be
+ 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[
@@ -737,7 +791,7 @@ aspect A {
]]></programlisting>
<para>
- Let's look at another variation of the "setters" pointcut:
+ Let's look at another variation of the <literal>setters</literal> pointcut:
</para>
<programlisting><![CDATA[
@@ -748,49 +802,47 @@ pointcut setter(Point p, int newval): target(p) &&
]]></programlisting>
<para>
- In this case, a <literal>Point</literal> object and an integer value
- are available when the calls happen. Looking at the events definition
- on the right-hand side, we find that the <literal>Point</literal>
- object is the object receiving the call, and the integer
- value is the argument of the method .
+ 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 definition of pointcut parameters is relatively flexible. The most
- important rule is that when each of those events defined in the
- right-hand side happen, all the pointcut parameters must be bound to
- some value. So, for example, the following pointcut definition will
- result in a compilation error:
- </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 xcut(Point p1, Point p2):
+ pointcut badPointcut(Point p1, Point p2):
(target(p1) && call(void setX(int))) ||
(target(p2) && call(void setY(int)));
]]></programlisting>
- <para>
- The right-hand side establishes that this pointcut picks out the call
- join points consisting of the <literal>setX(int)</literal> method
- called on a point object, or the <literal>setY(int)</literal> method
- called on a point object. This is fine. The problem is that the
- parameters definition tries to get access to two point objects. But
- when <literal>setX(int)</literal> is called on a point object, there is
- no other point object to grab! So in that case, the parameter
- <literal>p2</literal> is unbound, and hence, the compilation error.
+ 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>
<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>
+ 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 {
@@ -824,17 +876,19 @@ pointcut setter(Point p, int newval): target(p) &&
]]></programlisting>
</sect2>
-
</sect1>
- <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:
+ 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[
@@ -866,6 +920,11 @@ pointcut setter(Point p, int newval): target(p) &&
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;
@@ -873,8 +932,9 @@ pointcut setter(Point p, int newval): target(p) &&
]]></programlisting>
<para>
- This before advice runs just before the execution of the actions
- associated with the events in the (anonymous) pointcut.
+ 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[
@@ -884,9 +944,10 @@ pointcut setter(Point p, int newval): target(p) &&
]]></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.
+ 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[
@@ -896,10 +957,11 @@ pointcut setter(Point p, int newval): target(p) &&
]]></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.
+ 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[
@@ -909,11 +971,10 @@ pointcut setter(Point p, int newval): target(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.
+ 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[
@@ -924,146 +985,167 @@ void around(Point p, int x): target(p)
p.releaseResources();
}
]]></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>
-
</sect1>
- <sect1>
- <title>Introduction</title>
+<!-- ============================== -->
+
+ <sect1 id="language-interType">
+ <title>Inter-type declarations</title>
<para>
- Introduction declarations add whole new elements in the given types, and
- so change the type hierarchy. Here are examples of introduction
+ 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>
- <para>
- This privately introduces a field named <literal>disabled</literal> in
- <literal>Server</literal> and initializes it to
- <literal>false</literal>. Because it is declared
- <literal>private</literal>, only code defined in the aspect can access
- the field.
+ 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 x; }
+ public int Point.getX() { return this.x; }
]]></programlisting>
- <para>
- This publicly introduces a method named <literal>getX</literal> in
- <literal>Point</literal>; the method returns an <literal>int</literal>,
- it has no arguments, and its body is return <literal>x</literal>.
- Because it is defined publically, any code can call it.
+ 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>
- This publicly introduces a constructor in Point; the constructor has
- two arguments of type int, and its body is this.x = x; this.y = y;
</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>
- <para>
- This publicly introduces a field named x of type int in Point; the
- field is initialized to 0.
+ 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>
- <para>
- This declares that the <literal>Point</literal> class now implements the
- <literal>Comparable</literal> interface. Of course, this will be an error
- unless <literal>Point</literal> defines the methods of
- <literal>Comparable</literal>.
+ 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>
- This declares that the <literal>Point</literal> class now extends the
- <literal>GeometricObject</literal> class.
</para>
<para>
- An aspect can introduce several elements in at the same time. For
- example, the following declaration
- </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>
- <para>
- publicly introduces both a field and a method into class
- <literal>Point</literal>. Note that the identifier "name" in the body of
- the method is bound to the "name" field in <literal>Point</literal>, even
- if the aspect defined another field called "name".
+ 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>
- One declaration can introduce several elements in several classes as
- well. For example,
- </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[
- public String (Point || Line || Square).getName() { return name; }
+ aspect A {
+ private interface HasName {}
+ declare parents: (Point || Line || Square) implements HasName;
+
+ private String HasName.name;
+ public String HasName.getName() { return name; }
+ }
]]></programlisting>
- <para>
- publicly introduces three methods, one in <literal>Point</literal>,
- another in Line and another in <literal>Square</literal>. The three
- methods have the same name (getName), no parameters, return a String, and
- have the same body (return name;). The purpose of introducing several
- elements in one single declaration is that their bodies are the same. The
- introduction is an error if any of <literal>Point</literal>,
- <literal>Line</literal>, or <literal>Square</literal> do not have a
- "name" field.
+ 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>
- An aspect can introduce fields and methods (even with bodies) onto
- interfaces as well as classes.
+ 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>
- <title>Introduction Scope</title>
+ <title>Inter-type Scope</title>
<para>
- AspectJ allows private and package-protected (default) introduction in
- addition to public introduction. Private introduction means private in
+ 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 introduction of a field on a type
- </para>
+ aspect makes a private inter-type declaration of a field
<programlisting><![CDATA[
private int Foo.x;
]]></programlisting>
- <para>
- Then code in the aspect can refer to Foo's x field, but nobody else
- can. Similarly, if an aspect makes a package-protected
- introduction,
+ 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[
@@ -1071,22 +1153,27 @@ void around(Point p, int x): target(p)
]]></programlisting>
<para>
- then everything in the aspect's package (which may not be Foo's
- package) can access x.
+ 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>
<title>Example: <literal>PointAssertions</literal></title>
+
<para>
The example below consists of one class and one aspect. The aspect
- introduces all implementation that is related with assertions of the
- class. It privately introduces two methods in the class Point, namely
- assertX and assertY. It also advises the two set methods of Point with
- before declarations that assert the validity of the given values. The
- introductions are made privately because other parts of the program
- have no business accessing the assert methods. Only the code inside of
- the aspect can call those methods.
+ 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[
@@ -1124,27 +1211,29 @@ void around(Point p, int x): target(p)
}
]]></programlisting>
- </sect2>
+ </sect2>
</sect1>
<!-- ================================================== -->
- <sect1>
- <title>Reflection</title>
+ <sect1 id="language-thisJoinPoint">
+ <title>thisJoinPoint</title>
<para>
- AspectJ provides a special reference variable, thisJoinPoint, that
- contains reflective information about the current join point for the
- advice to use. The thisJoinPoint variable can only be used in the context
- of advice, just like this can only be used in the context of non-static
- methods and variable initializers. In advice, thisJoinPoint is an object
- of type JoinPoint.
+ 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,
- thisJoinPoint has a toString() method that makes quick-and-dirty tracing
- easy.
+ 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[
@@ -1156,33 +1245,29 @@ void around(Point p, int x): target(p)
]]></programlisting>
<para>
- The type of thisJoinPoint includes a rich reflective class hierarchy of
- signatures, and can be used to access both static and dynamic information
- about join points. If, however, only the static information about the
- join point (such as the Signature) is desired, a lightweight join-point
- object is available from the thisJoinPointStaticPart special variable.
- This object is the same object you would get from
- </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.getStaticPart()
+ thisJoinPoint.getArgs()
]]></programlisting>
- <para>
- The static part of a join point does not include dynamic information,
- such as the arguments, which can be accessed with
- </para>
+ 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.getArgs()
+ thisJoinPoint.getStaticPart()
]]></programlisting>
- <para>
- But it has the performance benefit that repeated execution of the code
- containing <literal>thisJoinPointStaticPart</literal> (through, for
- example, separate method calls) will not result in repeated construction
- of the reflective object.
+ 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
@@ -1199,13 +1284,12 @@ void around(Point p, int x): target(p)
<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
+ <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())
@@ -1213,12 +1297,4 @@ void around(Point p, int x): target(p)
]]></programlisting>
</sect1>
-
</chapter>
-
-<!-- Local variables: -->
-<!-- fill-column: 79 -->
-<!-- compile-command: "ant -quiet prog-html" -->
-<!-- sgml-local-ecat-files: progguide.ced -->
-<!-- sgml-parent-document:("progguide.xml" "book" "chapter") -->
-<!-- End: -->