Installation and Compilation
Damon distribution comes in the form of source code and a
precompiled binary JAR package. The downloadable version consists of a
ZIP
file which should be extracted to any directory. Damon comes
with a set of samples and JUnit testbed which can be executed to proof Damon's skills.
To execute these samples, you need at least Java5 JRE
v1.6.0. You will experience problems if you use prior versions because
the annotation functionalities were not available until JDK 1.5. However,
for run all instrumentation capabilities, it must be work over
Java6.
If you want to compile the sources, make sure you have
installed Jakarta ANT. You must change
to the ./bin directory in your Damon installation directory and execute the
following command:
ant
The next step is to edit the damon-config.xml
file located at the ./bin directory, and change the parameters
concerning bootstrap host, port, aspect framework to use, etc.
Running the
sample applications
There is a binary precompiled damon.jar file
contained in the ./lib directory which you should include in the
applications willing to use Damon.
Damon contains several sample applications which
demonstrate and test all of the functionalities in the middleware.
The instructions for running the different
included samples are as follows:
- Direct abstraction sample (damon.tutorial.direct)
This sample includes a simple sample. It
demonstrates the activation using direct abstraction.
1) Open a shell and run the host.
- run
damon.tutorial.direct.SimpleHost
2) Open a shell and run the deployer.
- run
damon.tutorial.direct.SimpleDeployer
- Distributed Meta-Aspect sample
(damon.tutorial.metapointcut)
This sample includes a distributed meta-aspect over the simple sample. It
tests the before, after, and around distributed meta-pointcuts.
1) Open a shell and run the host.
- run
damon.tutorial.metapointcut.SimpleHost
2) Open a shell and run the deployer.
- run
damon.tutorial.metapointcut.SimpleDeployer
- XML sample (damon.tutorial.xml)
This sample includes a simple sample. It demonstrates the use of
xml descriptor instead of annotations.
1) Open a set of shells and run the host.
- run
damon.tutorial.xml.simple.SimpleHost
2) Open a shell and run the deployer.
- run
damon.tutorial.xml.simple.SimpleDeployer
If you wish to code your aspects taking advantage of Damon
services, you should follow these simple steps:
- Add the corresponding annotation to aspect's classes :
import damon.annotation.*;
@DistributedAspect (abstraction =
Abstractions.MULTI, target = "p2p://chat.urv.cat")
public class DamonAspect {
@SourceHook(source
= "damon.samples.multihost.log.SourceHooks",
method = "preloadedCheck")
public Object aroundTask(JoinPoint joinPoint) throws Throwable {
...
}
Damon's annotations are explained in the next table :
Distributed Aspect and Activation
Annotation / Variable |
Type |
Definition |
@DistributedAspect |
Class |
Defines the kind of Damon distributed aspect
properties and activation |
abstraction
|
Value |
Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi
ones. |
num |
Value |
Only for many abstraction, where we can
specify the number of involved hosts. |
target |
Value |
peer-to-peer locator associated to specific host
or group of host |
@DamonRequirement |
Method |
Only in any/many abstraction, this
annotation can mark methods that return boolean values. When we
activate an aspect with requirements, the container uses them to
determinate if the host is successful to install it. |
- In any/many abstraction, we
can add a set of requirements to select the host to intercept using the
DamonRequirement annotation:
import damon.annotation.*;
@DistributedAspect
(abstraction = Abstractions.ANY, target = "p2p://calc.urv.cat")
public class DamonAspect {
@DamonRequirement
public boolean
checkHasFreeResources() {
...
}
Source Hook
Annotation / Variable |
Type |
Definition |
@SourceHook |
Method |
Defines the source hook local interception |
source |
Value |
pointcut definition class |
method
|
Value |
local advice method |
Remote Pointcut
Annotation / Variable |
Type |
Definition |
@RemotePointcut
|
Method |
Defines the remote pointcut properties and
propagation |
id
|
Value |
remote pointcut unique identifier |
abstraction
|
Value |
Determinates the abstraction type. We can choose
among local, direct, hopped, any, many or multi ones. |
num |
Value |
Only for many abstraction, where we can specify
the number of involved hosts. |
target |
Value |
peer-to-peer locator associated to specific host
or group of host |
Remote Advice
Annotation / Variable |
Type |
Definition |
@RemoteAdvice |
Method |
Defines the remote advice subscription |
id
|
Value |
subscribed remote pointcut unique identifier |
Remote Invocation
Annotation / Variable |
Type |
Definition |
@RemoteInvocation |
Method |
Defines the remote invocation properties and
propagation |
id
|
Value |
remote invocation unique identifier |
abstraction
|
Value |
Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi
ones. |
num |
Value |
Only for many abstraction, where we can
specify the number of involved hosts. |
target |
Value |
peer-to-peer locator associated to specific host
or group of host |
Remote Method
Annotation / Variable |
Type |
Definition |
@RemoteMethod |
Method |
Defines the remote method subscription |
id
|
Value |
subscribed remote invocation unique identifier |
- To use the aspect remoting services your
distributed aspect
must extend from AspectRemoting. Moreover, to start the invocations you can use the
invoke parent primitive.
@DistributedAspect (abstraction =
Abstractions.MULTI, target = "p2p://clockstation.urv.cat")
public class SynchroImpl extends
AspectRemoting
{
private
Hashtable<String,Long> times = new
Hashtable<String,Long>();
@RemoteAdvice (id = "time")
public void
valueArrived(RemoteJoinPoint rjp, Long value) { times.put(id,vale);
}
@RemotePointcut (id =
"time", abstraction = Abstractions.MULTI)
@SourceHook(source =
"damon.samples.invokation.synchro.SourceHooks", method = "getTime")
public Object aroundTask(JoinPoint joinPoint) throws Throwable {
long time = ((Long) joinPoint.proceed()).longValue();
invoke(Abstractions.MULTI, new
Long(time)); Collection<Long> c =
new Vector<Long>(times.values()); long avg = 0;
for(Long l : c) { avg+= l; }
if (c.isEmpty()) return time;
else { avg = avg/(c.size());
return new Long(avg); }
}
}
- Furthermore, to use the other services,
like reflection layer or persistence system, you must call the
thisEndPoint static object methods.
- The alternative, in order to allow
composition in runtime, is the use of equivalent XML descriptors. As
follow we present an esqueletor :
<distributed-aspect>
<name> </name>
<abstration> </abstraction>
<target> </target>
<state> </state>
<offered>
<name> </name>
<type>remote-pointcut</type>
<sourcehook>remote-pointcut
<source></source>
<method></method>
</sourcehook>
<id> </id>
<abstraction> </abstraction>
</offered>
<offered>
<name> </name>
<type>remote-invocation</type>
<id> </id>
<abstraction> </abstraction>
</offered>
<required>
<name> </name>
<type>remote-method</type>
<id> </id>
</required>
<required>
<name> </name>
<type>remote-advice</type>
<id> </id>
</required>
<meta-pointcut>
<name> </name>
<time> </time>
<target> </target>
<id> </id>
</meta-pointcut>
</distributed-aspect>
Remote Meta-Pointcut
Annotation / Variable |
Type |
Definition |
@RemoteMetaPointcut
|
Method |
Defines the distributed meta-pointcut hook |
id
|
Value |
subscribed remote pointcut unique identifier |
type
|
Value |
The
moment of the interception : Before, After or Around. |
target |
Value |
peer-to-peer locator associated to specific host
or group of host |
Remote Meta-Advice
Annotation / Variable |
Type |
Definition |
@RemoteMetaAdvice |
Method |
Defines the remote invocation properties and
propagation |
id
|
Value |
remote invocation unique identifier |
abstraction
|
Value |
Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi
ones. |
num |
Value |
Only for many abstraction, where we can
specify the number of involved hosts. |
target |
Value |
peer-to-peer locator associated to specific host
or group of host |
HOW TO USE Damon WITH OTHER Dynamic AOP Frameworks?
An aspect framework adaptation
layer has been created in Damon, so as it can be easily adapted to different
dynamic AOP frameworks. In our case, we have implemented Damon over AspectWerkz 2.0. In order to make Damon compatible with another runtime
aspect engine, you must implement a series of classes, which are detailed as
follows, showing Aspectwerkz's example:
Package |
Class |
Details |
damon.aspectwerkz |
HotDeployment DocumentCreator
AnnotationSwapper |
org.codehaus.aspectwerkz.transform.inlining.deployer.Deployer;
org.codehaus.aspectwerkz.transform.inlining.deployer.DeploymentHandler;
org.codehaus.aspectwerkz.annotation.*; |
damon.invokation.aspectwerkz |
AspectInvokeObserver
AspectRemoting |
org.codehaus.aspectwerkz.definition.Pointcut;
org.codehaus.aspectwerkz.joinpoint.JoinPoint; |
damon.metaaspect.aspectwerkz |
DistributedMetaAspect
MetaPointcutObserver |
org.codehaus.aspectwerkz.definition.Pointcut;
org.codehaus.aspectwerkz.joinpoint.JoinPoint; |
Finally, the package names must follow the same template.
For example, in our case we wanted to support Damon on top of Aspectwerkz,
we would implement the classes in packages as for example: damon.aspectwerkz or damon.messaging.aspectwerkz.
In order to use Damon with other dynamic aspect framework,
you must specify the package name (aspectwerkz in our case) in the
different configuration files we are using. For instance, damon-config.xml:
change the line "<entry key="damon.aspect.engine">aspectwerkz</entry>".
For example, messaging system needs to load (i.e. by a aop.xml file) the
damon.messaging.aspectwerkz.AspectObserver that extends
damon.messaging.aspectwerkz.AspectCommunicator. Note that run.bat batch file also will be changed to initiate another
aspect framework.
|
|
|