Use classpath URLs from class loader instead of system property
The system property doesn't work for a bootiful jar. With this change there is no need to scan the jar for nested jars either.
This commit is contained in:
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.function.compiler.java;
|
package org.springframework.cloud.function.compiler.java;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -32,16 +35,17 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A file manager that serves source code from in memory and ensures output results are kept in memory
|
* A file manager that serves source code from in memory and ensures output results are
|
||||||
* rather than being flushed out to disk. The JavaFileManager is also used as a lookup mechanism
|
* kept in memory rather than being flushed out to disk. The JavaFileManager is also used
|
||||||
* for resolving types.
|
* as a lookup mechanism for resolving types.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*/
|
*/
|
||||||
public class MemoryBasedJavaFileManager implements JavaFileManager {
|
public class MemoryBasedJavaFileManager implements JavaFileManager {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(MemoryBasedJavaFileManager.class);
|
private static Logger logger = LoggerFactory
|
||||||
|
.getLogger(MemoryBasedJavaFileManager.class);
|
||||||
|
|
||||||
private CompilationOutputCollector outputCollector;
|
private CompilationOutputCollector outputCollector;
|
||||||
|
|
||||||
private List<CloseableFilterableJavaFileObjectIterable> toClose = new ArrayList<>();
|
private List<CloseableFilterableJavaFileObjectIterable> toClose = new ArrayList<>();
|
||||||
@@ -52,7 +56,7 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int isSupportedOption(String option) {
|
public int isSupportedOption(String option) {
|
||||||
logger.debug("isSupportedOption({})",option);
|
logger.debug("isSupportedOption({})", option);
|
||||||
return -1; // Not yet supporting options
|
return -1; // Not yet supporting options
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,41 +64,69 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
|
|||||||
public ClassLoader getClassLoader(Location location) {
|
public ClassLoader getClassLoader(Location location) {
|
||||||
// Do not simply return the context classloader as it may get closed and then
|
// Do not simply return the context classloader as it may get closed and then
|
||||||
// be unusable for loading any further classes
|
// be unusable for loading any further classes
|
||||||
logger.debug("getClassLoader({})",location);
|
logger.debug("getClassLoader({})", location);
|
||||||
return null; // Do not currently need to load plugins
|
return null; // Do not currently need to load plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse)
|
public Iterable<JavaFileObject> list(Location location, String packageName,
|
||||||
throws IOException {
|
Set<Kind> kinds, boolean recurse) throws IOException {
|
||||||
logger.debug("list({},{},{},{})",location,packageName,kinds,recurse);
|
logger.debug("list({},{},{},{})", location, packageName, kinds, recurse);
|
||||||
CloseableFilterableJavaFileObjectIterable resultIterable = null;
|
CloseableFilterableJavaFileObjectIterable resultIterable = null;
|
||||||
if (location == StandardLocation.PLATFORM_CLASS_PATH && (kinds==null || kinds.contains(Kind.CLASS))) {
|
if (location == StandardLocation.PLATFORM_CLASS_PATH
|
||||||
|
&& (kinds == null || kinds.contains(Kind.CLASS))) {
|
||||||
String sunBootClassPath = System.getProperty("sun.boot.class.path");
|
String sunBootClassPath = System.getProperty("sun.boot.class.path");
|
||||||
logger.debug("Creating iterable for boot class path: {}",sunBootClassPath);
|
logger.debug("Creating iterable for boot class path: {}", sunBootClassPath);
|
||||||
resultIterable = new IterableClasspath(sunBootClassPath, packageName, recurse);
|
resultIterable = new IterableClasspath(sunBootClassPath, packageName,
|
||||||
|
recurse);
|
||||||
toClose.add(resultIterable);
|
toClose.add(resultIterable);
|
||||||
} else if (location == StandardLocation.CLASS_PATH && (kinds==null || kinds.contains(Kind.CLASS))) {
|
}
|
||||||
String javaClassPath = System.getProperty("java.class.path");
|
else if (location == StandardLocation.CLASS_PATH
|
||||||
logger.debug("Creating iterable for class path: {}",javaClassPath);
|
&& (kinds == null || kinds.contains(Kind.CLASS))) {
|
||||||
|
String javaClassPath = getClassPath();
|
||||||
|
logger.debug("Creating iterable for class path: {}", javaClassPath);
|
||||||
resultIterable = new IterableClasspath(javaClassPath, packageName, recurse);
|
resultIterable = new IterableClasspath(javaClassPath, packageName, recurse);
|
||||||
toClose.add(resultIterable);
|
toClose.add(resultIterable);
|
||||||
} else if (location == StandardLocation.SOURCE_PATH) {
|
}
|
||||||
|
else if (location == StandardLocation.SOURCE_PATH) {
|
||||||
// There are no 'extra sources'
|
// There are no 'extra sources'
|
||||||
resultIterable = EmptyIterable.instance;
|
resultIterable = EmptyIterable.instance;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Nothing to list
|
// Nothing to list
|
||||||
resultIterable = EmptyIterable.instance;
|
resultIterable = EmptyIterable.instance;
|
||||||
}
|
}
|
||||||
return resultIterable;
|
return resultIterable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getClassPath() {
|
||||||
|
ClassLoader loader = InMemoryJavaFileObject.class.getClassLoader();
|
||||||
|
if (loader instanceof URLClassLoader) {
|
||||||
|
URL[] urls = ((URLClassLoader) loader).getURLs();
|
||||||
|
if (urls.length > 1) { // heuristic that catches Maven surefire tests
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (URL url : urls) {
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
builder.append(File.pathSeparator);
|
||||||
|
}
|
||||||
|
String path = url.toString();
|
||||||
|
if (path.startsWith("file:")) {
|
||||||
|
path = path.substring("file:".length());
|
||||||
|
}
|
||||||
|
builder.append(url);
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return System.getProperty("java.class.path");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasLocation(Location location) {
|
public boolean hasLocation(Location location) {
|
||||||
logger.debug("hasLocation({})",location);
|
logger.debug("hasLocation({})", location);
|
||||||
return (location == StandardLocation.SOURCE_PATH ||
|
return (location == StandardLocation.SOURCE_PATH
|
||||||
location == StandardLocation.CLASS_PATH ||
|
|| location == StandardLocation.CLASS_PATH
|
||||||
location == StandardLocation.PLATFORM_CLASS_PATH);
|
|| location == StandardLocation.PLATFORM_CLASS_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -110,44 +142,50 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSameFile(FileObject a, FileObject b) {
|
public boolean isSameFile(FileObject a, FileObject b) {
|
||||||
logger.debug("isSameFile({},{})",a,b);
|
logger.debug("isSameFile({},{})", a, b);
|
||||||
return a.equals(b);
|
return a.equals(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleOption(String current, Iterator<String> remaining) {
|
public boolean handleOption(String current, Iterator<String> remaining) {
|
||||||
logger.debug("handleOption({},{})",current,remaining);
|
logger.debug("handleOption({},{})", current, remaining);
|
||||||
return false; // This file manager does not manage any options
|
return false; // This file manager does not manage any options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
|
public JavaFileObject getJavaFileForInput(Location location, String className,
|
||||||
logger.debug("getJavaFileForInput({},{},{})",location,className,kind);
|
Kind kind) throws IOException {
|
||||||
|
logger.debug("getJavaFileForInput({},{},{})", location, className, kind);
|
||||||
throw new IllegalStateException("Not expected to be used in this context");
|
throw new IllegalStateException("Not expected to be used in this context");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling)
|
public JavaFileObject getJavaFileForOutput(Location location, String className,
|
||||||
throws IOException {
|
Kind kind, FileObject sibling) throws IOException {
|
||||||
logger.debug("getJavaFileForOutput({},{},{},{})",location,className,kind,sibling);
|
logger.debug("getJavaFileForOutput({},{},{},{})", location, className, kind,
|
||||||
// Example parameters: CLASS_OUTPUT, Foo, CLASS, StringBasedJavaSourceFileObject[string:///a/b/c/Foo.java]
|
sibling);
|
||||||
|
// Example parameters: CLASS_OUTPUT, Foo, CLASS,
|
||||||
|
// StringBasedJavaSourceFileObject[string:///a/b/c/Foo.java]
|
||||||
return outputCollector.getJavaFileForOutput(location, className, kind, sibling);
|
return outputCollector.getJavaFileForOutput(location, className, kind, sibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
|
public FileObject getFileForInput(Location location, String packageName,
|
||||||
logger.debug("getFileForInput({},{},{})",location,packageName,relativeName);
|
String relativeName) throws IOException {
|
||||||
|
logger.debug("getFileForInput({},{},{})", location, packageName, relativeName);
|
||||||
throw new IllegalStateException("Not expected to be used in this context");
|
throw new IllegalStateException("Not expected to be used in this context");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling)
|
public FileObject getFileForOutput(Location location, String packageName,
|
||||||
throws IOException {
|
String relativeName, FileObject sibling) throws IOException {
|
||||||
logger.debug("getFileForOutput({},{},{},{})",location,packageName,relativeName,sibling);
|
logger.debug("getFileForOutput({},{},{},{})", location, packageName, relativeName,
|
||||||
|
sibling);
|
||||||
// This can be called when the annotation config processor runs
|
// This can be called when the annotation config processor runs
|
||||||
// Example parameters: CLASS_OUTPUT, , META-INF/spring-configuration-metadata.json, null
|
// Example parameters: CLASS_OUTPUT, ,
|
||||||
return outputCollector.getFileForOutput(location, packageName, relativeName, sibling);
|
// META-INF/spring-configuration-metadata.json, null
|
||||||
|
return outputCollector.getFileForOutput(location, packageName, relativeName,
|
||||||
|
sibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -156,7 +194,7 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
for (CloseableFilterableJavaFileObjectIterable closeable: toClose) {
|
for (CloseableFilterableJavaFileObjectIterable closeable : toClose) {
|
||||||
closeable.close();
|
closeable.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user