From 436486b8a1cab5a37a415c7560ee6dea8014bf9b Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 30 Aug 2016 13:02:16 -0400 Subject: [PATCH] Relax ServletContext check for resource handling This is a follow-up on commit 3b95e0b relaxing the expectation that a ServletContext is present. Instead we check defensively and fall back on PathExtensionContentNegotiationStrategy which can use JAF. Issue: SPR-14577 --- .../resource/ResourceHttpRequestHandler.java | 25 +++++++++---------- .../ResourceHandlerRegistryTests.java | 2 ++ .../ResourceHttpRequestHandlerTests.java | 6 +++++ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java index 4603296ce02..e779bef52db 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; @@ -32,6 +31,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.core.io.Resource; import org.springframework.core.io.support.ResourceRegion; import org.springframework.http.HttpHeaders; @@ -91,7 +91,7 @@ import org.springframework.web.servlet.support.WebContentGenerator; * @since 3.0.4 */ public class ResourceHttpRequestHandler extends WebContentGenerator - implements HttpRequestHandler, InitializingBean, CorsConfigurationSource { + implements HttpRequestHandler, InitializingBean, SmartInitializingSingleton, CorsConfigurationSource { // Servlet 3.1 setContentLengthLong(long) available? private static final boolean contentLengthLongAvailable = @@ -112,9 +112,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator private ContentNegotiationManager contentNegotiationManager; - private ServletPathExtensionContentNegotiationStrategy pathExtensionStrategy; - - private ServletContext servletContext; + private PathExtensionContentNegotiationStrategy pathExtensionStrategy; private CorsConfiguration corsConfiguration; @@ -248,11 +246,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator return this.corsConfiguration; } - @Override - protected void initServletContext(ServletContext servletContext) { - this.servletContext = servletContext; - } - @Override public void afterPropertiesSet() throws Exception { @@ -270,7 +263,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator if (this.resourceRegionHttpMessageConverter == null) { this.resourceRegionHttpMessageConverter = new ResourceRegionHttpMessageConverter(); } - this.pathExtensionStrategy = initPathExtensionStrategy(); } /** @@ -293,7 +285,12 @@ public class ResourceHttpRequestHandler extends WebContentGenerator } } - protected ServletPathExtensionContentNegotiationStrategy initPathExtensionStrategy() { + @Override + public void afterSingletonsInstantiated() { + this.pathExtensionStrategy = initContentNegotiationStrategy(); + } + + protected PathExtensionContentNegotiationStrategy initContentNegotiationStrategy() { Map mediaTypes = null; if (getContentNegotiationManager() != null) { PathExtensionContentNegotiationStrategy strategy = @@ -302,7 +299,9 @@ public class ResourceHttpRequestHandler extends WebContentGenerator mediaTypes = new HashMap<>(strategy.getMediaTypes()); } } - return new ServletPathExtensionContentNegotiationStrategy(this.servletContext, mediaTypes); + return (getServletContext() != null) ? + new ServletPathExtensionContentNegotiationStrategy(getServletContext(), mediaTypes) : + new PathExtensionContentNegotiationStrategy(mediaTypes); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java index 66965ed569a..32e2f64366c 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java @@ -79,6 +79,8 @@ public class ResourceHandlerRegistryTests { request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/testStylesheet.css"); ResourceHttpRequestHandler handler = getHandler("/resources/**"); + handler.afterPropertiesSet(); + handler.afterSingletonsInstantiated(); handler.handleRequest(request, this.response); assertEquals("test stylesheet content", this.response.getContentAsString()); 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..1a5b74f55b7 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 @@ -81,6 +81,7 @@ public class ResourceHttpRequestHandlerTests { this.handler.setCacheSeconds(3600); this.handler.setServletContext(new TestServletContext()); this.handler.afterPropertiesSet(); + this.handler.afterSingletonsInstantiated(); this.request = new MockHttpServletRequest("GET", ""); this.response = new MockHttpServletResponse(); @@ -147,6 +148,7 @@ public class ResourceHttpRequestHandlerTests { .addFixedVersionStrategy("versionString", "/**"); this.handler.setResourceResolvers(Arrays.asList(versionResolver, new PathResourceResolver())); this.handler.afterPropertiesSet(); + this.handler.afterSingletonsInstantiated(); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "versionString/foo.css"); this.handler.handleRequest(this.request, this.response); @@ -253,6 +255,7 @@ public class ResourceHttpRequestHandlerTests { handler.setLocations(paths); handler.setContentNegotiationManager(manager); handler.afterPropertiesSet(); + handler.afterSingletonsInstantiated(); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); handler.handleRequest(this.request, this.response); @@ -274,6 +277,7 @@ public class ResourceHttpRequestHandlerTests { handler.setLocations(paths); handler.setContentNegotiationManager(manager); handler.afterPropertiesSet(); + handler.afterSingletonsInstantiated(); this.request.addHeader("Accept", "application/json,text/plain,*/*"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.html"); @@ -302,6 +306,7 @@ public class ResourceHttpRequestHandlerTests { handler.setServletContext(servletContext); handler.setLocations(paths); handler.afterPropertiesSet(); + handler.afterSingletonsInstantiated(); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); handler.handleRequest(this.request, this.response); @@ -416,6 +421,7 @@ public class ResourceHttpRequestHandlerTests { handler.setServletContext(new MockServletContext()); handler.setLocations(Arrays.asList(location1, location2)); handler.afterPropertiesSet(); + handler.afterSingletonsInstantiated(); Resource[] locations = pathResolver.getAllowedLocations(); assertEquals(1, locations.length);