From 89f8af4e6e7057bfaeb1ff01701fe191e7b7e1c8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 27 Oct 2015 13:41:38 +0000 Subject: [PATCH] Make the configuration of the document root consistent across containers Previously, if getValidDocumentRoot() returned null, only the embedded Tomcat container would use a temporary directory. This left Jetty and Undertow unable to provide a URL for the root of the servlet context, i.e. servletContext.getResource("/") would return null. This commit updates the embedded containers for Jetty and Undertow to behave in the same way as Tomcat. A test has been added to verify that all three containers can produce a non-null URL for the root of the servlet context. Closes gh-2878 --- ...stractEmbeddedServletContainerFactory.java | 21 ++++++++++++++++ .../JettyEmbeddedServletContainerFactory.java | 24 ++++++++---------- ...TomcatEmbeddedServletContainerFactory.java | 21 ---------------- ...dertowEmbeddedServletContainerFactory.java | 5 ++-- ...tEmbeddedServletContainerFactoryTests.java | 25 +++++++++++++++++++ 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactory.java index 547049719a..ec4e803351 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactory.java @@ -164,4 +164,25 @@ public abstract class AbstractEmbeddedServletContainerFactory return dir; } + /** + * Returns the absolute temp dir for given servlet container. + * @param prefix servlet container name + * @return The temp dir for given servlet container. + */ + protected File createTempDir(String prefix) { + try { + File tempFolder = File.createTempFile(prefix + ".", "." + getPort()); + tempFolder.delete(); + tempFolder.mkdir(); + tempFolder.deleteOnExit(); + return tempFolder; + } + catch (IOException ex) { + throw new EmbeddedServletContainerException( + "Unable to create tempdir. java.io.tmpdir is set to " + + System.getProperty("java.io.tmpdir"), + ex); + } + } + } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java index 6558a38dfc..eac6266695 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java @@ -319,22 +319,20 @@ public class JettyEmbeddedServletContainerFactory private void configureDocumentRoot(WebAppContext handler) { File root = getValidDocumentRoot(); - if (root != null) { - try { - if (!root.isDirectory()) { - Resource resource = JarResource - .newJarResource(Resource.newResource(root)); - handler.setBaseResource(resource); - } - else { - handler.setBaseResource( - Resource.newResource(root.getCanonicalFile())); - } + root = (root != null ? root : createTempDir("jetty-docbase")); + try { + if (!root.isDirectory()) { + Resource resource = JarResource + .newJarResource(Resource.newResource(root)); + handler.setBaseResource(resource); } - catch (Exception ex) { - throw new IllegalStateException(ex); + else { + handler.setBaseResource(Resource.newResource(root.getCanonicalFile())); } } + catch (Exception ex) { + throw new IllegalStateException(ex); + } } /** diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index 65e42b2cf9..6a20dde860 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -457,27 +457,6 @@ public class TomcatEmbeddedServletContainerFactory this.resourceLoader = resourceLoader; } - /** - * Returns the absolute temp dir for given web server. - * @param prefix webserver name - * @return The temp dir for given web server. - */ - protected File createTempDir(String prefix) { - try { - File tempFolder = File.createTempFile(prefix + ".", "." + getPort()); - tempFolder.delete(); - tempFolder.mkdir(); - tempFolder.deleteOnExit(); - return tempFolder; - } - catch (IOException ex) { - throw new EmbeddedServletContainerException( - "Unable to create Tomcat tempdir. java.io.tmpdir is set to " - + System.getProperty("java.io.tmpdir"), - ex); - } - } - /** * Set the Tomcat base directory. If not specified a temporary directory will be used. * @param baseDirectory the tomcat base directory diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java index 40a1b416c1..7f2a506385 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java @@ -428,10 +428,11 @@ public class UndertowEmbeddedServletContainerFactory private ResourceManager getDocumentRootResourceManager() { File root = getValidDocumentRoot(); - if (root != null && root.isDirectory()) { + root = (root != null ? root : createTempDir("undertow-docbase")); + if (root.isDirectory()) { return new FileResourceManager(root, 0); } - if (root != null && root.isFile()) { + if (root.isFile()) { return new JarResourcemanager(root); } return ResourceManager.EMPTY_RESOURCE_MANAGER; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java index 68fa246c68..47d6ed1f66 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java @@ -23,8 +23,10 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.nio.charset.Charset; import java.security.KeyStore; import java.util.Arrays; @@ -36,6 +38,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.zip.GZIPInputStream; import javax.net.ssl.SSLException; @@ -84,6 +87,7 @@ import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; @@ -673,6 +677,27 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests { is(equalTo(expectedMimeMappings.size()))); } + @Test + public void rootServletContextResource() throws Exception { + AbstractEmbeddedServletContainerFactory factory = getFactory(); + AtomicReference rootResource = new AtomicReference(); + this.container = factory + .getEmbeddedServletContainer(new ServletContextInitializer() { + @Override + public void onStartup(ServletContext servletContext) + throws ServletException { + try { + rootResource.set(servletContext.getResource("/")); + } + catch (MalformedURLException ex) { + throw new ServletException(ex); + } + } + }); + this.container.start(); + assertThat(rootResource.get(), is(not(nullValue()))); + } + private boolean doTestCompression(int contentSize, String[] mimeTypes, String[] excludedUserAgents) throws Exception { String testContent = setUpFactoryForCompression(contentSize, mimeTypes,