that share common characteristics. Three wildcard
notations are available in AspectJ:
1. * means any number of characters except
the period.
2. .. means any number of characters
including any number of periods.
3. + means any subclass or sub-interface of a
given type.
Just like in Java, AspectJ provides a unary
negation operator (!) and two binary operators (|| and
&&) to form complex matching rules by combining
simple pointcuts. The negation operator ! allows the
matching of all join points except those specified by
the pointcut. Combining two pointcuts with the ||
operator causes the selection of join points that
match at least one of the pointcuts, while combining
them with the && operator causes the choice of join
points matching both the pointcuts.
2.2 Aspect Tracer
We defined the AspectTracer aspect to collect
information for building the sequence diagrams in
the UML2 model. In our approach a scenario is
associated with a test-case, thus a use case can be
related with a set of test-cases. Automated tests
written with JUnit act like a sort of specification of
scenarios.
Here we describe an example of AspectTracer
created for the ‘Foo’ case study.
Looking at the AspectTracer’s source code (see
Figure 1), the second line specifies the aspect name
following the AspectJ syntax. An aspect is
composed by a set of pointcuts and a set of advices.
In the aspect several pointcuts are defined and
named, in order to identify different sets of join
points in the application code; these pointcuts can
then be composed with logical operators to define
more complex pointcuts.
In order to identify these join-points, each advice
is related to one named pointcut, specifying a
particular set of join-points in the application code:
for example, whenever the related pointcut In the
aspect there are four advices of type before, used to
execute some code right before the identified join-
point, and one advice of type after, used to execute
some code right after the join-point. Each advice
contains, enclosed between braces, the additional
code that is inserted at the specified join-points
during the weaving process, at compile-time.
For example, test() matches a join-point in the
application, the advice of type before(), at line 19, is
executed immediately before the join-point.
The methodCalls() pointcut at line 9 in figure 1
can be read like this: ‘all the method calls defined in
whichever package, for whichever class, whichever
method, and whichever return value; moreover the
wildcard “..” used between method’s parenthesis,
matches whichever list of types for formal
parameters.
In the same way (see line 7) we intercept all calls
to constructor methods, identified by the keyword
‘new’.
Now we need to limit the scope to the ‘foo’
package, containing our case study to be inspected:
we define the targetPackage() pointcut to identify
all the join-points of our target application. This
pointcut relies on the AspectJ pointcut within()
which identifies all the join-points defined in the
source code of classes matching the type pattern
defined between parenthesis. For example,
“within(foo..*)” matches whichever string starting
with “foo” and followed by a string including
periods: this identifies all the join-points defined in
package “foo” and in all its sub-packages.
Wildcards are very powerful but the extensive
usage made by methodCalls() pointcut, leads to pick
up undesired join-points; thus, we need to define the
boundary() pointcut (see line 12) to describe all join-
points we want to exclude from tracing.
In particular, in order to avoid infinite recursion,
we defined the instrumentation() pointcut, which
excludes all the join points occurring inside our
instrumentation code, i.e. the AspectTracer’s body
and the related Tracer class. Moreover, we use the
init() pointcut to exclude the calls to initialization
methods, transparently inserted in bytecode during
compilation, and occurring whenever a new object is
created and its fields are initialized. Finally the
callSet() pointcut (at line 15) represents the method
calls we are interested to trace.
Whenever a method of a class in the “foo”
package is called the related ‘before()’ advice (at
line 22) is executed immediately before the join-
point: this advice simply store the caller object
reference. The keyword thisJoinPoint is, for an
aspect, what the keyword this is for Java language,
but, instead of returning the current executing object,
it returns the current join-point reached along the
execution. The getThis() method returns the
reference of the currently executing object, advised
by this aspect.
A DYNAMIC ANALYSIS TOOL FOR EXTRACTING UML 2 SEQUENCE DIAGRAMS
173