Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

NetBeans 6: Matisse Updates

NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed.

Introduction to Groovy Part 3

In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.

Easier Custom Components with Swing Fuse

Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.

Benchmark Analysis: Guice vs Spring

Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Replies: 4 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

Mustang: Compile Programmatically with the JSR-199 Compiler API

At 9:58 PM on Aug 28, 2005, R.J. Lorimer wrote:

As of Build 47 of the Mustang Java 6 JDK Project , the JSR 199 Compiler API has been included, and is available for early-access use. I want to give everyone a little glimpse of the API - I say 'little glimpse' because the API is still a fluid target. Just as an example, the early draft release which was complete in mid August is already quite different from what is available in the current as-of-this-writing (build 49) build of Mustang.

Ok, so I've given you the warning; the usual disclaimer - things are still moving around. That being said, a lot of the core concepts and classes will at least be fairly solid. So here is a peek.

Getting Started

To get started, you need to have the tools.jar in the classpath of your application. The tools.jar is located in the lib folder of the JDK.

The compiler APIs are provided through the javax.tools.ToolProvider class. This class dishes out javax.tools.Tool objects. As is now, the tool provider API only has facilities to work with compiler-style tools, but, it is designed to be able to extend to other standardized tool APIs. The interface we are interested in today, however, is javax.tools.JavaCompilerTool - which is an extension of the javax.tools.Tool interface, and as you can guess, it represents a compiler implementation.

Current State Side Note

Note that the tool provider has a very simple API, but unfortunately doesn't seem to work as expected. For instance:

System.out.println("Default Compiler: " + ToolProvider.defaultJavaCompiler().getClass().getName());
for (JavaCompilerTool compiler : ToolProvider.installedTools(JavaCompilerTool.class)) {
     System.out.println("Compiler: " + compiler.getClass().getName());
}

... this code block, according to the documentation, should print out:

Default Compiler: com.sun.tools.javac.api.Tool
-- Installed Compilers --
Installed Compiler: com.sun.tools.javac.api.Tool

Interestingly enough, it simply prints out this:

Default Compiler: com.sun.tools.javac.api.Tool
-- Installed Compilers --

The tool provider doesn't seem to have the default compiler listed as an 'installed' compiler - I don't know why; I have to assume it's a bug.

Using the JavaCompilerTool API

The JavaCompilerTool interface is meant to provide a standard API that allows you to invoke a compiler implementation using standard APIs, but also allows for implementation-specific hooks if at all necessary. Here is a basic example:

compiler.setOutputDirectory(new File("c:/temp2/output"));
boolean success = compiler.run(
	compiler.getStandardFileManager(), 
	new ExampleDiagnosticListener(), 
	new PrintWriter(System.out), 
	"c:/temp2/source/com/javalobby/tnt/mustang/compile/ClassA.java"
);

First note that I am calling a method on the compiler to set the output directory. This is previously done via the command-line by using the -d flag - now it can be called via API! There are three run methods available; I chose the most straightforward for this example. The first argument is of type JavaFileManager , and is an abstract representation of a 'filesystem' - it could be in-memory, across a socket, or on the actual filesystem; but the tool api allows for the actual source-code to be compiled to come from an implementation of your choosing. Incidentally, the demos that ship with the JSR 199 API (while being a little outdated) have an example of an in-memory compile-from-string example. In the case above, I simply ask for the standard file manager, which works with the local drive system. The second argument is an implementation of javax.tools.DiagnosticListener . This provides a way to receive compile failure events - I'll get to this shortly. The third argument is an output for the compiler implementation. Sun's default implementation doesn't seem to print anything out to this; they recommend using System.out if you don't desire to provide your own. Finally, the last argument is actually a String[] (in the code example above, varargs are in action), and represents the various arguments to the compiler.

Listening for Errors

The DiagnosticListener interface provides a facility for listening for errors from the compiler. Here is a sample diagnostic listener:

private static class ExampleDiagnosticListener implements DiagnosticListener {
	public void report(DiagnosticMessage message) {
		StringBuffer messageString = new StringBuffer()
		.append("Key: ").append(message.getKey()).append('\n')
		.append("Kind: ").append(message.getKind()).append('\n')
		.append("Position: ").append(message.getPosition()).append('\n')
		.append("Start Position: ").append(message.getStartPosition()).append('\n')
		.append("End Position: ").append(message.getEndPosition()).append('\n')
		.append("Source: ").append(message.getSource());
		System.out.println(messageString);			
	}
}

