diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/MimeMappings.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/MimeMappings.java index bd30748615..3149d45485 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/MimeMappings.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/MimeMappings.java @@ -88,6 +88,7 @@ public final class MimeMappings implements Iterable { mappings.add("jpg", "image/jpeg"); mappings.add("js", "application/javascript"); mappings.add("jsf", "text/plain"); + mappings.add("json", "application/json"); mappings.add("jspf", "text/plain"); mappings.add("kar", "audio/midi"); mappings.add("latex", "application/x-latex"); @@ -111,6 +112,7 @@ public final class MimeMappings implements Iterable { mappings.add("mpega", "audio/x-mpeg"); mappings.add("mpg", "video/mpeg"); mappings.add("mpv2", "video/mpeg2"); + mappings.add("ms", "application/x-wais-source"); mappings.add("nc", "application/x-netcdf"); mappings.add("oda", "application/oda"); mappings.add("odb", "application/vnd.oasis.opendocument.database"); @@ -206,7 +208,6 @@ public final class MimeMappings implements Iterable { mappings.add("wmv", "video/x-ms-wmv"); mappings.add("wrl", "model/vrml"); mappings.add("wspolicy", "application/wspolicy+xml"); - mappings.add("Z", "application/x-compress"); mappings.add("z", "application/x-compress"); mappings.add("zip", "application/zip"); DEFAULT = unmodifiableMappings(mappings); @@ -373,6 +374,12 @@ public final class MimeMappings implements Iterable { return false; } + @Override + public String toString() { + return "Mapping [extension=" + this.extension + ", mimeType=" + this.mimeType + + "]"; + } + } } 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 b241484ac7..68fa246c68 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 @@ -28,9 +28,12 @@ import java.net.URISyntaxException; import java.nio.charset.Charset; import java.security.KeyStore; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.GZIPInputStream; @@ -77,6 +80,8 @@ import org.springframework.util.concurrent.ListenableFuture; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; +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.notNullValue; @@ -649,6 +654,25 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests { assertFalse(doTestCompression(10000, null, new String[] { "testUserAgent" })); } + @Test + public void mimeMappingsAreCorrectlyConfigured() throws Exception { + AbstractEmbeddedServletContainerFactory factory = getFactory(); + this.container = factory.getEmbeddedServletContainer(); + Map configuredMimeMappings = getActualMimeMappings(); + Set> entrySet = configuredMimeMappings.entrySet(); + Collection expectedMimeMappings = getExpectedMimeMappings(); + for (Entry entry : entrySet) { + assertThat(expectedMimeMappings, + hasItem(new MimeMappings.Mapping(entry.getKey(), entry.getValue()))); + } + for (MimeMappings.Mapping mapping : expectedMimeMappings) { + assertThat(configuredMimeMappings, + hasEntry(mapping.getExtension(), mapping.getMimeType())); + } + assertThat(configuredMimeMappings.size(), + is(equalTo(expectedMimeMappings.size()))); + } + private boolean doTestCompression(int contentSize, String[] mimeTypes, String[] excludedUserAgents) throws Exception { String testContent = setUpFactoryForCompression(contentSize, mimeTypes, @@ -687,6 +711,12 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests { return testContent; } + protected abstract Map getActualMimeMappings(); + + protected Collection getExpectedMimeMappings() { + return MimeMappings.DEFAULT.getAll(); + } + private void addTestTxtFile(AbstractEmbeddedServletContainerFactory factory) throws IOException { FileCopyUtils.copy("test", diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MimeMappingsTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/MimeMappingsTests.java index 7f2b9ae0b7..129fcef59f 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MimeMappingsTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/MimeMappingsTests.java @@ -21,22 +21,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.catalina.Context; -import org.apache.catalina.Wrapper; -import org.apache.catalina.startup.Tomcat; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willAnswer; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; /** * Tests for {@link MimeMappings}. @@ -48,11 +39,6 @@ public class MimeMappingsTests { @Rule public ExpectedException thrown = ExpectedException.none(); - @Test - public void defaults() throws Exception { - assertThat(MimeMappings.DEFAULT, equalTo(getTomatDefaults())); - } - @Test(expected = UnsupportedOperationException.class) public void defaultsCannotBeModified() throws Exception { MimeMappings.DEFAULT.add("foo", "foo/bar"); @@ -155,21 +141,4 @@ public class MimeMappingsTests { assertThat(unmodifiable.get("foo"), nullValue()); } - private MimeMappings getTomatDefaults() { - final MimeMappings mappings = new MimeMappings(); - Context ctx = mock(Context.class); - Wrapper wrapper = mock(Wrapper.class); - given(ctx.createWrapper()).willReturn(wrapper); - willAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - mappings.add((String) args[0], (String) args[1]); - return null; - } - }).given(ctx).addMimeMapping(anyString(), anyString()); - Tomcat.initWebappDefaults(ctx); - return mappings; - } - } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java index 4b5f5b9f50..f80fb62f7e 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java @@ -231,4 +231,11 @@ public class JettyEmbeddedServletContainerFactoryTests return context.getServletHandler().getServlet("jsp"); } + @Override + protected Map getActualMimeMappings() { + WebAppContext context = (WebAppContext) ((JettyEmbeddedServletContainer) this.container) + .getServer().getHandler(); + return context.getMimeTypes().getMimeMap(); + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactoryTests.java index cab29ba95f..aca9ddc80e 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactoryTests.java @@ -44,6 +44,7 @@ import org.mockito.InOrder; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests; import org.springframework.boot.context.embedded.EmbeddedServletContainerException; import org.springframework.boot.context.embedded.Ssl; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.SocketUtils; import static org.hamcrest.Matchers.equalTo; @@ -369,6 +370,15 @@ public class TomcatEmbeddedServletContainerFactoryTests return (Wrapper) context.findChild("jsp"); } + @SuppressWarnings("unchecked") + @Override + protected Map getActualMimeMappings() { + Context context = (Context) ((TomcatEmbeddedServletContainer) this.container) + .getTomcat().getHost().findChildren()[0]; + return (Map) ReflectionTestUtils.getField(context, + "mimeMappings"); + } + private void assertTimeout(TomcatEmbeddedServletContainerFactory factory, int expected) { Tomcat tomcat = getTomcat(factory); diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java index 65a3e0aefc..f393b2a245 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java @@ -17,10 +17,15 @@ package org.springframework.boot.context.embedded.undertow; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import io.undertow.Undertow.Builder; import io.undertow.servlet.api.DeploymentInfo; +import io.undertow.servlet.api.DeploymentManager; import org.junit.Test; import org.mockito.InOrder; @@ -28,8 +33,10 @@ import org.springframework.boot.context.embedded.AbstractEmbeddedServletContaine import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests; import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.boot.context.embedded.ExampleServlet; +import org.springframework.boot.context.embedded.MimeMappings.Mapping; import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.http.HttpStatus; +import org.springframework.test.util.ReflectionTestUtils; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; @@ -161,4 +168,20 @@ public class UndertowEmbeddedServletContainerFactoryTests return null; // Undertow does not support JSPs } + @Override + protected Map getActualMimeMappings() { + return ((DeploymentManager) ReflectionTestUtils.getField(this.container, + "manager")).getDeployment().getMimeExtensionMappings(); + } + + @Override + protected Collection getExpectedMimeMappings() { + // Unlike Tomcat and Jetty, Undertow performs a case-sensitive match on file + // extension so it has a mapping for "z" and "Z". + Set expectedMappings = new HashSet( + super.getExpectedMimeMappings()); + expectedMappings.add(new Mapping("Z", "application/x-compress")); + return expectedMappings; + } + }