Drop Servlet 2.5 runtime compatibility
Issue: SPR-13189
This commit is contained in:
@@ -39,11 +39,6 @@ import org.springframework.util.CollectionUtils;
|
||||
*/
|
||||
public class ServletServerHttpResponse implements ServerHttpResponse {
|
||||
|
||||
/** Checking for Servlet 3.0+ HttpServletResponse.getHeader(String) */
|
||||
private static final boolean servlet3Present =
|
||||
ClassUtils.hasMethod(HttpServletResponse.class, "getHeader", String.class);
|
||||
|
||||
|
||||
private final HttpServletResponse servletResponse;
|
||||
|
||||
private final HttpHeaders headers;
|
||||
@@ -60,7 +55,7 @@ public class ServletServerHttpResponse implements ServerHttpResponse {
|
||||
public ServletServerHttpResponse(HttpServletResponse servletResponse) {
|
||||
Assert.notNull(servletResponse, "HttpServletResponse must not be null");
|
||||
this.servletResponse = servletResponse;
|
||||
this.headers = (servlet3Present ? new ServletResponseHttpHeaders() : new HttpHeaders());
|
||||
this.headers = new ServletResponseHttpHeaders();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -116,9 +115,9 @@ public class WebRequestDataBinder extends WebDataBinder {
|
||||
if (multipartRequest != null) {
|
||||
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
|
||||
}
|
||||
else if (ClassUtils.hasMethod(HttpServletRequest.class, "getParts")) {
|
||||
HttpServletRequest serlvetRequest = ((NativeWebRequest) request).getNativeRequest(HttpServletRequest.class);
|
||||
new Servlet3MultipartHelper(isBindEmptyMultipartFiles()).bindParts(serlvetRequest, mpvs);
|
||||
else {
|
||||
HttpServletRequest servletRequest = ((NativeWebRequest) request).getNativeRequest(HttpServletRequest.class);
|
||||
bindParts(servletRequest, mpvs);
|
||||
}
|
||||
}
|
||||
doBind(mpvs);
|
||||
@@ -133,6 +132,29 @@ public class WebRequestDataBinder extends WebDataBinder {
|
||||
return (contentType != null && StringUtils.startsWithIgnoreCase(contentType, "multipart"));
|
||||
}
|
||||
|
||||
private void bindParts(HttpServletRequest request, MutablePropertyValues mpvs) {
|
||||
try {
|
||||
MultiValueMap<String, Part> map = new LinkedMultiValueMap<String, Part>();
|
||||
for (Part part : request.getParts()) {
|
||||
map.add(part.getName(), part);
|
||||
}
|
||||
for (Map.Entry<String, List<Part>> entry: map.entrySet()) {
|
||||
if (entry.getValue().size() == 1) {
|
||||
Part part = entry.getValue().get(0);
|
||||
if (isBindEmptyMultipartFiles() || part.getSize() > 0) {
|
||||
mpvs.add(entry.getKey(), part);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mpvs.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MultipartException("Failed to get request parts", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats errors as fatal.
|
||||
* <p>Use this method only if it's an error if the input isn't valid.
|
||||
@@ -145,41 +167,4 @@ public class WebRequestDataBinder extends WebDataBinder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulate Part binding code for Servlet 3.0+ only containers.
|
||||
* @see javax.servlet.http.Part
|
||||
*/
|
||||
private static class Servlet3MultipartHelper {
|
||||
|
||||
private final boolean bindEmptyMultipartFiles;
|
||||
|
||||
public Servlet3MultipartHelper(boolean bindEmptyMultipartFiles) {
|
||||
this.bindEmptyMultipartFiles = bindEmptyMultipartFiles;
|
||||
}
|
||||
|
||||
public void bindParts(HttpServletRequest request, MutablePropertyValues mpvs) {
|
||||
try {
|
||||
MultiValueMap<String, Part> map = new LinkedMultiValueMap<String, Part>();
|
||||
for (Part part : request.getParts()) {
|
||||
map.add(part.getName(), part);
|
||||
}
|
||||
for (Map.Entry<String, List<Part>> entry: map.entrySet()) {
|
||||
if (entry.getValue().size() == 1) {
|
||||
Part part = entry.getValue().get(0);
|
||||
if (this.bindEmptyMultipartFiles || part.getSize() > 0) {
|
||||
mpvs.add(entry.getKey(), part);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mpvs.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MultipartException("Failed to get request parts", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,12 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -73,10 +71,6 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
||||
private static final Pattern ETAG_HEADER_VALUE_PATTERN = Pattern.compile("\\*|\\s*((W\\/)?(\"[^\"]*\"))\\s*,?");
|
||||
|
||||
|
||||
/** Checking for Servlet 3.0+ HttpServletResponse.getHeader(String) */
|
||||
private static final boolean servlet3Present =
|
||||
ClassUtils.hasMethod(HttpServletResponse.class, "getHeader", String.class);
|
||||
|
||||
private boolean notModified = false;
|
||||
|
||||
|
||||
@@ -283,19 +277,19 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
||||
|
||||
private boolean isCompatibleWithConditionalRequests(HttpServletResponse response) {
|
||||
try {
|
||||
if (response == null || !servlet3Present) {
|
||||
if (response == null) {
|
||||
// Can't check response.getStatus() - let's assume we're good
|
||||
return true;
|
||||
}
|
||||
return HttpStatus.valueOf(response.getStatus()).is2xxSuccessful();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHeaderAbsent(HttpServletResponse response, String header) {
|
||||
if (response == null || !servlet3Present) {
|
||||
if (response == null) {
|
||||
// Can't check response.getHeader(header) - let's assume it's not set
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.context.request.async;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* An {@code AsyncWebRequest} to use when there is no underlying async support.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class NoSupportAsyncWebRequest extends ServletWebRequest implements AsyncWebRequest {
|
||||
|
||||
public NoSupportAsyncWebRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
super(request, response);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addCompletionHandler(Runnable runnable) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimeout(Long timeout) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTimeoutHandler(Runnable runnable) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncStarted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Not supported
|
||||
|
||||
@Override
|
||||
public void startAsync() {
|
||||
throw new UnsupportedOperationException("No async support in a pre-Servlet 3.0 runtime");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncComplete() {
|
||||
throw new UnsupportedOperationException("No async support in a pre-Servlet 3.0 runtime");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch() {
|
||||
throw new UnsupportedOperationException("No async support in a pre-Servlet 3.0 runtime");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -20,7 +20,6 @@ import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
@@ -35,9 +34,6 @@ public abstract class WebAsyncUtils {
|
||||
|
||||
public static final String WEB_ASYNC_MANAGER_ATTRIBUTE = WebAsyncManager.class.getName() + ".WEB_ASYNC_MANAGER";
|
||||
|
||||
// Determine whether Servlet 3.0's ServletRequest.startAsync method is available
|
||||
private static final boolean startAsyncAvailable = ClassUtils.hasMethod(ServletRequest.class, "startAsync");
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the {@link WebAsyncManager} for the current request, or if not
|
||||
@@ -76,19 +72,7 @@ public abstract class WebAsyncUtils {
|
||||
* @return an AsyncWebRequest instance (never {@code null})
|
||||
*/
|
||||
public static AsyncWebRequest createAsyncWebRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
return (startAsyncAvailable ? AsyncWebRequestFactory.createStandardAsyncWebRequest(request, response) :
|
||||
new NoSupportAsyncWebRequest(request, response));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a hard dependency on the Servlet 3.0 API.
|
||||
*/
|
||||
private static class AsyncWebRequestFactory {
|
||||
|
||||
public static AsyncWebRequest createStandardAsyncWebRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
return new StandardServletAsyncWebRequest(request, response);
|
||||
}
|
||||
return new StandardServletAsyncWebRequest(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.web.filter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
@@ -29,7 +28,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
@@ -61,29 +59,30 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String STREAMING_ATTRIBUTE = ShallowEtagHeaderFilter.class.getName() + ".STREAMING";
|
||||
|
||||
/** Checking for Servlet 3.0+ HttpServletResponse.getHeader(String) */
|
||||
private static final boolean servlet3Present =
|
||||
ClassUtils.hasMethod(HttpServletResponse.class, "getHeader", String.class);
|
||||
|
||||
private boolean writeWeakETag = false;
|
||||
|
||||
/**
|
||||
* Set whether the ETag value written to the response should be weak, as per rfc7232.
|
||||
* <p>Should be configured using an {@code <init-param>} for parameter name
|
||||
* "writeWeakETag" in the filter definition in {@code web.xml}.
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7232#section-2.3">rfc7232 section-2.3</a>
|
||||
*/
|
||||
public boolean isWriteWeakETag() {
|
||||
return writeWeakETag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the ETag value written to the response should be weak, as per rfc7232.
|
||||
* Set whether the ETag value written to the response should be weak, as per RFC 7232.
|
||||
* <p>Should be configured using an {@code <init-param>} for parameter name
|
||||
* "writeWeakETag" in the filter definition in {@code web.xml}.
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7232#section-2.3">RFC 7232 section 2.3</a>
|
||||
* @since 4.3
|
||||
*/
|
||||
public void setWriteWeakETag(boolean writeWeakETag) {
|
||||
this.writeWeakETag = writeWeakETag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the ETag value written to the response should be weak, as per RFC 7232.
|
||||
* @since 4.3
|
||||
*/
|
||||
public boolean isWriteWeakETag() {
|
||||
return this.writeWeakETag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The default value is "false" so that the filter may delay the generation of
|
||||
* an ETag until the last asynchronously dispatched thread.
|
||||
@@ -169,10 +168,7 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
||||
if (responseStatusCode >= 200 && responseStatusCode < 300 &&
|
||||
(HttpMethod.GET.matches(method) || HttpMethod.HEAD.matches(method))) {
|
||||
|
||||
String cacheControl = null;
|
||||
if (servlet3Present) {
|
||||
cacheControl = response.getHeader(HEADER_CACHE_CONTROL);
|
||||
}
|
||||
String cacheControl = response.getHeader(HEADER_CACHE_CONTROL);
|
||||
if (cacheControl == null || !cacheControl.contains(DIRECTIVE_NO_STORE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
@@ -42,20 +40,6 @@ public abstract class MultipartResolutionDelegate {
|
||||
public static final Object UNRESOLVABLE = new Object();
|
||||
|
||||
|
||||
private static Class<?> servletPartClass = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
servletPartClass = ClassUtils.forName("javax.servlet.http.Part",
|
||||
MultipartResolutionDelegate.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Servlet 3.0 javax.servlet.http.Part type not available -
|
||||
// Part references simply not supported then.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMultipartRequest(HttpServletRequest request) {
|
||||
return (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null ||
|
||||
isMultipartContent(request));
|
||||
@@ -71,15 +55,7 @@ public abstract class MultipartResolutionDelegate {
|
||||
if (unwrapped != null) {
|
||||
return unwrapped;
|
||||
}
|
||||
return adaptToMultipartHttpServletRequest(request);
|
||||
}
|
||||
|
||||
private static MultipartHttpServletRequest adaptToMultipartHttpServletRequest(HttpServletRequest request) {
|
||||
if (servletPartClass != null) {
|
||||
// Servlet 3.0 available ..
|
||||
return new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
throw new MultipartException("Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
return new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,8 +63,7 @@ public abstract class MultipartResolutionDelegate {
|
||||
Class<?> paramType = parameter.getNestedParameterType();
|
||||
return (MultipartFile.class == paramType ||
|
||||
isMultipartFileCollection(parameter) || isMultipartFileArray(parameter) ||
|
||||
(servletPartClass != null && (servletPartClass == paramType ||
|
||||
isPartCollection(parameter) || isPartArray(parameter))));
|
||||
(Part.class == paramType || isPartCollection(parameter) || isPartArray(parameter)));
|
||||
}
|
||||
|
||||
public static Object resolveMultipartArgument(String name, MethodParameter parameter, HttpServletRequest request)
|
||||
@@ -100,19 +75,19 @@ public abstract class MultipartResolutionDelegate {
|
||||
|
||||
if (MultipartFile.class == parameter.getNestedParameterType()) {
|
||||
if (multipartRequest == null && isMultipart) {
|
||||
multipartRequest = adaptToMultipartHttpServletRequest(request);
|
||||
multipartRequest = new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
return (multipartRequest != null ? multipartRequest.getFile(name) : null);
|
||||
}
|
||||
else if (isMultipartFileCollection(parameter)) {
|
||||
if (multipartRequest == null && isMultipart) {
|
||||
multipartRequest = adaptToMultipartHttpServletRequest(request);
|
||||
multipartRequest = new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
return (multipartRequest != null ? multipartRequest.getFiles(name) : null);
|
||||
}
|
||||
else if (isMultipartFileArray(parameter)) {
|
||||
if (multipartRequest == null && isMultipart) {
|
||||
multipartRequest = adaptToMultipartHttpServletRequest(request);
|
||||
multipartRequest = new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
if (multipartRequest != null) {
|
||||
List<MultipartFile> multipartFiles = multipartRequest.getFiles(name);
|
||||
@@ -122,7 +97,7 @@ public abstract class MultipartResolutionDelegate {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (parameter.getNestedParameterType() == servletPartClass) {
|
||||
else if (Part.class == parameter.getNestedParameterType()) {
|
||||
return (isMultipart ? RequestPartResolver.resolvePart(request, name) : null);
|
||||
}
|
||||
else if (isPartCollection(parameter)) {
|
||||
@@ -145,11 +120,11 @@ public abstract class MultipartResolutionDelegate {
|
||||
}
|
||||
|
||||
private static boolean isPartCollection(MethodParameter methodParam) {
|
||||
return (servletPartClass == getCollectionParameterType(methodParam));
|
||||
return (Part.class == getCollectionParameterType(methodParam));
|
||||
}
|
||||
|
||||
private static boolean isPartArray(MethodParameter methodParam) {
|
||||
return (servletPartClass == methodParam.getNestedParameterType().getComponentType());
|
||||
return (Part.class == methodParam.getNestedParameterType().getComponentType());
|
||||
}
|
||||
|
||||
private static Class<?> getCollectionParameterType(MethodParameter methodParam) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -145,7 +145,6 @@ public class CookieGenerator {
|
||||
|
||||
/**
|
||||
* Set whether the cookie is supposed to be marked with the "HttpOnly" attribute.
|
||||
* <p>Note that this feature is only available on Servlet 3.0 and higher.
|
||||
* @see javax.servlet.http.Cookie#setHttpOnly
|
||||
*/
|
||||
public void setCookieHttpOnly(boolean cookieHttpOnly) {
|
||||
|
||||
Reference in New Issue
Block a user