Backport selected refinements from the nullability efforts
Issue: SPR-15656
This commit is contained in:
@@ -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.
|
||||
@@ -50,6 +50,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Or, by using a builder accessible via static methods:
|
||||
* <pre class="code">
|
||||
* @RequestMapping("/handle")
|
||||
@@ -66,7 +67,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
|
||||
private final Object statusCode;
|
||||
private final Object status;
|
||||
|
||||
|
||||
/**
|
||||
@@ -104,7 +105,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
public ResponseEntity(T body, MultiValueMap<String, String> headers, HttpStatus status) {
|
||||
super(body, headers);
|
||||
Assert.notNull(status, "HttpStatus must not be null");
|
||||
this.statusCode = status;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,11 +113,11 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
* Just used behind the nested builder API.
|
||||
* @param body the entity body
|
||||
* @param headers the entity headers
|
||||
* @param statusCode the status code (as {@code HttpStatus} or as {@code Integer} value)
|
||||
* @param status the status code (as {@code HttpStatus} or as {@code Integer} value)
|
||||
*/
|
||||
private ResponseEntity(T body, MultiValueMap<String, String> headers, Object statusCode) {
|
||||
private ResponseEntity(T body, MultiValueMap<String, String> headers, Object status) {
|
||||
super(body, headers);
|
||||
this.statusCode = statusCode;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,11 +126,11 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
* @return the HTTP status as an HttpStatus enum entry
|
||||
*/
|
||||
public HttpStatus getStatusCode() {
|
||||
if (this.statusCode instanceof HttpStatus) {
|
||||
return (HttpStatus) this.statusCode;
|
||||
if (this.status instanceof HttpStatus) {
|
||||
return (HttpStatus) this.status;
|
||||
}
|
||||
else {
|
||||
return HttpStatus.valueOf((Integer) this.statusCode);
|
||||
return HttpStatus.valueOf((Integer) this.status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,11 +140,11 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
* @since 4.3
|
||||
*/
|
||||
public int getStatusCodeValue() {
|
||||
if (this.statusCode instanceof HttpStatus) {
|
||||
return ((HttpStatus) this.statusCode).value();
|
||||
if (this.status instanceof HttpStatus) {
|
||||
return ((HttpStatus) this.status).value();
|
||||
}
|
||||
else {
|
||||
return (Integer) this.statusCode;
|
||||
return (Integer) this.status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,21 +158,21 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
return false;
|
||||
}
|
||||
ResponseEntity<?> otherEntity = (ResponseEntity<?>) other;
|
||||
return ObjectUtils.nullSafeEquals(this.statusCode, otherEntity.statusCode);
|
||||
return ObjectUtils.nullSafeEquals(this.status, otherEntity.status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (super.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.statusCode));
|
||||
return (super.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.status));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("<");
|
||||
builder.append(this.statusCode.toString());
|
||||
if (this.statusCode instanceof HttpStatus) {
|
||||
builder.append(this.status.toString());
|
||||
if (this.status instanceof HttpStatus) {
|
||||
builder.append(' ');
|
||||
builder.append(((HttpStatus) this.statusCode).getReasonPhrase());
|
||||
builder.append(((HttpStatus) this.status).getReasonPhrase());
|
||||
}
|
||||
builder.append(',');
|
||||
T body = getBody();
|
||||
@@ -328,11 +329,11 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
|
||||
/**
|
||||
* Set the entity tag of the body, as specified by the {@code ETag} header.
|
||||
* @param eTag the new entity tag
|
||||
* @param etag the new entity tag
|
||||
* @return this builder
|
||||
* @see HttpHeaders#setETag(String)
|
||||
*/
|
||||
B eTag(String eTag);
|
||||
B eTag(String etag);
|
||||
|
||||
/**
|
||||
* Set the time the resource was last changed, as specified by the
|
||||
@@ -464,16 +465,16 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder eTag(String eTag) {
|
||||
if (eTag != null) {
|
||||
if (!eTag.startsWith("\"") && !eTag.startsWith("W/\"")) {
|
||||
eTag = "\"" + eTag;
|
||||
public BodyBuilder eTag(String etag) {
|
||||
if (etag != null) {
|
||||
if (!etag.startsWith("\"") && !etag.startsWith("W/\"")) {
|
||||
etag = "\"" + etag;
|
||||
}
|
||||
if (!eTag.endsWith("\"")) {
|
||||
eTag = eTag + "\"";
|
||||
if (!etag.endsWith("\"")) {
|
||||
etag = etag + "\"";
|
||||
}
|
||||
}
|
||||
this.headers.setETag(eTag);
|
||||
this.headers.setETag(etag);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -89,9 +89,9 @@ final class HttpComponentsStreamingClientHttpRequest extends AbstractClientHttpR
|
||||
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
|
||||
HttpComponentsClientHttpRequest.addHeaders(this.httpRequest, headers);
|
||||
|
||||
if (this.httpRequest instanceof HttpEntityEnclosingRequest && body != null) {
|
||||
if (this.httpRequest instanceof HttpEntityEnclosingRequest && this.body != null) {
|
||||
HttpEntityEnclosingRequest entityEnclosingRequest = (HttpEntityEnclosingRequest) this.httpRequest;
|
||||
HttpEntity requestEntity = new StreamingHttpEntity(getHeaders(), body);
|
||||
HttpEntity requestEntity = new StreamingHttpEntity(getHeaders(), this.body);
|
||||
entityEnclosingRequest.setEntity(requestEntity);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -37,81 +37,80 @@ import org.springframework.util.concurrent.ListenableFuture;
|
||||
*/
|
||||
class InterceptingAsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest {
|
||||
|
||||
private AsyncClientHttpRequestFactory requestFactory;
|
||||
private AsyncClientHttpRequestFactory requestFactory;
|
||||
|
||||
private List<AsyncClientHttpRequestInterceptor> interceptors;
|
||||
private List<AsyncClientHttpRequestInterceptor> interceptors;
|
||||
|
||||
private URI uri;
|
||||
private URI uri;
|
||||
|
||||
private HttpMethod httpMethod;
|
||||
private HttpMethod httpMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Creates new instance of {@link InterceptingAsyncClientHttpRequest}.
|
||||
*
|
||||
* @param requestFactory the async request factory
|
||||
* @param interceptors the list of interceptors
|
||||
* @param uri the request URI
|
||||
* @param httpMethod the HTTP method
|
||||
*/
|
||||
public InterceptingAsyncClientHttpRequest(AsyncClientHttpRequestFactory requestFactory,
|
||||
List<AsyncClientHttpRequestInterceptor> interceptors, URI uri, HttpMethod httpMethod) {
|
||||
/**
|
||||
* Create new instance of {@link InterceptingAsyncClientHttpRequest}.
|
||||
* @param requestFactory the async request factory
|
||||
* @param interceptors the list of interceptors
|
||||
* @param uri the request URI
|
||||
* @param httpMethod the HTTP method
|
||||
*/
|
||||
public InterceptingAsyncClientHttpRequest(AsyncClientHttpRequestFactory requestFactory,
|
||||
List<AsyncClientHttpRequestInterceptor> interceptors, URI uri, HttpMethod httpMethod) {
|
||||
|
||||
this.requestFactory = requestFactory;
|
||||
this.interceptors = interceptors;
|
||||
this.uri = uri;
|
||||
this.httpMethod = httpMethod;
|
||||
}
|
||||
this.requestFactory = requestFactory;
|
||||
this.interceptors = interceptors;
|
||||
this.uri = uri;
|
||||
this.httpMethod = httpMethod;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<ClientHttpResponse> executeInternal(HttpHeaders headers, byte[] body)
|
||||
throws IOException {
|
||||
@Override
|
||||
protected ListenableFuture<ClientHttpResponse> executeInternal(HttpHeaders headers, byte[] body)
|
||||
throws IOException {
|
||||
|
||||
return new AsyncRequestExecution().executeAsync(this, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return httpMethod;
|
||||
}
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return this.httpMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return uri;
|
||||
}
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
private class AsyncRequestExecution implements AsyncClientHttpRequestExecution {
|
||||
private class AsyncRequestExecution implements AsyncClientHttpRequestExecution {
|
||||
|
||||
private Iterator<AsyncClientHttpRequestInterceptor> iterator;
|
||||
private Iterator<AsyncClientHttpRequestInterceptor> iterator;
|
||||
|
||||
public AsyncRequestExecution() {
|
||||
this.iterator = interceptors.iterator();
|
||||
}
|
||||
public AsyncRequestExecution() {
|
||||
this.iterator = interceptors.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<ClientHttpResponse> executeAsync(HttpRequest request, byte[] body)
|
||||
throws IOException {
|
||||
@Override
|
||||
public ListenableFuture<ClientHttpResponse> executeAsync(HttpRequest request, byte[] body)
|
||||
throws IOException {
|
||||
|
||||
if (this.iterator.hasNext()) {
|
||||
AsyncClientHttpRequestInterceptor interceptor = this.iterator.next();
|
||||
return interceptor.intercept(request, body, this);
|
||||
}
|
||||
else {
|
||||
URI theUri = request.getURI();
|
||||
HttpMethod theMethod = request.getMethod();
|
||||
HttpHeaders theHeaders = request.getHeaders();
|
||||
if (this.iterator.hasNext()) {
|
||||
AsyncClientHttpRequestInterceptor interceptor = this.iterator.next();
|
||||
return interceptor.intercept(request, body, this);
|
||||
}
|
||||
else {
|
||||
URI uri = request.getURI();
|
||||
HttpMethod method = request.getMethod();
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
|
||||
AsyncClientHttpRequest delegate = requestFactory.createAsyncRequest(theUri, theMethod);
|
||||
delegate.getHeaders().putAll(theHeaders);
|
||||
if (body.length > 0) {
|
||||
StreamUtils.copy(body, delegate.getBody());
|
||||
}
|
||||
AsyncClientHttpRequest delegate = requestFactory.createAsyncRequest(uri, method);
|
||||
delegate.getHeaders().putAll(headers);
|
||||
if (body.length > 0) {
|
||||
StreamUtils.copy(body, delegate.getBody());
|
||||
}
|
||||
|
||||
return delegate.executeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
return delegate.executeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -20,9 +20,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpResponse} implementation based on OkHttp 3.x.
|
||||
@@ -36,7 +38,7 @@ class OkHttp3ClientHttpResponse extends AbstractClientHttpResponse {
|
||||
|
||||
private final Response response;
|
||||
|
||||
private HttpHeaders headers;
|
||||
private volatile HttpHeaders headers;
|
||||
|
||||
|
||||
public OkHttp3ClientHttpResponse(Response response) {
|
||||
@@ -57,13 +59,15 @@ class OkHttp3ClientHttpResponse extends AbstractClientHttpResponse {
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
return this.response.body().byteStream();
|
||||
ResponseBody body = this.response.body();
|
||||
return (body != null ? body.byteStream() : StreamUtils.emptyInput());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
if (this.headers == null) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
HttpHeaders headers = this.headers;
|
||||
if (headers == null) {
|
||||
headers = new HttpHeaders();
|
||||
for (String headerName : this.response.headers().names()) {
|
||||
for (String headerValue : this.response.headers(headerName)) {
|
||||
headers.add(headerName, headerValue);
|
||||
@@ -71,12 +75,15 @@ class OkHttp3ClientHttpResponse extends AbstractClientHttpResponse {
|
||||
}
|
||||
this.headers = headers;
|
||||
}
|
||||
return this.headers;
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.response.body().close();
|
||||
ResponseBody body = this.response.body();
|
||||
if (body != null) {
|
||||
body.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -65,8 +65,8 @@ public abstract class AbstractWireFeedHttpMessageConverter<T extends WireFeed> e
|
||||
|
||||
WireFeedInput feedInput = new WireFeedInput();
|
||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||
Charset charset =
|
||||
(contentType != null && contentType.getCharset() != null? contentType.getCharset() : DEFAULT_CHARSET);
|
||||
Charset charset = (contentType != null && contentType.getCharset() != null ?
|
||||
contentType.getCharset() : DEFAULT_CHARSET);
|
||||
try {
|
||||
Reader reader = new InputStreamReader(inputMessage.getBody(), charset);
|
||||
return (T) feedInput.build(reader);
|
||||
@@ -80,20 +80,17 @@ public abstract class AbstractWireFeedHttpMessageConverter<T extends WireFeed> e
|
||||
protected void writeInternal(T wireFeed, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
String wireFeedEncoding = wireFeed.getEncoding();
|
||||
if (!StringUtils.hasLength(wireFeedEncoding)) {
|
||||
wireFeedEncoding = DEFAULT_CHARSET.name();
|
||||
}
|
||||
Charset charset = (StringUtils.hasLength(wireFeed.getEncoding()) ?
|
||||
Charset.forName(wireFeed.getEncoding()) : DEFAULT_CHARSET);
|
||||
MediaType contentType = outputMessage.getHeaders().getContentType();
|
||||
if (contentType != null) {
|
||||
Charset wireFeedCharset = Charset.forName(wireFeedEncoding);
|
||||
contentType = new MediaType(contentType.getType(), contentType.getSubtype(), wireFeedCharset);
|
||||
contentType = new MediaType(contentType.getType(), contentType.getSubtype(), charset);
|
||||
outputMessage.getHeaders().setContentType(contentType);
|
||||
}
|
||||
|
||||
WireFeedOutput feedOutput = new WireFeedOutput();
|
||||
try {
|
||||
Writer writer = new OutputStreamWriter(outputMessage.getBody(), wireFeedEncoding);
|
||||
Writer writer = new OutputStreamWriter(outputMessage.getBody(), charset);
|
||||
feedOutput.output(wireFeed, writer);
|
||||
}
|
||||
catch (FeedException ex) {
|
||||
|
||||
@@ -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.
|
||||
@@ -87,7 +87,7 @@ public abstract class AbstractMappingContentNegotiationStrategy extends MappingM
|
||||
|
||||
/**
|
||||
* Extract a key from the request to use to look up media types.
|
||||
* @return the lookup key or {@code null}.
|
||||
* @return the lookup key, or {@code null} if none
|
||||
*/
|
||||
protected abstract String getMediaTypeKey(NativeWebRequest request);
|
||||
|
||||
@@ -110,4 +110,4 @@ public abstract class AbstractMappingContentNegotiationStrategy extends MappingM
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -38,6 +38,15 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
|
||||
private final ServletContext servletContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance without any mappings to start with. Mappings may be
|
||||
* added later when extensions are resolved through
|
||||
* {@link ServletContext#getMimeType(String)} or via JAF.
|
||||
*/
|
||||
public ServletPathExtensionContentNegotiationStrategy(ServletContext context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with the given extension-to-MediaType lookup.
|
||||
*/
|
||||
@@ -49,15 +58,6 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance without any mappings to start with. Mappings may be
|
||||
* added later when extensions are resolved through
|
||||
* {@link ServletContext#getMimeType(String)} or via JAF.
|
||||
*/
|
||||
public ServletPathExtensionContentNegotiationStrategy(ServletContext context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve file extension via {@link ServletContext#getMimeType(String)}
|
||||
@@ -88,7 +88,7 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
|
||||
* {@link PathExtensionContentNegotiationStrategy#getMediaTypeForResource}
|
||||
* with the ability to also look up through the ServletContext.
|
||||
* @param resource the resource to look up
|
||||
* @return the MediaType for the extension or {@code null}.
|
||||
* @return the MediaType for the extension, or {@code null} if none found
|
||||
* @since 4.3
|
||||
*/
|
||||
public MediaType getMediaTypeForResource(Resource resource) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.web.bind;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
@@ -47,9 +48,7 @@ public class EscapedErrors implements Errors {
|
||||
* Create a new EscapedErrors instance for the given source instance.
|
||||
*/
|
||||
public EscapedErrors(Errors source) {
|
||||
if (source == null) {
|
||||
throw new IllegalArgumentException("Cannot wrap a null instance");
|
||||
}
|
||||
Assert.notNull(source, "Errors source must not be null");
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -29,7 +29,7 @@ package org.springframework.web.context.request;
|
||||
public interface NativeWebRequest extends WebRequest {
|
||||
|
||||
/**
|
||||
* Return the underlying native request object, if available.
|
||||
* Return the underlying native request object.
|
||||
* @see javax.servlet.http.HttpServletRequest
|
||||
* @see javax.portlet.ActionRequest
|
||||
* @see javax.portlet.RenderRequest
|
||||
@@ -37,7 +37,7 @@ public interface NativeWebRequest extends WebRequest {
|
||||
Object getNativeRequest();
|
||||
|
||||
/**
|
||||
* Return the underlying native response object, if available.
|
||||
* Return the underlying native response object, if any.
|
||||
* @see javax.servlet.http.HttpServletResponse
|
||||
* @see javax.portlet.ActionResponse
|
||||
* @see javax.portlet.RenderResponse
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +28,6 @@ import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
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;
|
||||
@@ -229,7 +228,6 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
||||
}
|
||||
|
||||
boolean validated = validateIfNoneMatch(etag);
|
||||
|
||||
if (!validated) {
|
||||
validateIfModifiedSince(lastModifiedTimestamp);
|
||||
}
|
||||
@@ -286,6 +284,7 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
||||
if (!StringUtils.hasLength(etag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Enumeration<String> ifNoneMatch;
|
||||
try {
|
||||
ifNoneMatch = getRequest().getHeaders(IF_NONE_MATCH);
|
||||
@@ -296,21 +295,22 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
||||
if (!ifNoneMatch.hasMoreElements()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We will perform this validation...
|
||||
etag = padEtagIfNecessary(etag);
|
||||
while (ifNoneMatch.hasMoreElements()) {
|
||||
String clientETags = ifNoneMatch.nextElement();
|
||||
|
||||
Matcher eTagMatcher = ETAG_HEADER_VALUE_PATTERN.matcher(clientETags);
|
||||
Matcher etagMatcher = ETAG_HEADER_VALUE_PATTERN.matcher(clientETags);
|
||||
// Compare weak/strong ETags as per https://tools.ietf.org/html/rfc7232#section-2.3
|
||||
while (eTagMatcher.find()) {
|
||||
if (StringUtils.hasLength(eTagMatcher.group())
|
||||
&& etag.replaceFirst("^W/", "").equals(eTagMatcher.group(3))) {
|
||||
while (etagMatcher.find()) {
|
||||
if (StringUtils.hasLength(etagMatcher.group()) &&
|
||||
etag.replaceFirst("^W/", "").equals(etagMatcher.group(3))) {
|
||||
this.notModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -114,7 +114,7 @@ public class CharacterEncodingFilter extends OncePerRequestFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured encoding for requests and/or responses
|
||||
* Return the configured encoding for requests and/or responses.
|
||||
* @since 4.3
|
||||
*/
|
||||
public String getEncoding() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -115,7 +115,7 @@ public class DelegatingFilterProxy extends GenericFilterBean {
|
||||
* @see #setEnvironment(org.springframework.core.env.Environment)
|
||||
*/
|
||||
public DelegatingFilterProxy(Filter delegate) {
|
||||
Assert.notNull(delegate, "delegate Filter object must not be null");
|
||||
Assert.notNull(delegate, "Delegate Filter must not be null");
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public class DelegatingFilterProxy extends GenericFilterBean {
|
||||
* @see #setEnvironment(org.springframework.core.env.Environment)
|
||||
*/
|
||||
public DelegatingFilterProxy(String targetBeanName, WebApplicationContext wac) {
|
||||
Assert.hasText(targetBeanName, "target Filter bean name must not be null or empty");
|
||||
Assert.hasText(targetBeanName, "Target Filter bean name must not be null or empty");
|
||||
this.setTargetBeanName(targetBeanName);
|
||||
this.webApplicationContext = wac;
|
||||
if (wac != null) {
|
||||
@@ -246,15 +246,16 @@ public class DelegatingFilterProxy extends GenericFilterBean {
|
||||
Filter delegateToUse = this.delegate;
|
||||
if (delegateToUse == null) {
|
||||
synchronized (this.delegateMonitor) {
|
||||
if (this.delegate == null) {
|
||||
delegateToUse = this.delegate;
|
||||
if (delegateToUse == null) {
|
||||
WebApplicationContext wac = findWebApplicationContext();
|
||||
if (wac == null) {
|
||||
throw new IllegalStateException("No WebApplicationContext found: " +
|
||||
"no ContextLoaderListener or DispatcherServlet registered?");
|
||||
}
|
||||
this.delegate = initDelegate(wac);
|
||||
delegateToUse = initDelegate(wac);
|
||||
}
|
||||
delegateToUse = this.delegate;
|
||||
this.delegate = delegateToUse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.springframework.core.ExceptionDepthComparator;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.web.method.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
@@ -39,16 +39,18 @@ public class InitBinderDataBinderFactory extends DefaultDataBinderFactory {
|
||||
|
||||
private final List<InvocableHandlerMethod> binderMethods;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
* @param binderMethods {@code @InitBinder} methods, or {@code null}
|
||||
* @param initializer for global data binder intialization
|
||||
* Create a new InitBinderDataBinderFactory instance.
|
||||
* @param binderMethods {@code @InitBinder} methods
|
||||
* @param initializer for global data binder initialization
|
||||
*/
|
||||
public InitBinderDataBinderFactory(List<InvocableHandlerMethod> binderMethods, WebBindingInitializer initializer) {
|
||||
super(initializer);
|
||||
this.binderMethods = (binderMethods != null) ? binderMethods : new ArrayList<InvocableHandlerMethod>();
|
||||
this.binderMethods = (binderMethods != null ? binderMethods : Collections.<InvocableHandlerMethod>emptyList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a WebDataBinder with {@code @InitBinder} methods.
|
||||
* If the {@code @InitBinder} annotation specifies attributes names, it is
|
||||
@@ -61,22 +63,22 @@ public class InitBinderDataBinderFactory extends DefaultDataBinderFactory {
|
||||
if (isBinderMethodApplicable(binderMethod, binder)) {
|
||||
Object returnValue = binderMethod.invokeForRequest(request, null, binder);
|
||||
if (returnValue != null) {
|
||||
throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);
|
||||
throw new IllegalStateException(
|
||||
"@InitBinder methods should return void: " + binderMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the given {@code @InitBinder} method should be
|
||||
* invoked to initialize the given WebDataBinder.
|
||||
* <p>The default implementation checks if target object name is included
|
||||
* in the attribute names specified in the {@code @InitBinder} annotation.
|
||||
* Whether the given {@code @InitBinder} method should be used to initialize
|
||||
* the given WebDataBinder instance. By default we check the attributes
|
||||
* names of the annotation, if present.
|
||||
*/
|
||||
protected boolean isBinderMethodApplicable(HandlerMethod initBinderMethod, WebDataBinder binder) {
|
||||
InitBinder annot = initBinderMethod.getMethodAnnotation(InitBinder.class);
|
||||
Collection<String> names = Arrays.asList(annot.value());
|
||||
return (names.size() == 0 || names.contains(binder.getObjectName()));
|
||||
InitBinder ann = initBinderMethod.getMethodAnnotation(InitBinder.class);
|
||||
Collection<String> names = Arrays.asList(ann.value());
|
||||
return (names.isEmpty() || names.contains(binder.getObjectName()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.springframework.web.context.request.WebRequest;
|
||||
* {@link SessionStatus#setComplete()}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class SessionAttributesHandler {
|
||||
@@ -74,10 +75,7 @@ public class SessionAttributesHandler {
|
||||
this.attributeNames.addAll(Arrays.asList(annotation.names()));
|
||||
this.attributeTypes.addAll(Arrays.asList(annotation.types()));
|
||||
}
|
||||
|
||||
for (String attributeName : this.attributeNames) {
|
||||
this.knownAttributeNames.add(attributeName);
|
||||
}
|
||||
this.knownAttributeNames.addAll(this.attributeNames);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +88,7 @@ public class SessionAttributesHandler {
|
||||
|
||||
/**
|
||||
* Whether the attribute name or type match the names and types specified
|
||||
* via {@code @SessionAttributes} in underlying controller.
|
||||
* via {@code @SessionAttributes} on the underlying controller.
|
||||
* <p>Attributes successfully resolved through this method are "remembered"
|
||||
* and subsequently used in {@link #retrieveAttributes(WebRequest)} and
|
||||
* {@link #cleanupAttributes(WebRequest)}.
|
||||
@@ -117,7 +115,7 @@ public class SessionAttributesHandler {
|
||||
public void storeAttributes(WebRequest request, Map<String, ?> attributes) {
|
||||
for (String name : attributes.keySet()) {
|
||||
Object value = attributes.get(name);
|
||||
Class<?> attrType = (value != null) ? value.getClass() : null;
|
||||
Class<?> attrType = (value != null ? value.getClass() : null);
|
||||
if (isHandlerSessionAttribute(name, attrType)) {
|
||||
this.sessionAttributeStore.storeAttribute(request, name, value);
|
||||
}
|
||||
@@ -158,7 +156,7 @@ public class SessionAttributesHandler {
|
||||
* A pass-through call to the underlying {@link SessionAttributeStore}.
|
||||
* @param request the current request
|
||||
* @param attributeName the name of the attribute of interest
|
||||
* @return the attribute value or {@code null}
|
||||
* @return the attribute value, or {@code null} if none
|
||||
*/
|
||||
Object retrieveAttribute(WebRequest request, String attributeName) {
|
||||
return this.sessionAttributeStore.retrieveAttribute(request, attributeName);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 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.
|
||||
@@ -41,12 +41,12 @@ public interface UriComponentsContributor {
|
||||
|
||||
/**
|
||||
* Process the given method argument and either update the
|
||||
* {@link UriComponentsBuilder} or add to the map with URI variables to use to
|
||||
* expand the URI after all arguments are processed.
|
||||
* @param parameter the controller method parameter, never {@literal null}.
|
||||
* @param value the argument value, possibly {@literal null}.
|
||||
* @param builder the builder to update, never {@literal null}.
|
||||
* @param uriVariables a map to add URI variables to, never {@literal null}.
|
||||
* {@link UriComponentsBuilder} or add to the map with URI variables
|
||||
* to use to expand the URI after all arguments are processed.
|
||||
* @param parameter the controller method parameter (never {@code null})
|
||||
* @param value the argument value (possibly {@code null})
|
||||
* @param builder the builder to update (never {@code null})
|
||||
* @param uriVariables a map to add URI variables to (never {@code null})
|
||||
* @param conversionService a ConversionService to format values as Strings
|
||||
*/
|
||||
void contributeMethodArgument(MethodParameter parameter, Object value, UriComponentsBuilder builder,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -151,6 +151,10 @@ public abstract class CommonsFileUploadSupport {
|
||||
this.fileUpload.setHeaderEncoding(defaultEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the default encoding to use for parsing requests.
|
||||
* @see #setDefaultEncoding
|
||||
*/
|
||||
protected String getDefaultEncoding() {
|
||||
String encoding = getFileUpload().getHeaderEncoding();
|
||||
if (encoding == null) {
|
||||
@@ -172,6 +176,10 @@ public abstract class CommonsFileUploadSupport {
|
||||
this.uploadTempDirSpecified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the temporary directory where uploaded files get stored.
|
||||
* @see #setUploadTempDir
|
||||
*/
|
||||
protected boolean isUploadTempDirSpecified() {
|
||||
return this.uploadTempDirSpecified;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -33,7 +33,6 @@ public class JavaScriptUtils {
|
||||
|
||||
/**
|
||||
* Turn JavaScript special characters into escaped characters.
|
||||
*
|
||||
* @param input the input string
|
||||
* @return the string with escaped characters
|
||||
*/
|
||||
|
||||
@@ -70,6 +70,13 @@ public abstract class UriComponents implements Serializable {
|
||||
return this.scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fragment. Can be {@code null}.
|
||||
*/
|
||||
public final String getFragment() {
|
||||
return this.fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scheme specific part. Can be {@code null}.
|
||||
*/
|
||||
@@ -110,13 +117,6 @@ public abstract class UriComponents implements Serializable {
|
||||
*/
|
||||
public abstract MultiValueMap<String, String> getQueryParams();
|
||||
|
||||
/**
|
||||
* Return the fragment. Can be {@code null}.
|
||||
*/
|
||||
public final String getFragment() {
|
||||
return this.fragment;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode all URI components using their specific encoding rules, and returns the
|
||||
|
||||
Reference in New Issue
Block a user