From d414718467edf9edaed3a036f378c06117d224f6 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 15 Mar 2017 10:52:19 +0100 Subject: [PATCH] Update MockServletContext to MediaTypeFactory This commit changes the `MockServletContext.getMimeType` method to use `MediaTypeFactory` instead of JAF. It also adds a `addMimeType(String, MediaType)` method to customize the mime types returned from said method. Issue: SPR-14908 --- .../mock/web/MockServletContext.java | 46 ++++++++++--------- .../mock/web/MockServletContextTests.java | 16 +++---- .../mock/web/test/MockServletContext.java | 45 +++++++++--------- .../ResourceHttpRequestHandlerTests.java | 12 +++-- .../web/servlet/resource/test/foo.bar | 1 + 5 files changed, 64 insertions(+), 56 deletions(-) create mode 100644 spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/foo.bar diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java b/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java index 074ea5d6d71..cd5b8d87690 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java @@ -29,7 +29,6 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import javax.activation.FileTypeMap; import javax.servlet.Filter; import javax.servlet.FilterRegistration; import javax.servlet.RequestDispatcher; @@ -47,9 +46,12 @@ import org.apache.commons.logging.LogFactory; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; import org.springframework.web.util.WebUtils; /** @@ -136,6 +138,8 @@ public class MockServletContext implements ServletContext { private String responseCharacterEncoding; + private final Map mimeTypes = new LinkedHashMap<>(); + /** * Create a new {@code MockServletContext}, using no base path and a @@ -256,29 +260,27 @@ public class MockServletContext implements ServletContext { return this.effectiveMinorVersion; } - /** - * This method uses the default - * {@link javax.activation.FileTypeMap#getDefaultFileTypeMap() FileTypeMap} - * from the Java Activation Framework to resolve MIME types. - *

The Java Activation Framework returns {@code "application/octet-stream"} - * if the MIME type is unknown (i.e., it never returns {@code null}). Thus, in - * order to honor the {@link ServletContext#getMimeType(String)} contract, - * this method returns {@code null} if the MIME type is - * {@code "application/octet-stream"}. - *

{@code MockServletContext} does not provide a direct mechanism for - * setting a custom MIME type; however, if the default {@code FileTypeMap} - * is an instance of {@code javax.activation.MimetypesFileTypeMap}, a custom - * MIME type named {@code text/enigma} can be registered for a custom - * {@code .puzzle} file extension in the following manner: - *

-	 * MimetypesFileTypeMap mimetypesFileTypeMap = (MimetypesFileTypeMap) FileTypeMap.getDefaultFileTypeMap();
-	 * mimetypesFileTypeMap.addMimeTypes("text/enigma    puzzle");
-	 * 
- */ @Override public String getMimeType(String filePath) { - String mimeType = FileTypeMap.getDefaultFileTypeMap().getContentType(filePath); - return ("application/octet-stream".equals(mimeType) ? null : mimeType); + String extension = StringUtils.getFilenameExtension(filePath); + MediaType result; + if (this.mimeTypes.containsKey(extension)) { + result = this.mimeTypes.get(extension); + } + else { + result = MediaTypeFactory.getMediaType(filePath); + } + return result != null ? result.toString() : null; + } + + /** + * Adds a mime type mapping for use by {@link #getMimeType(String)}. + * @param fileExtension a file extension, such as {@code txt}, {@code gif} + * @param mimeType the mime type + */ + public void addMimeType(String fileExtension, MediaType mimeType) { + Assert.notNull(fileExtension, "'fileExtension' must not be null"); + this.mimeTypes.put(fileExtension, mimeType); } @Override diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockServletContextTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockServletContextTests.java index 9e7dff48cf7..acc7081ec0f 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockServletContextTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockServletContextTests.java @@ -18,16 +18,19 @@ package org.springframework.mock.web; import java.util.Map; import java.util.Set; -import javax.activation.FileTypeMap; -import javax.activation.MimetypesFileTypeMap; import javax.servlet.FilterRegistration; import javax.servlet.RequestDispatcher; import javax.servlet.ServletRegistration; import org.junit.Test; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; +import org.springframework.http.MediaType; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; /** * @author Juergen Hoeller @@ -87,10 +90,7 @@ public class MockServletContextTests { */ @Test public void getMimeTypeWithCustomConfiguredType() { - FileTypeMap defaultFileTypeMap = FileTypeMap.getDefaultFileTypeMap(); - assertThat(defaultFileTypeMap, instanceOf(MimetypesFileTypeMap.class)); - MimetypesFileTypeMap mimetypesFileTypeMap = (MimetypesFileTypeMap) defaultFileTypeMap; - mimetypesFileTypeMap.addMimeTypes("text/enigma enigma"); + sc.addMimeType("enigma", new MediaType("text", "enigma")); assertEquals("text/enigma", sc.getMimeType("filename.enigma")); } diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockServletContext.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockServletContext.java index 86dcd8965e0..eb0bc996b7e 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockServletContext.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockServletContext.java @@ -29,7 +29,6 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import javax.activation.FileTypeMap; import javax.servlet.Filter; import javax.servlet.FilterRegistration; import javax.servlet.RequestDispatcher; @@ -47,9 +46,12 @@ import org.apache.commons.logging.LogFactory; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; import org.springframework.web.util.WebUtils; /** @@ -136,6 +138,7 @@ public class MockServletContext implements ServletContext { private String responseCharacterEncoding; + private final Map mimeTypes = new LinkedHashMap<>(); /** * Create a new {@code MockServletContext}, using no base path and a @@ -256,29 +259,27 @@ public class MockServletContext implements ServletContext { return this.effectiveMinorVersion; } - /** - * This method uses the default - * {@link javax.activation.FileTypeMap#getDefaultFileTypeMap() FileTypeMap} - * from the Java Activation Framework to resolve MIME types. - *

The Java Activation Framework returns {@code "application/octet-stream"} - * if the MIME type is unknown (i.e., it never returns {@code null}). Thus, in - * order to honor the {@link ServletContext#getMimeType(String)} contract, - * this method returns {@code null} if the MIME type is - * {@code "application/octet-stream"}. - *

{@code MockServletContext} does not provide a direct mechanism for - * setting a custom MIME type; however, if the default {@code FileTypeMap} - * is an instance of {@code javax.activation.MimetypesFileTypeMap}, a custom - * MIME type named {@code text/enigma} can be registered for a custom - * {@code .puzzle} file extension in the following manner: - *

-	 * MimetypesFileTypeMap mimetypesFileTypeMap = (MimetypesFileTypeMap) FileTypeMap.getDefaultFileTypeMap();
-	 * mimetypesFileTypeMap.addMimeTypes("text/enigma    puzzle");
-	 * 
- */ @Override public String getMimeType(String filePath) { - String mimeType = FileTypeMap.getDefaultFileTypeMap().getContentType(filePath); - return ("application/octet-stream".equals(mimeType) ? null : mimeType); + String extension = StringUtils.getFilenameExtension(filePath); + MediaType result; + if (this.mimeTypes.containsKey(extension)) { + result = this.mimeTypes.get(extension); + } + else { + result = MediaTypeFactory.getMediaType(filePath); + } + return result != null ? result.toString() : null; + } + + /** + * Adds a mime type mapping for use by {@link #getMimeType(String)}. + * @param fileExtension a file extension, such as {@code txt}, {@code gif} + * @param mimeType the mime type + */ + public void addMimeType(String fileExtension, MediaType mimeType) { + Assert.notNull(fileExtension, "'fileExtension' must not be null"); + this.mimeTypes.put(fileExtension, mimeType); } @Override diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java index e835aff8c15..cd174d35fa0 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,11 @@ import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.accept.ContentNegotiationManagerFactoryBean; import org.springframework.web.servlet.HandlerMapping; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * Unit tests for ResourceHttpRequestHandler. @@ -243,7 +247,7 @@ public class ResourceHttpRequestHandlerTests { @Test // SPR-13658 public void getResourceWithRegisteredMediaType() throws Exception { ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean(); - factory.addMediaType("css", new MediaType("foo", "bar")); + factory.addMediaType("bar", new MediaType("foo", "bar")); factory.afterPropertiesSet(); ContentNegotiationManager manager = factory.getObject(); @@ -254,7 +258,7 @@ public class ResourceHttpRequestHandlerTests { handler.setContentNegotiationManager(manager); handler.afterPropertiesSet(); - this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); + this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.bar"); handler.handleRequest(this.request, this.response); assertEquals("foo/bar", this.response.getContentType()); diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/foo.bar b/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/foo.bar new file mode 100644 index 00000000000..e2f0b1c742a --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/foo.bar @@ -0,0 +1 @@ +h1 { color:red; } \ No newline at end of file