Fallback to JVM URL handler on exception
Update the executable JAR `Handler` to fallback to the JVM handler if the jar cannot be opened. This prevents exceptions when trying to open URLs in the form "jar:jndi:/localhost...". Fixes gh-347
This commit is contained in:
parent
97c258a2b4
commit
dfe6de8c1f
|
|
@ -18,10 +18,13 @@ package org.springframework.boot.loader.jar;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.net.URLStreamHandler;
|
import java.net.URLStreamHandler;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link URLStreamHandler} for Spring Boot loader {@link JarFile}s.
|
* {@link URLStreamHandler} for Spring Boot loader {@link JarFile}s.
|
||||||
|
|
@ -38,8 +41,26 @@ public class Handler extends URLStreamHandler {
|
||||||
|
|
||||||
private static final String SEPARATOR = JarURLConnection.SEPARATOR;
|
private static final String SEPARATOR = JarURLConnection.SEPARATOR;
|
||||||
|
|
||||||
|
private static final String[] FALLBACK_HANDLERS = { "sun.net.www.protocol.jar.Handler" };
|
||||||
|
|
||||||
|
private static final Method OPEN_CONNECTION_METHOD;
|
||||||
|
static {
|
||||||
|
Method method = null;
|
||||||
|
try {
|
||||||
|
method = URLStreamHandler.class
|
||||||
|
.getDeclaredMethod("openConnection", URL.class);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
}
|
||||||
|
OPEN_CONNECTION_METHOD = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Logger logger = Logger.getLogger(getClass().getName());
|
||||||
|
|
||||||
private final JarFile jarFile;
|
private final JarFile jarFile;
|
||||||
|
|
||||||
|
private URLStreamHandler fallbackHandler;
|
||||||
|
|
||||||
public Handler() {
|
public Handler() {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
@ -50,8 +71,60 @@ public class Handler extends URLStreamHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected URLConnection openConnection(URL url) throws IOException {
|
protected URLConnection openConnection(URL url) throws IOException {
|
||||||
JarFile jarFile = (this.jarFile != null ? this.jarFile : getJarFileFromUrl(url));
|
if (this.jarFile != null) {
|
||||||
return new JarURLConnection(url, jarFile);
|
return new JarURLConnection(url, this.jarFile);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new JarURLConnection(url, getJarFileFromUrl(url));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
return openFallbackConnection(url, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private URLConnection openFallbackConnection(URL url, Exception reason)
|
||||||
|
throws IOException {
|
||||||
|
try {
|
||||||
|
return openConnection(getFallbackHandler(), url);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
this.logger.log(Level.WARNING, "Unable to open fallback handler", ex);
|
||||||
|
if (reason instanceof IOException) {
|
||||||
|
throw (IOException) reason;
|
||||||
|
}
|
||||||
|
if (reason instanceof RuntimeException) {
|
||||||
|
throw (RuntimeException) reason;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private URLStreamHandler getFallbackHandler() {
|
||||||
|
if (this.fallbackHandler != null) {
|
||||||
|
return this.fallbackHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String handlerClassName : FALLBACK_HANDLERS) {
|
||||||
|
try {
|
||||||
|
Class<?> handlerClass = Class.forName(handlerClassName);
|
||||||
|
this.fallbackHandler = (URLStreamHandler) handlerClass.newInstance();
|
||||||
|
return this.fallbackHandler;
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Unable to find fallback handler");
|
||||||
|
}
|
||||||
|
|
||||||
|
private URLConnection openConnection(URLStreamHandler handler, URL url)
|
||||||
|
throws Exception {
|
||||||
|
if (OPEN_CONNECTION_METHOD == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Unable to invoke fallback open connection method");
|
||||||
|
}
|
||||||
|
OPEN_CONNECTION_METHOD.setAccessible(true);
|
||||||
|
return (URLConnection) OPEN_CONNECTION_METHOD.invoke(handler, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JarFile getJarFileFromUrl(URL url) throws IOException {
|
public JarFile getJarFileFromUrl(URL url) throws IOException {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue