SPR-7116 - Simplified (removed gzip and white-listing) and completed XML namespace config.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link BeanDefinitonParser}s that register an {@link HttpRequestHandler}.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @since 3.0.4
|
||||
*/
|
||||
public abstract class AbstractHttpRequestHandlerBeanDefinitionParser implements BeanDefinitionParser{
|
||||
|
||||
private static final String HANDLER_ADAPTER_BEAN_NAME = "org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
registerHandlerAdapterIfNecessary(parserContext, source);
|
||||
doParse(element, parserContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void doParse(Element element, ParserContext parserContext);
|
||||
|
||||
private void registerHandlerAdapterIfNecessary(ParserContext parserContext, Object source) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_ADAPTER_BEAN_NAME)) {
|
||||
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
|
||||
handlerAdapterDef.setSource(source);
|
||||
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
parserContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.web.servlet.resources.DefaultServletHttpRequestHandler;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} that parses a {@code default-servlet-handler} element to
|
||||
* register a {@link DefaultServletHttpRequestHandler}. Will also register a
|
||||
* {@link SimpleUrlHandlerMapping} for mapping resource requests, and a
|
||||
* {@link HttpRequestHandlerAdapter} if necessary.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @since 3.0.4
|
||||
*/
|
||||
public class DefaultServletHandlerBeanDefinitionParser extends AbstractHttpRequestHandlerBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
public void doParse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
String defaultServletName = element.getAttribute("default-servlet-name");
|
||||
RootBeanDefinition defaultServletHandlerDef = new RootBeanDefinition(DefaultServletHttpRequestHandler.class);
|
||||
defaultServletHandlerDef.setSource(source);
|
||||
defaultServletHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
if (StringUtils.hasText(defaultServletName)) {
|
||||
defaultServletHandlerDef.getPropertyValues().add("defaultServletName", defaultServletName);
|
||||
}
|
||||
String defaultServletHandlerName = parserContext.getReaderContext().generateBeanName(defaultServletHandlerDef);
|
||||
parserContext.getRegistry().registerBeanDefinition(defaultServletHandlerName, defaultServletHandlerDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(defaultServletHandlerDef, defaultServletHandlerName));
|
||||
|
||||
Map<String, String> urlMap = new ManagedMap<String, String>();
|
||||
urlMap.put("/**", defaultServletHandlerName);
|
||||
|
||||
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
|
||||
handlerMappingDef.setSource(source);
|
||||
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
|
||||
|
||||
String handlerMappingBeanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);
|
||||
parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,12 +23,14 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
* {@link NamespaceHandler} for Spring MVC configuration namespace.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Jeremy Grelle
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.web.servlet.resources.ResourceHttpRequestHandler;
|
||||
@@ -18,74 +20,66 @@ import org.w3c.dom.Element;
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
|
||||
* {@code resources} element to register a {@link ResourceHttpRequestHandler}.
|
||||
* Will also register a {@link SimpleUrlHandlerMapping} for mapping resource requests, if necessary.
|
||||
* Will also register a {@link HttpRequestHandlerAdapter} if necessary.
|
||||
* Will also register a {@link SimpleUrlHandlerMapping} for mapping resource requests,
|
||||
* and a {@link HttpRequestHandlerAdapter} if necessary.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Jeremy Grelle
|
||||
* @since 3.0.4
|
||||
*/
|
||||
public class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
public class ResourcesBeanDefinitionParser extends AbstractHttpRequestHandlerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String HANDLER_ADAPTER_BEAN_NAME = "org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter";
|
||||
|
||||
private static final String HANDLER_MAPPING_BEAN_NAME = "org.springframework.web.servlet.config.resourcesHandlerMapping";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
@Override
|
||||
public void doParse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
registerHandlerAdapterIfNecessary(parserContext, source);
|
||||
BeanDefinition handlerMappingDef = registerHandlerMappingIfNecessary(parserContext, source);
|
||||
|
||||
List<String> resourcePaths = new ManagedList<String>();
|
||||
resourcePaths.add("/");
|
||||
registerResourceMappings(parserContext, element, source);
|
||||
}
|
||||
|
||||
private void registerResourceMappings(ParserContext parserContext, Element element, Object source) {
|
||||
String resourceHandlerName = registerResourceHandler(parserContext, element, source);
|
||||
if (!StringUtils.hasText(resourceHandlerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String> urlMap = new ManagedMap<String, String>();
|
||||
String resourceRequestPath = element.getAttribute("mapping");
|
||||
if (!StringUtils.hasText(resourceRequestPath)) {
|
||||
parserContext.getReaderContext().error("The 'mapping' attribute is required.", parserContext.extractSource(element));
|
||||
return;
|
||||
}
|
||||
urlMap.put(resourceRequestPath, resourceHandlerName);
|
||||
|
||||
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
|
||||
handlerMappingDef.setSource(source);
|
||||
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
|
||||
|
||||
String mappingOrder = element.getAttribute("mapping-order");
|
||||
handlerMappingDef.getPropertyValues().add("order", StringUtils.hasText(mappingOrder) ? mappingOrder : Ordered.LOWEST_PRECEDENCE - 1);
|
||||
|
||||
String beanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);
|
||||
parserContext.getRegistry().registerBeanDefinition(beanName, handlerMappingDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, beanName));
|
||||
}
|
||||
|
||||
private String registerResourceHandler(ParserContext parserContext, Element element, Object source) {
|
||||
String locationAttr = element.getAttribute("location");
|
||||
if (!StringUtils.hasText(locationAttr)) {
|
||||
parserContext.getReaderContext().error("The 'location' attribute is required.", parserContext.extractSource(element));
|
||||
return "";
|
||||
}
|
||||
String[] locationPatterns = locationAttr.split(",\\s*");
|
||||
List<String> locations = new ManagedList<String>();
|
||||
for (String location : locationPatterns) {
|
||||
locations.add(location);
|
||||
}
|
||||
RootBeanDefinition resourceHandlerDef = new RootBeanDefinition(ResourceHttpRequestHandler.class);
|
||||
resourceHandlerDef.setSource(source);
|
||||
resourceHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
resourceHandlerDef.getConstructorArgumentValues().addIndexedArgumentValue(0, resourcePaths);
|
||||
|
||||
Map<String, BeanDefinition> urlMap = getUrlMap(handlerMappingDef);
|
||||
String resourceRequestPath = "/resources/**";
|
||||
urlMap.put(resourceRequestPath, resourceHandlerDef);
|
||||
|
||||
return null;
|
||||
resourceHandlerDef.getConstructorArgumentValues().addIndexedArgumentValue(0, locations);
|
||||
String beanName = parserContext.getReaderContext().generateBeanName(resourceHandlerDef);
|
||||
parserContext.getRegistry().registerBeanDefinition(beanName, resourceHandlerDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(resourceHandlerDef, beanName));
|
||||
return beanName;
|
||||
}
|
||||
|
||||
private void registerHandlerAdapterIfNecessary(ParserContext parserContext, Object source) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_ADAPTER_BEAN_NAME)) {
|
||||
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
|
||||
handlerAdapterDef.setSource(source);
|
||||
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
parserContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
private BeanDefinition registerHandlerMappingIfNecessary(ParserContext parserContext, Object source) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_MAPPING_BEAN_NAME)) {
|
||||
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
|
||||
handlerMappingDef.setSource(source);
|
||||
handlerMappingDef.getPropertyValues().add("order", "2");
|
||||
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
parserContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
|
||||
return handlerMappingDef;
|
||||
}
|
||||
else {
|
||||
return parserContext.getRegistry().getBeanDefinition(HANDLER_MAPPING_BEAN_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, BeanDefinition> getUrlMap(BeanDefinition handlerMappingDef) {
|
||||
Map<String, BeanDefinition> urlMap;
|
||||
if (handlerMappingDef.getPropertyValues().contains("urlMap")) {
|
||||
urlMap = (Map<String, BeanDefinition>) handlerMappingDef.getPropertyValues().getPropertyValue("urlMap").getValue();
|
||||
}
|
||||
else {
|
||||
urlMap = new ManagedMap<String, BeanDefinition>();
|
||||
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
|
||||
}
|
||||
return urlMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ import org.springframework.web.context.ServletContextAware;
|
||||
* can be matched.
|
||||
*
|
||||
* <p>Requests are handled by forwarding through the {@link RequestDispatcher} obtained via the name specified through the
|
||||
* {@code fileServletName} property. In most cases, the {@code fileServletName} does not need to be set explicitly, as the
|
||||
* {@code defaultServletName} property. In most cases, the {@code defaultServletName} does not need to be set explicitly, as the
|
||||
* handler checks at initialization time for the presence of the default Servlet of one of the known containers. However, if
|
||||
* running in a container where the default Servlet's name is not known, or where it has been customized via configuration, the
|
||||
* {@code fileServletName} will need to be set explicitly.
|
||||
* {@code defaultServletName} will need to be set explicitly.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @since 3.0.4
|
||||
@@ -55,40 +55,40 @@ public class DefaultServletHttpRequestHandler implements InitializingBean, HttpR
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
private String fileServletName;
|
||||
private String defaultServletName;
|
||||
|
||||
/**
|
||||
* If the {@code filedServletName} property has not been explicitly set, attempts to locate the default Servlet using the
|
||||
* known common container-specific names.
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (!StringUtils.hasText(this.fileServletName)) {
|
||||
if (!StringUtils.hasText(this.defaultServletName)) {
|
||||
if (this.servletContext.getNamedDispatcher(COMMON_DEFAULT_SERVLET_NAME) != null) {
|
||||
this.fileServletName = COMMON_DEFAULT_SERVLET_NAME;
|
||||
this.defaultServletName = COMMON_DEFAULT_SERVLET_NAME;
|
||||
} else if (this.servletContext.getNamedDispatcher(RESIN_DEFAULT_SERVLET_NAME) != null) {
|
||||
this.fileServletName = RESIN_DEFAULT_SERVLET_NAME;
|
||||
this.defaultServletName = RESIN_DEFAULT_SERVLET_NAME;
|
||||
} else if (this.servletContext.getNamedDispatcher(WEBLOGIC_DEFAULT_SERVLET_NAME) != null) {
|
||||
this.fileServletName = WEBLOGIC_DEFAULT_SERVLET_NAME;
|
||||
this.defaultServletName = WEBLOGIC_DEFAULT_SERVLET_NAME;
|
||||
} else if (this.servletContext.getNamedDispatcher(WEBSPHERE_DEFAULT_SERVLET_NAME) != null) {
|
||||
this.fileServletName = WEBSPHERE_DEFAULT_SERVLET_NAME;
|
||||
this.defaultServletName = WEBSPHERE_DEFAULT_SERVLET_NAME;
|
||||
}
|
||||
Assert.hasText(this.fileServletName, "Unable to locate the default servlet for serving static content. Please set the 'fileServletName' property explicitly.");
|
||||
Assert.hasText(this.defaultServletName, "Unable to locate the default servlet for serving static content. Please set the 'defaultServletName' property explicitly.");
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException {
|
||||
RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.fileServletName);
|
||||
Assert.notNull(rd, "A RequestDispatcher could not be located for the servlet name '"+this.fileServletName+"'");
|
||||
RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
|
||||
Assert.notNull(rd, "A RequestDispatcher could not be located for the servlet name '"+this.defaultServletName+"'");
|
||||
rd.forward(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the default Servlet to be forwarded to for static resource requests.
|
||||
* @param fileServletName The name of the Servlet to use for static resources.
|
||||
* @param defaultServletName The name of the Servlet to use for static resources.
|
||||
*/
|
||||
public void setDefaultServletName(String fileServletName) {
|
||||
this.fileServletName = fileServletName;
|
||||
public void setDefaultServletName(String defaultServletName) {
|
||||
this.defaultServletName = defaultServletName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.springframework.web.servlet.resources;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -8,18 +7,15 @@ import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -39,8 +35,7 @@ import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
|
||||
|
||||
/**
|
||||
* {@link HttpRequestHandler} that serves static resources optimized for superior browser performance
|
||||
* (according to the guidelines of Page Speed, YSlow, etc.) by adding far future cache expiration headers
|
||||
* and gzip compressing the resources if supported by the client.
|
||||
* (according to the guidelines of Page Speed, YSlow, etc.) by adding far future cache expiration headers.
|
||||
*
|
||||
* <p>TODO - expand the docs further
|
||||
*
|
||||
@@ -54,39 +49,14 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
|
||||
private final List<Resource> resourcePaths;
|
||||
|
||||
private int maxAge = 31556926;
|
||||
|
||||
private static final String defaultMediaTypes = "image/*,text/css,text/javascript,text/html";
|
||||
|
||||
private List<MediaType> allowedMediaTypes = new ArrayList<MediaType>();
|
||||
private final int maxAge = 31556926;
|
||||
|
||||
private FileMediaTypeMap fileMediaTypeMap;
|
||||
|
||||
private boolean gzipEnabled = true;
|
||||
|
||||
private int minGzipSize = 150;
|
||||
|
||||
private int maxGzipSize = 500000;
|
||||
|
||||
public ResourceHttpRequestHandler(List<Resource> resourcePaths) {
|
||||
this(resourcePaths, defaultMediaTypes);
|
||||
}
|
||||
|
||||
public ResourceHttpRequestHandler(List<Resource> resourcePaths, String allowedMediaTypes) {
|
||||
this(resourcePaths, allowedMediaTypes, false);
|
||||
}
|
||||
|
||||
public ResourceHttpRequestHandler(List<Resource> resourcePaths, String allowedMediaTypes, boolean overrideDefaultMediaTypes) {
|
||||
Assert.notNull(resourcePaths, "Resource paths must not be null");
|
||||
validateResourcePaths(resourcePaths);
|
||||
this.resourcePaths = resourcePaths;
|
||||
if (StringUtils.hasText(allowedMediaTypes)) {
|
||||
this.allowedMediaTypes.addAll(MediaType.parseMediaTypes(allowedMediaTypes));
|
||||
}
|
||||
if (!overrideDefaultMediaTypes) {
|
||||
this.allowedMediaTypes.addAll(MediaType.parseMediaTypes(defaultMediaTypes));
|
||||
}
|
||||
MediaType.sortBySpecificity(this.allowedMediaTypes);
|
||||
}
|
||||
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
@@ -95,7 +65,7 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
new String[] {"GET"}, "ResourceHttpRequestHandler only supports GET requests");
|
||||
}
|
||||
URLResource resource = getResource(request);
|
||||
if (resource == null || !isResourceAllowed(resource)) {
|
||||
if (resource == null) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
@@ -106,18 +76,6 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
writeResponse(resource, request, response);
|
||||
}
|
||||
|
||||
public void setGzipEnabled(boolean gzipEnabled) {
|
||||
this.gzipEnabled = gzipEnabled;
|
||||
}
|
||||
|
||||
public void setMinGzipSize(int minGzipSize) {
|
||||
this.minGzipSize = minGzipSize;
|
||||
}
|
||||
|
||||
public void setMaxGzipSize(int maxGzipSize) {
|
||||
this.maxGzipSize = maxGzipSize;
|
||||
}
|
||||
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.fileMediaTypeMap = new DefaultFileMediaTypeMap(servletContext);
|
||||
}
|
||||
@@ -167,18 +125,9 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
response.setHeader("Cache-Control", "max-age=" + this.maxAge);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isResourceAllowed(URLResource resource) {
|
||||
for(MediaType allowedType : allowedMediaTypes) {
|
||||
if (allowedType.includes(resource.getMediaType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void writeResponse(URLResource resource, HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
OutputStream out = selectOutputStream(resource, request, response);
|
||||
OutputStream out = response.getOutputStream();
|
||||
try {
|
||||
InputStream in = resource.getInputStream();
|
||||
try {
|
||||
@@ -199,19 +148,6 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
}
|
||||
}
|
||||
|
||||
private OutputStream selectOutputStream(URLResource resource, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
String acceptEncoding = request.getHeader("Accept-Encoding");
|
||||
boolean isGzipEligible = resource.getContentLength() >= this.minGzipSize && resource.getContentLength() <= this.maxGzipSize;
|
||||
if (this.gzipEnabled && isGzipEligible && StringUtils.hasText(acceptEncoding)
|
||||
&& acceptEncoding.indexOf("gzip") > -1
|
||||
&& response.getContentType().startsWith("text/")){
|
||||
return new GZIPResponseStream(response);
|
||||
} else {
|
||||
return response.getOutputStream();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidFile(Resource resource) throws IOException {
|
||||
return resource.exists() && StringUtils.hasText(resource.getFilename());
|
||||
}
|
||||
@@ -223,13 +159,11 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
}
|
||||
}
|
||||
|
||||
// TODO promote to top-level and make reusable
|
||||
|
||||
public interface FileMediaTypeMap {
|
||||
private interface FileMediaTypeMap {
|
||||
MediaType getMediaType(String fileName);
|
||||
}
|
||||
|
||||
public static class DefaultFileMediaTypeMap implements FileMediaTypeMap {
|
||||
private static class DefaultFileMediaTypeMap implements FileMediaTypeMap {
|
||||
|
||||
private static final boolean jafPresent =
|
||||
ClassUtils.isPresent("javax.activation.FileTypeMap", ContentNegotiatingViewResolver.class.getClassLoader());
|
||||
@@ -314,67 +248,6 @@ public class ResourceHttpRequestHandler implements HttpRequestHandler, ServletCo
|
||||
}
|
||||
}
|
||||
|
||||
private class GZIPResponseStream extends ServletOutputStream {
|
||||
|
||||
private ByteArrayOutputStream byteStream = null;
|
||||
|
||||
private GZIPOutputStream gzipStream = null;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private HttpServletResponse response = null;
|
||||
|
||||
private ServletOutputStream servletStream = null;
|
||||
|
||||
public GZIPResponseStream(HttpServletResponse response) throws IOException {
|
||||
super();
|
||||
closed = false;
|
||||
this.response = response;
|
||||
this.servletStream = response.getOutputStream();
|
||||
byteStream = new ByteArrayOutputStream();
|
||||
gzipStream = new GZIPOutputStream(byteStream);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("This output stream has already been closed");
|
||||
}
|
||||
gzipStream.finish();
|
||||
byte[] bytes = byteStream.toByteArray();
|
||||
response.setContentLength(bytes.length);
|
||||
response.addHeader("Content-Encoding", "gzip");
|
||||
servletStream.write(bytes);
|
||||
servletStream.flush();
|
||||
servletStream.close();
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Cannot flush a closed output stream");
|
||||
}
|
||||
gzipStream.flush();
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Cannot write to a closed output stream");
|
||||
}
|
||||
gzipStream.write((byte) b);
|
||||
}
|
||||
|
||||
public void write(byte b[]) throws IOException {
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Cannot write to a closed output stream");
|
||||
}
|
||||
gzipStream.write(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static class URLResource implements Resource {
|
||||
|
||||
private final Resource wrapped;
|
||||
|
||||
Reference in New Issue
Block a user