package net.karneim.pojobuilder.testenv; import java.util.List; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.tools.Diagnostic; import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileObject; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; public class ProcessingEnvironmentRunner extends BlockJUnit4ClassRunner { private static final ProcessingEnvironmentAdaptor processingEnvironment = new ProcessingEnvironmentAdaptor(); private static final RoundEnvironmentAdaptor roundEnvironment = new RoundEnvironmentAdaptor(); public static ProcessingEnvironment getProcessingEnvironment() { return processingEnvironment; } public static RoundEnvironment getRoundEnvironment() { return roundEnvironment; } private Class<?> klass; public ProcessingEnvironmentRunner(Class<?> klass) throws InitializationError { super(klass); this.klass = klass; } @Override protected Statement methodBlock(FrameworkMethod method) { final Statement next = super.methodBlock(method); return new CompilationStatement(next, method); } private class CompilationStatement extends Statement { private Statement next; private FrameworkMethod method; private Throwable exception; public CompilationStatement(Statement next, FrameworkMethod method) { super(); this.next = next; this.method = method; } @Override public void evaluate() throws Throwable { exception = null; JavaProject prj = new JavaProject(Util.createTempDir()); addSourceFiles(prj, klass.getAnnotation(AddToSourceTree.class)); addSourceFiles(prj, method.getMethod().getAnnotation(AddToSourceTree.class)); ProcessingInterceptor interceptor = new ProcessingInterceptor(); interceptor.setListener(new ProcessorListener() { @Override public void onInvoke(ProcessingEnvironment env, RoundEnvironment roundEnv) { processingEnvironment.setDelegate(env); roundEnvironment.setDelegate(roundEnv); try { next.evaluate(); } catch (Throwable t) { exception = t; } } }); prj.getProcessors().add(interceptor); prj.addClassnameForProcessing(klass.getCanonicalName()); try { prj.compile(); List<Diagnostic<? extends JavaFileObject>> diagnostics = prj.getDiagnostics(); for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics) { if (diagnostic.getKind() == Kind.ERROR) { throw new CompilationException(diagnostic.toString()); } } } finally { processingEnvironment.setDelegate(null); roundEnvironment.setDelegate(null); prj.delete(); } if (exception != null) { throw exception; } } } private static void addSourceFiles(JavaProject prj, AddToSourceTree anno) { if (anno != null) { String[] files = anno.value(); if (files != null) { for (String file : files) { prj.addSourceFile(file); } } } } @Override public void run(RunNotifier notifier) { super.run(notifier); } }