Add heuristic for Spring Boot fat jar

The function compiler knows how to extract jars nested inside
a Spring Boot fat jar. It's really slow (so that's maybe another
problem for another day), but it works now.

Fixes gh-115
This commit is contained in:
Dave Syer
2017-10-25 10:19:39 +01:00
parent b1437fe9c0
commit d58c58b765

View File

@@ -55,7 +55,7 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
private List<CloseableFilterableJavaFileObjectIterable> toClose = new ArrayList<>(); private List<CloseableFilterableJavaFileObjectIterable> toClose = new ArrayList<>();
private Map<String,File> resolvedAdditionalDependencies = new LinkedHashMap<>(); private Map<String, File> resolvedAdditionalDependencies = new LinkedHashMap<>();
public MemoryBasedJavaFileManager() { public MemoryBasedJavaFileManager() {
outputCollector = new CompilationOutputCollector(); outputCollector = new CompilationOutputCollector();
@@ -89,14 +89,17 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
&& (kinds == null || kinds.contains(Kind.CLASS))) { && (kinds == null || kinds.contains(Kind.CLASS))) {
String javaClassPath = getClassPath(); String javaClassPath = getClassPath();
if (!resolvedAdditionalDependencies.isEmpty()) { if (!resolvedAdditionalDependencies.isEmpty()) {
for (File resolvedAdditionalDependency: resolvedAdditionalDependencies.values()) { for (File resolvedAdditionalDependency : resolvedAdditionalDependencies
javaClassPath += File.pathSeparatorChar + resolvedAdditionalDependency.toURI().toString().substring("file:".length()); .values()) {
javaClassPath += File.pathSeparatorChar + resolvedAdditionalDependency
.toURI().toString().substring("file:".length());
} }
} }
classpath = javaClassPath; classpath = javaClassPath;
logger.debug("Creating iterable for class path: {}", classpath); logger.debug("Creating iterable for class path: {}", classpath);
} }
CloseableFilterableJavaFileObjectIterable resultIterable = new IterableClasspath(classpath, packageName, recurse); CloseableFilterableJavaFileObjectIterable resultIterable = new IterableClasspath(
classpath, packageName, recurse);
toClose.add(resultIterable); toClose.add(resultIterable);
return resultIterable; return resultIterable;
} }
@@ -106,18 +109,20 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
if (loader instanceof URLClassLoader) { if (loader instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) loader).getURLs(); URL[] urls = ((URLClassLoader) loader).getURLs();
if (urls.length > 1) { // heuristic that catches Maven surefire tests if (urls.length > 1) { // heuristic that catches Maven surefire tests
StringBuilder builder = new StringBuilder(); if (!urls[0].toString().startsWith("jar:file:")) { // heuristic for Spring Boot fat jar
for (URL url : urls) { StringBuilder builder = new StringBuilder();
if (builder.length() > 0) { for (URL url : urls) {
builder.append(File.pathSeparator); if (builder.length() > 0) {
builder.append(File.pathSeparator);
}
String path = url.toString();
if (path.startsWith("file:")) {
path = path.substring("file:".length());
}
builder.append(path);
} }
String path = url.toString(); return builder.toString();
if (path.startsWith("file:")) {
path = path.substring("file:".length());
}
builder.append(path);
} }
return builder.toString();
} }
} }
return System.getProperty("java.class.path"); return System.getProperty("java.class.path");
@@ -207,26 +212,33 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
public List<CompilationMessage> addAndResolveDependencies(String[] dependencies) { public List<CompilationMessage> addAndResolveDependencies(String[] dependencies) {
List<CompilationMessage> resolutionMessages = new ArrayList<>(); List<CompilationMessage> resolutionMessages = new ArrayList<>();
for (String dependency: dependencies) { for (String dependency : dependencies) {
if (dependency.startsWith("maven:")) { if (dependency.startsWith("maven:")) {
// Resolving an explicit external archive // Resolving an explicit external archive
String coordinates = dependency.replaceFirst("maven:\\/*", ""); String coordinates = dependency.replaceFirst("maven:\\/*", "");
DependencyResolver engine = DependencyResolver.instance(); DependencyResolver engine = DependencyResolver.instance();
try { try {
File resolved = engine.resolve(new Dependency(new DefaultArtifact(coordinates), "runtime")); File resolved = engine.resolve(
new Dependency(new DefaultArtifact(coordinates), "runtime"));
// Example: // Example:
// dependency = maven://org.springframework:spring-expression:4.3.9.RELEASE // dependency =
// resolved.toURI() = file:/Users/aclement/.m2/repository/org/springframework/spring-expression/4.3.9.RELEASE/spring-expression-4.3.9.RELEASE.jar // maven://org.springframework:spring-expression:4.3.9.RELEASE
// resolved.toURI() =
// file:/Users/aclement/.m2/repository/org/springframework/spring-expression/4.3.9.RELEASE/spring-expression-4.3.9.RELEASE.jar
resolvedAdditionalDependencies.put(dependency, resolved); resolvedAdditionalDependencies.put(dependency, resolved);
} catch (RuntimeException re) { }
CompilationMessage compilationMessage = catch (RuntimeException re) {
new CompilationMessage(CompilationMessage.Kind.ERROR,re.getMessage(),null,0,0); CompilationMessage compilationMessage = new CompilationMessage(
CompilationMessage.Kind.ERROR, re.getMessage(), null, 0, 0);
resolutionMessages.add(compilationMessage); resolutionMessages.add(compilationMessage);
} }
} }
else { else {
resolutionMessages.add(new CompilationMessage(CompilationMessage.Kind.ERROR, resolutionMessages.add(new CompilationMessage(
"Unrecognized dependency: "+dependency+" (expected something of the form: maven://groupId:artifactId:version)",null,0,0)); CompilationMessage.Kind.ERROR,
"Unrecognized dependency: " + dependency
+ " (expected something of the form: maven://groupId:artifactId:version)",
null, 0, 0));
} }
} }
return resolutionMessages; return resolutionMessages;