Determine Spring Boot version correctly when using module path

In Java 9, a package may return null for its implementation version
even when the manifest attribute specifying the version is present
in the jar from which the package was loaded.

This commit updates SpringBootVersion to fall back to
accessing the jar and its manifest attributes directly when the
implementation version of its package is null.

See gh-16182
This commit is contained in:
Hendrig Sellik 2019-03-09 12:00:59 +01:00 committed by Andy Wilkinson
parent 47d42cbc35
commit ec8fb614f7
1 changed files with 37 additions and 2 deletions

View File

@ -16,6 +16,14 @@
package org.springframework.boot;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
/**
* Class that exposes the Spring Boot version. Fetches the "Implementation-Version"
* manifest attribute from the jar file.
@ -40,8 +48,35 @@ public final class SpringBootVersion {
* @see Package#getImplementationVersion()
*/
public static String getVersion() {
Package pkg = SpringBootVersion.class.getPackage();
return (pkg != null) ? pkg.getImplementationVersion() : null;
return determineSpringBootVersion();
}
private static String determineSpringBootVersion() {
String implementationVersion = SpringBootVersion.class.getPackage()
.getImplementationVersion();
if (implementationVersion != null) {
return implementationVersion;
}
URL codeSourceLocation = SpringBootVersion.class.getProtectionDomain()
.getCodeSource().getLocation();
try {
URLConnection connection = codeSourceLocation.openConnection();
if (connection instanceof JarURLConnection) {
return getImplementationVersion(
((JarURLConnection) connection).getJarFile());
}
try (JarFile jarFile = new JarFile(new File(codeSourceLocation.toURI()))) {
return getImplementationVersion(jarFile);
}
}
catch (Exception ex) {
return null;
}
}
private static String getImplementationVersion(JarFile jarFile) throws IOException {
return jarFile.getManifest().getMainAttributes()
.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
}
}