XAspects: Extensible Plug-ins for
Aspect-Oriented Programming
Functional Specification+

Macneil Shonle
Ankit Shah
Version 1.1
6 March 2003

1 Introduction

XAspects is a tool and a library focused on the integration of domain-specific aspect-oriented solutions into AspectJ. The key idea behind this integration is to translate domain-specific aspects at compile time into general AspectJ source code. In this way, AspectJ serves as a base language from which other aspects can be defined. Traversals are the primary focus of the domain-specific aspects implemented for the project, though the plug-in mechanism is general enough to be useful for supporting other domains. See the project's home page at <http://www.ccs.neu.edu/research/demeter/xaspects> for more information about XAspects.

2 Imported Interfaces

The XAspects project requires the interfaces provided by the following Java libraries. Because each library has unique licenses the user of XAspects will need to have all of these libraries downloaded and installed before use.

Name

Version

License

Redistributable

Source

ANTLR (antlr.jar)

2.7.2

public domain*

Yes

http://antlr.org

DJ (rt.jar)

0.8.6

Northeastern U.

If no charge is levied

http://www.ccs.neu.edu/
research/demeter/DJ

DAJ (daj.jar)

5

MPL 1.1

Yes

http://daj.sourceforge.net

AspectJ (aspectjtools.jar, aspectjrt.jar)

1.1 beta4

Common Public Licence

Yes

http://eclipse.org

* The ANTLR Software Rights states that credit for the ANTLR project should be provided.

3 Exported Interfaces

The XAspects project introduces internal changes to the AspectJ compiler and introduces a new library containing plug-in aspects.

Name

Reference

AspectJ changes*

This document. Section 4.1.

XAspects Library (xaspects.jar)

This document. Section 4.2.

* The initial prototype implementation will deliver a wrapper around AspectJ instead of modifying the AspectJ sources.

4 Deliverables

4.1 AspectJ Changes

The AspectJ compiler is extended to allow the use of domain-specific aspects in all source files. The following grammar rules represent the changes to the AspectJ compiler's external interface:

  <Aspect>          ::= ["privileged"] [<Modifiers>]
                        "aspect" "(" <Type> ")" <Id>
                        ["extends" <Type>] ["implements" <TypeList>]
                        "{" [<BalancedCurlies>] "}"
  <BalancedCurlies> ::= <BCText> [<BalancedCurlies>]
  <BCText>          ::= <BCToken> | "{" [<BalancedCurlies>] "}"
  <BCToken>         ::=  all Java tokens except for '{' and '}'

