Java: Dynamic Compiling

Un ejemplo de uso del API de Compilacion de Java, en este caso generaremos una clase “HelloWorld” dinamicamente desde un String:

import java.net.URI;
import java.util.Arrays;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;

public class StringCompiler {
	public static final void compile(String className, String sourceCode, 
			String outputDir) {
		long ts = System.currentTimeMillis();
		SimpleJavaFileObject fileObject = new JavaSourceFromString(className, 
			sourceCode);
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		Iterable<? extends JavaFileObject> compilationUnits = Arrays
			.asList(fileObject);
		Iterable<String> compilationOptionss = Arrays.asList( //
				"-source", "1.6", // Source version
				"-target", "1.6", // Target version
				"-d", outputDir // Output Directory
				);
		DiagnosticCollector<JavaFileObject> diagnostics = new 
			DiagnosticCollector<JavaFileObject>();
		CompilationTask compilerTask = compiler.getTask(null, null, 
			diagnostics, compilationOptionss, null, compilationUnits);
		System.out.format("Compiling %s ", className);
		if (!compilerTask.call()) { // Error compiling
			for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
				System.out.format("Error on line %d in %s ", 
					diagnostic.getLineNumber(), diagnostic);
			}
		}
		System.out.format("time=%d (ms)\n", (System.currentTimeMillis() - ts));
	}

	/**
	 * Simple HelloWorld Compilation
	 */
	public static void main(final String[] args) {
		final StringBuilder sb = new StringBuilder();
		final String tmpDir = System.getProperty("java.io.tmpdir");
		sb.append("package com.acme;").append('\n');
		sb.append("public class Test {").append('\n');
		sb.append("  public static void main(String[] args) {").append('\n');
		sb.append("    System.out.println(\"hello world\");").append('\n');
		sb.append("  }").append('\n');
		sb.append("}").append('\n');
		compile("com.acme.Test", sb.toString(), tmpDir);
	}

	public static class JavaSourceFromString extends SimpleJavaFileObject {
		final String code;

		JavaSourceFromString(final String name, final String code) {
			super(URI.create("string:///" + name.replace('.', '/') + 
				Kind.SOURCE.extension), Kind.SOURCE);
			this.code = code;
		}

		@Override
		public CharSequence getCharContent(boolean ignoreEncodingErrors) {
			return code;
		}
	}
}

Fuentes:
javax.tools.JavaCompiler

Alternativas:
Apache Commons JCI || Sample
Janino || Sample
Eclipse Compiler for Java || Sample

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: