XAspects: Extensible Plug-ins for
Aspect-Oriented Programming
Design Specifications - ClassDictionary Plugin

Macneil Shonle
Ankit Shah
Version 1.1
12 March 2003

Download Source Code of ClassDictionary Plugin

public class ClassDictionary extends AspectPlugin{
    HashMap compileData;

    public ClassDictionary ();
    public void init (CompilationEnvironment ce);

    public void receiveBody(String aspectID, String[] keywords, String body);

    public File[] generateExternalInterfaces();
    public File[] generateCode(File[] classFiles);

    public void cleanup();

    private void cdProcessStep1 (String aspectID, String text);
    private void cdProcessStep2 (String aspectID, File grammarFile, File out, File err);

    private void processError1(String aspectID, Exception e);
    private void processError2 (String aspectID, Exception e, File out, File err);
    private void processFatalError (String aspectID, Error e);

    private File[] generatedFiles();
}

Constructors and Initialization

Since, parameterized constructors cannot be called, init is implemented to initialize the plugin so that it can have a reference to the CompilationEnvironment instance that helps communications during the proces. Since, no additional initialization is necessary, these methods pass on the calls to the corresponding methods of the super classes.

Implementing the receiveBody() method

No special pre-processing is necessary to the incoming code fragment. Hence, it is stored away in a HashMap with the corresponding aspectID as the key. It, however, does checks to see that keywords array is empty. If not it reports a warning stating that those keywords have no meaning and are ignored.

generateExternalInterfaces()

This is the only method that does all the compilation of the class dictionaries. Compilation of the class Dictionary is a two - step process, wherein first the class dictionary is processed to create classes and data members and in the second step a parser is generated to parse input data.
To capture all the messages generated by DAJ and ANTLR, output will be redirected to two different disk files before step 1 and restored after all the processing is completed in step 2. These files may later be analyzed for further errors and warnings.
Although no exceptions are thrown by these methods, runtime errors may be generated to due missing classes or libraries or packages. These are caught and processed to report errors and warnings to the CompilationEnvironment and also provide a smooth functioning of the plugin. These errors are passed on to processFatalError() for further processing and reporting.

Step 1:
For this step we leverage code from DAJ. The method DAJ.processClassDictionary(ClassGraph, String, File) seems the best candidate as this can process individual class dictionary, input in ANY format, to produce either the necesary output or report errors and warnings generated.
To generate the necessary inputs to this method, we invoke ClassGraph.fromString() method to convert the input string into a classgraph. Also from the input string, DAJ.getRootNode() to get the 2nd parameter, which is actually the root class in the whole class hierarchy defined by the classdictionary. For the third parameter, by the specification of AspectPlugin, working directory must be used.
This method returns a reference to a list of files generated, but it is of no use to us, since the protocal states that only an array of File objects that refer to .java files must be returned. Also, we need to do processing for the 2nd stage too.
Exceptions will be thrown if errors are found in the classDictionary. These exceptions are caught and passed on to processError1() method for further processing and reporting to the environment.

Step 2:
For this step too, we leverage code from DAJ. The method DAJ.generateParser(File grammar, File gendir) will parse the input .g file to generate classes that will parse input for that class dictionary
The first parameter, which is a reference to the grammar .g file for the current aspect, can be generated by exploiting a certain DAJ feature for naming files. For an input ClassDictionary by the name abc, DAJ generates a corresponding abc.g grammar file. In case of this plugin, name of the plugin is the aspectID. Thus, the grammar file becomes <aspectID>.g.
For the second parameter, by the specification of AspectPlugin, working directory must be used.
This method too returns a reference to a list of files generated, but it is of no use to us, since the protocal states that only an array of File objects that refer to .java files must be returned. Besides, we also wish to check the redirected output / error files to check for possible warnings.
Exceptions may be thrown if errors are found in the classDictionary grammar. These exceptions are caught and passed on to processError2() method for further processing and reporting to the environment.

Returning Calls
Invoke method generatedFiles() to return the list of .java Files in the working Directory. Return that list.

generateCode()

All the work to process a ClassDictionary has been done in the previous call. So simply return the list returned by generatedFiles()

cleanup()

No specific cleanup to be done. As per AspectPlugin requirements, call cleanup of superclass.

Helper Methods

Error Processing Methods

processError1()

This method deals with all the errors generated during step 1 above. These errors are all exceptions. The exception is decoded to extract the line number of error. Note that this number is relative to the aspect. The aspectID is provided by step 1.
Using these, it reports the error Message, line number and aspectID to the CompilationEnvironment.

processError2()

This method deals with all the errors generated during step2 above. It deals mostly with ANTLR, which, in most cases, generates warnings. This method reads the file that received messages redirected from Standard error and reports them as warnings to the CompilationEnvironment.

processFatalError()

This method deals with all the errors generated due to missing files / classes / packages / libraries.
In this case, the line number is not required. Only the missing class name and the aspectID is used to report the error to CompilationEnvironment

generatedFiles()

This method scans the working Directory for all .java files, collects them in an array of File objects are returns the array. It returns null if no .java files are found

References

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

DAJ API, < http://daj.sourceforge.net/api/edu/neu/ccs/demeter/tools/daj/DAJ.html>.

Class Dictionary Syntax, <http://www.ccs.neu.edu/research/demeter/software/docs/UserManual/node2.html>.

Author: Ankit Shah. Copyright © 2003. All rights reserved.