Skip to content

Commit c66da65

Browse files
committed
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 spring-projectsgh-6129
1 parent 17dfec7 commit c66da65

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ overridedb.*
3535
.DS_Store
3636
.factorypath
3737
dump.rdb
38+
transaction-logs

spring-boot/src/main/java/org/springframework/boot/ApplicationHome.java

+67-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,12 +18,17 @@
1818

1919
import java.io.File;
2020
import java.io.IOException;
21+
import java.io.InputStream;
2122
import java.net.JarURLConnection;
2223
import java.net.URL;
2324
import java.net.URLConnection;
2425
import java.security.CodeSource;
2526
import java.security.ProtectionDomain;
27+
import java.util.Enumeration;
28+
import java.util.jar.JarFile;
29+
import java.util.jar.Manifest;
2630

31+
import org.springframework.util.ClassUtils;
2732
import org.springframework.util.StringUtils;
2833

2934
/**
@@ -51,17 +56,51 @@ public ApplicationHome() {
5156
* @param sourceClass the source class or {@code null}
5257
*/
5358
public ApplicationHome(Class<?> sourceClass) {
54-
this.source = findSource(sourceClass == null ? getClass() : sourceClass);
59+
this.source = findSource(sourceClass == null ? getStartClass() : sourceClass);
5560
this.dir = findHomeDir(this.source);
5661
}
5762

63+
private Class<?> getStartClass() {
64+
try {
65+
ClassLoader classLoader = getClass().getClassLoader();
66+
return getStartClass(classLoader.getResources("META-INF/MANIFEST.MF"));
67+
}
68+
catch (Exception ex) {
69+
return null;
70+
}
71+
}
72+
73+
private Class<?> getStartClass(Enumeration<URL> manifestResources) {
74+
while (manifestResources.hasMoreElements()) {
75+
try {
76+
InputStream inputStream = manifestResources.nextElement().openStream();
77+
try {
78+
Manifest manifest = new Manifest(inputStream);
79+
String startClass = manifest.getMainAttributes()
80+
.getValue("Start-Class");
81+
if (startClass != null) {
82+
return ClassUtils.forName(startClass,
83+
getClass().getClassLoader());
84+
}
85+
}
86+
finally {
87+
inputStream.close();
88+
}
89+
}
90+
catch (Exception ex) {
91+
}
92+
}
93+
return null;
94+
}
95+
5896
private File findSource(Class<?> sourceClass) {
5997
try {
60-
ProtectionDomain protectionDomain = sourceClass.getProtectionDomain();
61-
CodeSource codeSource = protectionDomain.getCodeSource();
98+
ProtectionDomain domain = (sourceClass == null ? null
99+
: sourceClass.getProtectionDomain());
100+
CodeSource codeSource = (domain == null ? null : domain.getCodeSource());
62101
URL location = (codeSource == null ? null : codeSource.getLocation());
63102
File source = (location == null ? null : findSource(location));
64-
if (source != null && source.exists()) {
103+
if (source != null && source.exists() && !isUnitTest()) {
65104
return source.getAbsoluteFile();
66105
}
67106
return null;
@@ -71,14 +110,36 @@ private File findSource(Class<?> sourceClass) {
71110
}
72111
}
73112

113+
private boolean isUnitTest() {
114+
try {
115+
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
116+
if (element.getClassName().startsWith("org.junit.")) {
117+
return true;
118+
}
119+
}
120+
}
121+
catch (Exception ex) {
122+
}
123+
return false;
124+
}
125+
74126
private File findSource(URL location) throws IOException {
75127
URLConnection connection = location.openConnection();
76128
if (connection instanceof JarURLConnection) {
77-
return new File(((JarURLConnection) connection).getJarFile().getName());
129+
return getRootJarFile(((JarURLConnection) connection).getJarFile());
78130
}
79131
return new File(location.getPath());
80132
}
81133

134+
private File getRootJarFile(JarFile jarFile) {
135+
String name = jarFile.getName();
136+
int separator = name.indexOf("!/");
137+
if (separator > 0) {
138+
name = name.substring(0, separator);
139+
}
140+
return new File(name);
141+
}
142+
82143
private File findHomeDir(File source) {
83144
File homeDir = source;
84145
homeDir = (homeDir == null ? findDefaultHomeDir() : homeDir);

0 commit comments

Comments
 (0)