From ef12eecb7e282b0e499bdb267ddc00cd95c3aa33 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 11 May 2017 21:03:42 +0100 Subject: [PATCH] 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 --- .../web/embedded/jetty/JasperInitializer.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java b/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java index ffab66fe006..266b492d1a4 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JasperInitializer.java @@ -25,6 +25,7 @@ import java.net.URLStreamHandlerFactory; import javax.servlet.ServletContainerInitializer; +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.webapp.WebAppContext; @@ -69,11 +70,18 @@ class JasperInitializer extends AbstractLifeCycle { if (this.initializer == null) { return; } - try { - URL.setURLStreamHandlerFactory(new WarUrlStreamHandlerFactory()); + if (ClassUtils.isPresent( + "org.apache.catalina.webresources.TomcatURLStreamHandlerFactory", + getClass().getClassLoader())) { + TomcatURLStreamHandlerFactory.register(); } - catch (Error ex) { - // Ignore + else { + try { + URL.setURLStreamHandlerFactory(new WarUrlStreamHandlerFactory()); + } + catch (Error ex) { + // Ignore + } } ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try {