Backport selected refinements from the nullability efforts

Issue: SPR-15656
This commit is contained in:
Juergen Hoeller
2017-09-27 00:09:58 +02:00
parent 18a3322d2f
commit 9fdc4404a5
194 changed files with 1236 additions and 1218 deletions

View File

@@ -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">
* &#64;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;
}

View File

@@ -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);
}

View File

@@ -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();
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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) {

View File

@@ -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;
}
}
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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()));
}
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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
*/

View File

@@ -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