Refine ApplicationHome detection logic

Update the detection logic used in ApplicationHome to:
- Deal with `!/` elements in URLs so that `BOOT-INF/classes` packaging
  works as expected.
- Use the `start-class` when no explicit source class is provided to
  prevent accidentally picking a home next to a `spring-boot.jar` that
  happens to be on the classpath.
- Ignore search logic when running from a unit test.

Fixes gh-6129
pull/6133/head
Phillip Webb 9 years ago
parent 17dfec7c4e
commit c66da65e23

1
.gitignore vendored

@ -35,3 +35,4 @@ overridedb.*
.DS_Store .DS_Store
.factorypath .factorypath
dump.rdb dump.rdb
transaction-logs

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,12 +18,17 @@ package org.springframework.boot;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection; import java.net.JarURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.security.CodeSource; import java.security.CodeSource;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -51,17 +56,51 @@ public class ApplicationHome {
* @param sourceClass the source class or {@code null} * @param sourceClass the source class or {@code null}
*/ */
public ApplicationHome(Class<?> sourceClass) { public ApplicationHome(Class<?> sourceClass) {
this.source = findSource(sourceClass == null ? getClass() : sourceClass); this.source = findSource(sourceClass == null ? getStartClass() : sourceClass);
this.dir = findHomeDir(this.source); this.dir = findHomeDir(this.source);
} }
private Class<?> getStartClass() {
try {
ClassLoader classLoader = getClass().getClassLoader();
return getStartClass(classLoader.getResources("META-INF/MANIFEST.MF"));
}
catch (Exception ex) {
return null;
}
}
private Class<?> getStartClass(Enumeration<URL> manifestResources) {
while (manifestResources.hasMoreElements()) {
try {
InputStream inputStream = manifestResources.nextElement().openStream();
try {
Manifest manifest = new Manifest(inputStream);
String startClass = manifest.getMainAttributes()
.getValue("Start-Class");
if (startClass != null) {
return ClassUtils.forName(startClass,
getClass().getClassLoader());
}
}
finally {
inputStream.close();
}
}
catch (Exception ex) {
}
}
return null;
}
private File findSource(Class<?> sourceClass) { private File findSource(Class<?> sourceClass) {
try { try {
ProtectionDomain protectionDomain = sourceClass.getProtectionDomain(); ProtectionDomain domain = (sourceClass == null ? null
CodeSource codeSource = protectionDomain.getCodeSource(); : sourceClass.getProtectionDomain());
CodeSource codeSource = (domain == null ? null : domain.getCodeSource());
URL location = (codeSource == null ? null : codeSource.getLocation()); URL location = (codeSource == null ? null : codeSource.getLocation());
File source = (location == null ? null : findSource(location)); File source = (location == null ? null : findSource(location));
if (source != null && source.exists()) { if (source != null && source.exists() && !isUnitTest()) {
return source.getAbsoluteFile(); return source.getAbsoluteFile();
} }
return null; return null;
@ -71,14 +110,36 @@ public class ApplicationHome {
} }
} }
private boolean isUnitTest() {
try {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getClassName().startsWith("org.junit.")) {
return true;
}
}
}
catch (Exception ex) {
}
return false;
}
private File findSource(URL location) throws IOException { private File findSource(URL location) throws IOException {
URLConnection connection = location.openConnection(); URLConnection connection = location.openConnection();
if (connection instanceof JarURLConnection) { if (connection instanceof JarURLConnection) {
return new File(((JarURLConnection) connection).getJarFile().getName()); return getRootJarFile(((JarURLConnection) connection).getJarFile());
} }
return new File(location.getPath()); return new File(location.getPath());
} }
private File getRootJarFile(JarFile jarFile) {
String name = jarFile.getName();
int separator = name.indexOf("!/");
if (separator > 0) {
name = name.substring(0, separator);
}
return new File(name);
}
private File findHomeDir(File source) { private File findHomeDir(File source) {
File homeDir = source; File homeDir = source;
homeDir = (homeDir == null ? findDefaultHomeDir() : homeDir); homeDir = (homeDir == null ? findDefaultHomeDir() : homeDir);

Loading…
Cancel
Save