reliably delegate all not explicitly imeplemented API calls from StandardJavaFileManager to JDK implementation object

This commit is contained in:
Eugene Zhuravlev
2016-04-06 14:52:37 +02:00
parent 4969706019
commit b8f10f6b5c
2 changed files with 32 additions and 25 deletions
@@ -25,7 +25,6 @@ import javax.tools.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
@@ -109,26 +108,6 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
getStdManager().setLocation(location, path);
}
// IMPORTANT! DO NOT REMOVE!
// when run on java9, this method will override corresponding method from the superclass
// will be called by javac9
public void setLocationFromPaths(Location location, Iterable<? /*extends java.nio.file.Path*/> paths) throws IOException {
try {
final Method forwardingMethod = StandardJavaFileManager.class.getMethod("setLocationFromPaths", Location.class, Iterable.class);
forwardingMethod.invoke(getStdManager(), location, paths);
}
catch (InvocationTargetException e) {
final Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException)cause;
}
throw new IOException("Error configuring " + location.getName(), cause);
}
catch (Throwable e) {
throw new IOException("Internal error: ", e);
}
}
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
return wrapJavaFileObjects(getStdManager().getJavaFileObjectsFromFiles(files));
}
@@ -358,4 +337,21 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
public Context getContext() {
return myContext;
}
private static Map<Method, Boolean> ourImplStatus = Collections.synchronizedMap(new HashMap<Method, Boolean>());
JavaFileManager getApiCallHandler(Method method) {
Boolean isImplemented = ourImplStatus.get(method);
if (isImplemented == null) {
try {
JavacFileManager.class.getDeclaredMethod(method.getName(), method.getParameterTypes());
isImplemented = Boolean.TRUE;
}
catch (NoSuchMethodException e) {
isImplemented = Boolean.FALSE;
}
ourImplStatus.put(method, isImplemented);
}
return isImplemented? this : getStdManager();
}
}
@@ -30,9 +30,7 @@ import org.jetbrains.jps.incremental.LineOutputWriter;
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -155,7 +153,7 @@ public class JavacMain {
};
final JavaCompiler.CompilationTask task = compiler.getTask(
out, fileManager, diagnosticConsumer, _options, null, fileManager.getJavaFileObjectsFromFiles(sources)
out, wrapWithCallDispatcher(fileManager), diagnosticConsumer, _options, null, fileManager.getJavaFileObjectsFromFiles(sources)
);
compilingTool.prepareCompilationTask(task, _options);
@@ -191,6 +189,19 @@ public class JavacMain {
return false;
}
// methods added to newer versions of StandardJavaFileManager interfaces have default implementations that
// do not delegate to corresponding methods of FileManager's base implementation
// this proxy object makes sure the calls, not implemented in our file manager, are dispatched further to the base file manager implementation
private static StandardJavaFileManager wrapWithCallDispatcher(final JavacFileManager fileManager) {
//return fileManager;
return (StandardJavaFileManager)Proxy.newProxyInstance(fileManager.getClass().getClassLoader(), new Class[]{StandardJavaFileManager.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(fileManager.getApiCallHandler(method), args);
}
});
}
private static boolean canUseOptimizedFileManager(JavaCompilingTool compilingTool) {
// since java 9 internal API's used by the optimizedFileManager have changed
return compilingTool instanceof JavacCompilerTool && !SystemInfo.isJavaVersionAtLeast("1.9");