@ -18,10 +18,13 @@ package org.springframework.boot.loader.jar;
import java.io.File ;
import java.io.IOException ;
import java.lang.reflect.Method ;
import java.net.MalformedURLException ;
import java.net.URL ;
import java.net.URLConnection ;
import java.net.URLStreamHandler ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
/ * *
* { @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 [ ] 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 URLStreamHandler fallbackHandler ;
public Handler ( ) {
this ( null ) ;
}
@ -50,8 +71,60 @@ public class Handler extends URLStreamHandler {
@Override
protected URLConnection openConnection ( URL url ) throws IOException {
JarFile jarFile = ( this . jarFile ! = null ? this . jarFile : getJarFileFromUrl ( url ) ) ;
return new JarURLConnection ( url , jarFile ) ;
if ( this . jarFile ! = null ) {
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 {