Here, <Aspect> is the grammar rule for an aspect definition and the rule specified above is an additional form the rule can take. The new <Aspect> rule has a <Type> in parenthesis after the aspect keyword and a body that contains any combination of Java tokens that produce balanced curlies. When an aspect of the above form is parsed the following operations are performed:

  1. The AspectJ compiler finds the class specified by the matched <Type>. The AspectJ compiler checks the current class-path to find the correct class (import statements affect which class is found in the case of an ambiguity). The package edu.neu.ccs.xaspects is searched if the class cannot be found otherwise.

  2. An instance of the class is constructed (or obtained if already constructed). The class must be a subclass of the AspectPlugin class (see Section 4.2). A CompilationEnvironment (see Section 4.2) is passed to the plug-in's constructor. Each AspectPlugin has only one instance associated with it, no matter how many times the plug-in's aspect type is used to define plug-in specific aspects. (For example, there could be multiple ClassDictionary aspects in the user's source code, but only one instance of the ClassDictionary plug-in will exist.)

  3. The AspectJ compiler then provides the plug-in instance with a String representation of the tokens that match the <BalancedCurlies> rule by invoking the instance's receiveBody method. The name specified by the <Id> is also passed in the call to receiveBody.

The above three steps are performed for each aspect of the above syntactic form encountered. When the parsing is complete, the AspectJ compiler proceeds with the post-parsing steps:

  1. At some point after all receiveBody calls are made to each plug-in, the generateExternalInterfaces() method is invoked for each plug-in. The generateExternalInterfaces() methods return lists of generated source files. All new classes, methods or fields that the plug-in introduces for external use (i.e. to be used by the rest of the program) are specified during this phase. The classes and methods provided can be stubs with empty definitions.

  2. The AspectJ compiler then compiles the entire program with the files returned from generateExternalInterfaces() and constructs a ClassGraph object. This ClassGraph object is then passed to all plug-ins by invoking the generateCode() method. The generateCode() methods return lists of generated source files.

  3. The program is compiled again with the files returned from generateCode(). The files returned from generateExternalInterfaces() will not be compiled at this step (replacement definitions for the stubs should be provided by the plug-in's generateCode() method; if the definitions returned from generateExternalInterfaces() were complete the same list of files can be returned again).

  4. Finally, the cleanUp method is invoked on all plug-ins.

During any of the calls to receiveBody, generateExternalInterfaces and generateCode the plug-in can report errors and warnings using the interface provided by the CompilationEnvironment class.

4.2 Plug-ins

The AspectJ compiler interacts with the plug-in aspects via the abstract AspectPlugin class and the concrete CompilationEnvironment class as described in section 4.1. Here are outline definitions for each class:

    class CompilationEnvironment {
        // methods that a plug-in can call:
        public void reportError(int line, String mesg, String fromAspectID);
        public void reportWarning(int line, String mesg, String fromAspectID);

        // methods called by ajc:
        public void mapAspect(String aspectID, File file, int startingLine);
        public int getNumErrors(String fromAspectID);
        public int getNumWarnings(String fromAspectID);
        public Iterator getErrors();
        public Iterator gerWarnings();
    }

    abstract class AspectPlugin {
        public AspectPlugin(CompilationEnvironment ce);

        abstract void recieveBody(AspectInfo ai, String aspectID, String body);
        abstract File[] generateExternalInterfaces();
        abstract File[] generateCode(ClassGraph cg);
        abstract void cleanUp();
    }

Four subclasses of AspectPlugin as well as the AspectPlugin class and the CompilerationEnvironment class are packaged into xaspects.jar, using the path edu.ccs.neu.xaspects. The four subclasses of AspectPlugin are ClassDictionary, Traversal, TraversalAdvice, and AspectJ--described in the following sections.

4.2.1 Class Dictionary Plug-in

The class dictionary plug-in implements the same functionality found in DAJ's *.cd files. The classes and support code for a class dictionary are all generated from the aspect body (i.e. the code supplied in the recieveBody call) during the generateExternalInterfaces phase. The generateCode phase returns the same files returned from the generateExternalInterfaces phase.

The name of the class that implements the AspectPlugin interface for class dictionaries is called ClassDictionary.

4.2.2 Traversal Plug-in

The traversal plug-in implements the same functionality found in DAJ's *.trv files. The aspects and support code for traversals are generated during the generateCode phase. The generateExternalInterfaces method returns a list of stubs for the new methods introduced.

The name of the class that implements the AspectPlugin interface for traversals is called Traversal.

4.2.3 Traversal Advice Plug-in

The TraversalAdvice plug-in is a utility plug-in to enforce correct implementation of visitor classes, as used in DAJ. The class is generated during the generateExternalInterfaces phase. The generateCode phase returns the same files returned from the generateExternalInterfaces phase.

The name of the class that implements the AspectPlugin interface for traversal advice is called TraversalAdvice.

4.2.4 AspectJ Plug-in

The AspectJ plug-in is a plug-in included for completeness, as a way to access AspectJ-style aspects using the new notation. The aspect is generated during the generateExternalInterfaces phase. The generateCode phase returns the same files returned from the generateExternalInterfaces phase.

The name of the class that implements the AspectPlugin interface for traversal advice is called AspectJ.

5 Testing+

6 Future Work+

More plug-in aspects can be created after the initial prototype implementation of XAspects. These new plug-ins can be distributed as part of the xaspects.jar library (see Section 4.2). Future work can include

7 References

XAspects Project Home Page, <http://www.ccs.neu.edu/research/demeter/xaspects>.