diff --git a/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java b/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java index 59e8edd31a..698e66949b 100644 --- a/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java +++ b/jOOQ/src/main/java/org/jooq/tools/reflect/Compile.java @@ -28,7 +28,10 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; @@ -60,29 +63,32 @@ class Compile { try { ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null)); - List files = new ArrayList(); + List files = new ArrayList<>(); files.add(new CharSequenceJavaFileObject(className, content)); StringWriter out = new StringWriter(); - List options = new ArrayList(); - StringBuilder classpath = new StringBuilder(); - String separator = System.getProperty("path.separator"); - String prop = System.getProperty("java.class.path"); + List options = new ArrayList<>(compileOptions.options); + if (!options.contains("-classpath")) { + StringBuilder classpath = new StringBuilder(); + String separator = System.getProperty("path.separator"); + String prop = System.getProperty("java.class.path"); - if (prop != null && !"".equals(prop)) - classpath.append(prop); + if (prop != null && !"".equals(prop)) + classpath.append(prop); - if (cl instanceof URLClassLoader) { - for (URL url : ((URLClassLoader) cl).getURLs()) { - if (classpath.length() > 0) - classpath.append(separator); + if (cl instanceof URLClassLoader) { + for (URL url : ((URLClassLoader) cl).getURLs()) { + if (classpath.length() > 0) + classpath.append(separator); - if ("file".equals(url.getProtocol())) - classpath.append(new File(url.getFile())); + if ("file".equals(url.getProtocol())) + classpath.append(new File(url.toURI())); + } } + + options.addAll(Arrays.asList("-classpath", classpath.toString())); } - options.addAll(Arrays.asList("-classpath", classpath.toString())); CompilationTask task = compiler.getTask(out, fileManager, null, options, null, files); if (!compileOptions.processors.isEmpty()) @@ -90,16 +96,21 @@ class Compile { task.call(); - if (fileManager.o == null) + if (fileManager.isEmpty()) throw new ReflectException("Compilation error: " + out); Class result = null; // This works if we have private-access to the interfaces in the class hierarchy - if (Reflect.CACHED_LOOKUP_CONSTRUCTOR != null) { - byte[] b = fileManager.o.getBytes(); - result = Reflect.on(cl).call("defineClass", className, b, 0, b.length).get(); - } + + + + result = fileManager.loadAndReturnMainClass(className, + (name, bytes) -> Reflect.on(cl).call("defineClass", name, bytes, 0, bytes.length).get()); + + + + @@ -150,6 +161,22 @@ class Compile { } } + + + + + + + + + + + + + + + + static final class JavaFileObject extends SimpleJavaFileObject { final ByteArrayOutputStream os = new ByteArrayOutputStream(); @@ -168,10 +195,13 @@ class Compile { } static final class ClassFileManager extends ForwardingJavaFileManager { - JavaFileObject o; + private final Map fileObjectMap; + private Map classes; ClassFileManager(StandardJavaFileManager standardManager) { super(standardManager); + + fileObjectMap = new HashMap<>(); } @Override @@ -181,8 +211,42 @@ class Compile { JavaFileObject.Kind kind, FileObject sibling ) { - return o = new JavaFileObject(className, kind); + JavaFileObject result = new JavaFileObject(className, kind); + fileObjectMap.put(className, result); + return result; } + + boolean isEmpty() { + return fileObjectMap.isEmpty(); + } + + Map classes() { + if (classes == null) { + classes = new HashMap<>(); + + for (Entry entry : fileObjectMap.entrySet()) + classes.put(entry.getKey(), entry.getValue().getBytes()); + } + + return classes; + } + + Class loadAndReturnMainClass(String mainClassName, ThrowingBiFunction> definer) throws Exception { + Class result = null; + + for (Entry entry : classes().entrySet()) { + Class c = definer.apply(entry.getKey(), entry.getValue()); + if (mainClassName.equals(entry.getKey())) + result = c; + } + + return result; + } + } + + @FunctionalInterface + interface ThrowingBiFunction { + R apply(T t, U u) throws Exception; } static final class CharSequenceJavaFileObject extends SimpleJavaFileObject { diff --git a/jOOQ/src/main/java/org/jooq/tools/reflect/CompileOptions.java b/jOOQ/src/main/java/org/jooq/tools/reflect/CompileOptions.java index e284e2040b..570371368b 100644 --- a/jOOQ/src/main/java/org/jooq/tools/reflect/CompileOptions.java +++ b/jOOQ/src/main/java/org/jooq/tools/reflect/CompileOptions.java @@ -13,10 +13,9 @@ */ package org.jooq.tools.reflect; + + import java.util.Arrays; - - - import java.util.Collections; import java.util.List; @@ -28,25 +27,37 @@ import javax.annotation.processing.Processor; public final class CompileOptions { final List processors; + final List options; public CompileOptions() { this( + Collections.emptyList(), Collections.emptyList() ); } - private CompileOptions(List processors) { + private CompileOptions( + List processors, + List options + ) { this.processors = processors; + this.options = options; } - @SuppressWarnings("hiding") - public CompileOptions processors(Processor... processors) { - return processors(Arrays.asList(processors)); + public final CompileOptions processors(Processor... newProcessors) { + return processors(Arrays.asList(newProcessors)); } - @SuppressWarnings("hiding") - public CompileOptions processors(List processors) { - return new CompileOptions(processors); + public final CompileOptions processors(List newProcessors) { + return new CompileOptions(newProcessors, options); + } + + public final CompileOptions options(String... newOptions) { + return options(Arrays.asList(newOptions)); + } + + public final CompileOptions options(List newOptions) { + return new CompileOptions(processors, newOptions); } }