Avoid a clash with TomcatURLStreamHandlerFactory

In the unlikely (outside the tests of a number of Spring Boot's
modules) event that both Tomcat and Jetty are on the classpath,
there's a risk that Tomcat will try to register its
URLStreamHandlerFactory after JasperInitializer has registered its
WarUrlStreamHandlerFactory. Should this happen, Tomcat will fail to
start.

TomcatURLStreamHandlerFactory registers a handler for the war: URLs
produced by org.apache.tomcat.util.scan.JarFactory that's used by
both Tomcat and Jetty's Jasper integration. This makes it a suitable
replacement for WarUrlStreamHandlerFactory so this commit updates
JasperIntializer to register TomcatURLStreamHandlerFactory when it's
available, falling back to WarUrlStreamHandlerFactory when it's not.

Closes gh-8622
pull/9046/merge
Andy Wilkinson 8 years ago
parent 71b53e816d
commit ef12eecb7e

@ -25,6 +25,7 @@ import java.net.URLStreamHandlerFactory;
import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContainerInitializer;
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
@ -69,12 +70,19 @@ class JasperInitializer extends AbstractLifeCycle {
if (this.initializer == null) { if (this.initializer == null) {
return; return;
} }
if (ClassUtils.isPresent(
"org.apache.catalina.webresources.TomcatURLStreamHandlerFactory",
getClass().getClassLoader())) {
TomcatURLStreamHandlerFactory.register();
}
else {
try { try {
URL.setURLStreamHandlerFactory(new WarUrlStreamHandlerFactory()); URL.setURLStreamHandlerFactory(new WarUrlStreamHandlerFactory());
} }
catch (Error ex) { catch (Error ex) {
// Ignore // Ignore
} }
}
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try { try {
Thread.currentThread().setContextClassLoader(this.context.getClassLoader()); Thread.currentThread().setContextClassLoader(this.context.getClassLoader());

Loading…
Cancel
Save