package com.josketres.builderator;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.security.SecureClassLoader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class TestCompiler {
private final JavaCompiler compiler;
private final DiagnosticCollector<JavaFileObject> diagnosticCollector;
private final MemoryFileManager fileManager;
public TestCompiler() {
compiler = ToolProvider.getSystemJavaCompiler();
diagnosticCollector = new DiagnosticCollector<JavaFileObject>();
fileManager = new MemoryFileManager(compiler.getStandardFileManager(diagnosticCollector, Locale.getDefault(), Charsets.UTF_8));
}
public boolean compile(JavaFileObject... sources) {
JavaCompiler.CompilationTask task = compiler.getTask(
null, // explicitly use the default because old versions of javac log some output on stderr
fileManager,
diagnosticCollector,
ImmutableSet.<String>of(),
ImmutableSet.<String>of(),
Arrays.asList(sources));
return task.call();
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
return fileManager.getClassLoader(null).loadClass(name);
}
}
class MemoryJavaClassObject extends SimpleJavaFileObject {
protected final ByteArrayOutputStream stream = new ByteArrayOutputStream();
public MemoryJavaClassObject(String name, Kind kind) {
super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind);
}
public byte[] getBytes() {
return stream.toByteArray();
}
@Override
public OutputStream openOutputStream() throws IOException {
return stream;
}
}
class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private Map<String, MemoryJavaClassObject> objects = new HashMap<String, MemoryJavaClassObject>();
public MemoryFileManager(StandardJavaFileManager manager) {
super(manager);
}
@Override
public ClassLoader getClassLoader(Location location) {
return new SecureClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] b = objects.get(name).getBytes();
return super.defineClass(name, objects.get(name).getBytes(), 0, b.length);
}
};
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
System.out.println(location.toString());
objects.put(name, new MemoryJavaClassObject(name, kind));
return objects.get(name);
}
}
class MemoryJavaFileObject extends SimpleJavaFileObject {
private CharSequence content;
protected MemoryJavaFileObject(String className, CharSequence content) {
super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
this.content = content;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return content;
}
}