Here is an example error from having an unfinished method signature:

Key: compiler.err.expected
Kind: ERROR
Position: 186
Start Position: 186
End Position: 187
Source: c:\temp2\source\com\javalobby\tnt\mustang\compile\ClassB.java

I have no idea currently where the available keys are documented; although I think they are probably allowed to be different for each compiler. If anyone has any information, I'll be interested to know!

Bending the Rules - Implementation-Specific Options

The demos provided with the JSR 199 download provide some clues into how to hook options into the compiler. You can, of course, add them as part of the String[] used above, but you can also use programmatic hooks to set options:

// Get a compiler tool
JavaCompilerTool compiler = ToolProvider.defaultJavaCompiler();
compiler.setExtendedOption("-Xlint:all"); // report all warnings
compiler.setOption("-g:none"); // don't generate debug info

Well, that's all I've got for now - I'm looking forward to hear what other people have learned about this.

R.J. Lorimer
Contributing Editor - rj -at- javalobby.org
Author              - http://www.coffee-bytes.com
Software Consultant - http://www.crosslogic.com

1 . At 4:56 PM on Nov 16, 2005, Jason wrote:
  Click to reply to this thread Reply

Re: Mustang: Compile Programmatically with the JSR-199 Compiler API

I am curious about how you think this is helpful for the Java community outside of IDE providers?

Back in the day, sure, I'd write a java program and pop open a command prompt and type javac all day long. Now with Eclipse, everything is basically built as I type, and with Ant my entire source tree is built for our builds.

I'm not saying this is not valuable, because for certain the Eclipse team could put this to use potentially, or if I were writing my own IDE. But I'm trying to figure out a good use for this outside of those groups and I'm coming up blank.

Who pushed for this? Did this receive a bunch of votes on the Sun bugs site, or is this something they just decided was overdue? Curious to hear your thoughts...

The biggest benefit I see for this is the javax.tools package it comes in, which is a really nice framework for creating add-on tools (plugins) for software packages.
2 . At 3:39 AM on Jan 27, 2006, Thomas Darimont wrote:
  Click to reply to this thread Reply

Re: Mustang: Compile Programmatically with the JSR-199 Compiler API

Hello,

a concrete example for the Java Compiler API could look like this:
/**
  * 
  */
 package de.tutorials.mustang;
 
 import java.io.File;
 import java.io.Writer;
 
 import javax.tools.JavaCompilerTool;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.ToolProvider;
 
 /**
  * @author Tom
  * 
  */
 public class SimpleFileInteraction {
 
 	/**
 	 * @param args
 	 */
 	public static void main(String[] args) {
 		JavaCompilerTool javaCompilerTool = ToolProvider.defaultJavaCompiler();
 		JavaFileManager javaFileManager = javaCompilerTool
 				.getStandardFileManager();
 		try {
 			JavaFileObject javaFileObject = javaFileManager
 				    .getFileForInput("bin/Tutorials.java");
 
 			Writer writer = javaFileObject.openWriter();
 			writer.write("public class Tutorials{"
 				    + "public static void main(String[] args){"
 				    + "System.out.println(\"We love JavaLobby :)\");"
 					+ "}" + "}");
 			writer.close();
 			
 			javaCompilerTool.setOutputDirectory(new File("bin"));
 		    System.out.println(javaCompilerTool.run(null,new JavaFileObject[]{javaFileObject}).getDiagnostics());
 
 			Class.forName("Tutorials").getDeclaredMethod("main",
 				    new Class[] { String[].class }).invoke(null,
 				    new Object[] { null });
 
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
 	}
 }


Cheers Tom
3 . At 9:04 AM on Aug 29, 2006, Valerio Schiavoni wrote:
  Click to reply to this thread Reply

Re: Mustang: Compile Programmatically with the JSR-199 Compiler API

unfortunately, the example is outdated: tools.jar doesn't provide anymore the suggested interfaces and classes.

Everything has been moved out tools.jar and into rt.jar

The problem at this moment are on how to set the output directory for the compiled classes: do you have any suggestion ?

thanks,
Valerio
4 . At 6:15 AM on Sep 2, 2006, Guy Korland wrote:
  Click to reply to this thread Reply

Re: Mustang: Compile Programmatically with the JSR-199 Compiler API

Is there anyway to use this tool to add pre-compilation capabilities?

Guy

thread.rss_message