Out Of My Comfort Zone

Pratibha Malhotra's Weblog
All | Java | Personal | SOA/BI | Sun
« Java@FOSS - 2006 | Main | Trails of Java »

20061130 Thursday November 30, 2006

Javac Demo@FOSS-2006 - Your first (Hello World) Annotation Processor

FOSS is over and what an enriching and memorable experiance it was!!
Open JDK booth was one of the most sought after booth at FOSS. Our team came across all kind of visitors right from students, Java developers to open source contributers.
Java Compiler being opensourced recently, we showcased Demo around it.

Open Source JDk as of today contains below-mentioned components of the JDK -
> The HotSpot Virtual Machine
> The Java programming-language compiler(Javac)

The Java programming-language compiler (javac)
javac, compiles Java source code into bytecode. It can also process annotations found in source and class files using the Pluggable Annotation Processing API.

APIs of javac
> Java Compiler API.
> Pluggable Annotation Processing API.
> The Tree API



Writing your first (Hello World) Annotation Processor

Annotation processing is a form of meta-programming. Meta-Programming is based on the structure of a program.

Below is the code for a "Hello World" annotation processor - It traverse through user's Java Program and give user control over code at compile time.
> Annotation processors are run by javac before the input source files are compiled.
> Your Annotation Processor must implement javax.annotation.processing.Processor. Another convenient option is to extend javax.annotation.processing.AbstractProcessor.
> You can write Processors as per need of your Project.
for eg. A processor to point out empty-catch in your code. (Leaving Catches empty can be proved fatal at times)
Similarly Processors can be written to put a check on
        > Unused Variables
        > For, While Loops
        > Imports
        > Continue/return statement
        > Arrays
        > try/catch/throws
        > if/else
        > expressions etc ................ :)


import java.io.*;
public class TestClass {
public static void main(String args[]) {
prats: { System.out.println("Hello World");
}
test: { System.out.println("Good Bye");
}
}
}


import java.util.*;
// import all JSR 199, JSR 269 and Tree API stuff
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.tools.*;
import com.sun.source.tree.*;
import com.sun.source.util.*;
// An annotation processor that processes all classes
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class TestProcessor extends AbstractProcessor {
private Trees treeUtils;
public void init(ProcessingEnvironment pe) {
super.init(pe);
treeUtils = Trees.instance(pe);
}
public boolean process(Set annotations, RoundEnvironment roundEnv) {
Messager messager = processingEnv.getMessager();
if (! roundEnv.processingOver()) {
Set elements = roundEnv.getRootElements();
note(" >>>>>> Traversing Starts Here .....");
for (Element e: elements) {
Tree tree = treeUtils.getTree(e);
if (tree.getKind().equals(Tree.Kind.CLASS)) {
verify((ClassTree)tree);
}
}
}
else{
note(" >>>>>> Traversing Ends Here .....");
}
return true;
}
// verify each class tree
private void verify(ClassTree ct) {
ct.accept(new TreeScanner() {
private String currentClass, currentMethod;
public Object visitClass(ClassTree node, Void v) {
currentClass = node.getSimpleName().toString();
note("Class >>> "+currentClass);
return super.visitClass(node, v);
}
public Object visitMethod(MethodTree node, Void v) {
currentMethod = node.getName().toString();
note("Method >>> "+currentMethod);
return super.visitMethod(node, v);
}
public Object visitLabeledStatement(LabeledStatementTree node, Void v) {
Name labelName = node.getLabel();
note("Statement >>> "+labelName.toString());
StatementTree statementName = node.getStatement();
return super.visitLabeledStatement(node, v);
}
}, null);
}
private void note(String msg) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
}

}


Compile time Output
 
Compiletime Output

Runtime Output
 
Runtime Output

In order to Compile TestProcessor.java - javac -classpath $JDK_HOME/lib/tools.jar TestProcessor.java

To use your Annotation Processor - javac -processor TestProcessor TestClass.java
Output as shown in above image would be
Note: >>>>>> Traversing of Tree Starts Here .....
Note: Class >>> TestClass
Note: Method >>> init
Note: Method >>> main
Note: Label Statement >>> prats
Note: Label Statement >>> test
Note: >>>>> Traversing of Tree Ends Here .....

To run TestClass - java TestClass
Output as shown in above image would be
Hello World
Good Bye

Posted by prats ( Nov 30 2006, 07:28:26 AM PST ) Permalink Comments [0]

Trackback URL: http://blogs.sun.com/prats/entry/javac_demo%40foss-2006
Comments:

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.

                                                                                                                                              hits since September 21, 2006