Consistent use of @Nullable across the codebase (even for internals)

Beyond just formally declaring the current behavior, this revision actually enforces non-null behavior in selected signatures now, not tolerating null values anymore when not explicitly documented. It also changes some utility methods with historic null-in/null-out tolerance towards enforced non-null return values, making them a proper citizen in non-null assignments.

Some issues are left as to-do: in particular a thorough revision of spring-test, and a few tests with unclear failures (ignored as "TODO: NULLABLE") to be sorted out in a follow-up commit.

Issue: SPR-15540
This commit is contained in:
Juergen Hoeller
2017-06-07 14:17:48 +02:00
parent ffc3f6d87d
commit f813712f5b
1493 changed files with 10670 additions and 9172 deletions

View File

@@ -22,14 +22,16 @@ import java.nio.charset.StandardCharsets;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import static java.nio.charset.StandardCharsets.*;
/**
* Represent the content disposition type and parameters as defined in RFC 2183.
* Represent the Content-Disposition type and parameters as defined in RFC 2183.
*
* @author Sebastien Deleuze
* @author Juergen Hoeller
* @since 5.0
* @see <a href="https://tools.ietf.org/html/rfc2183">RFC 2183</a>
*/
@@ -49,7 +51,9 @@ public class ContentDisposition {
/**
* Private constructor. See static factory methods in this class.
*/
private ContentDisposition(@Nullable String type, @Nullable String name, @Nullable String filename, @Nullable Charset charset, @Nullable Long size) {
private ContentDisposition(@Nullable String type, @Nullable String name, @Nullable String filename,
@Nullable Charset charset, @Nullable Long size) {
this.type = type;
this.name = name;
this.filename = filename;
@@ -115,7 +119,7 @@ public class ContentDisposition {
* Return an empty content disposition.
*/
public static ContentDisposition empty() {
return new ContentDisposition(null, null, null, null, null);
return new ContentDisposition("", null, null, null, null);
}
/**
@@ -209,36 +213,28 @@ public class ContentDisposition {
}
@Override
public boolean equals(Object o) {
if (this == o) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (o == null || getClass() != o.getClass()) {
if (!(other instanceof ContentDisposition)) {
return false;
}
ContentDisposition that = (ContentDisposition) o;
if (type != null ? !type.equals(that.type) : that.type != null) {
return false;
}
if (name != null ? !name.equals(that.name) : that.name != null) {
return false;
}
if (filename != null ? !filename.equals(that.filename) : that.filename != null) {
return false;
}
if (charset != null ? !charset.equals(that.charset) : that.charset != null) {
return false;
}
return size != null ? size.equals(that.size) : that.size == null;
ContentDisposition otherCd = (ContentDisposition) other;
return (ObjectUtils.nullSafeEquals(this.type, otherCd.type) &&
ObjectUtils.nullSafeEquals(this.name, otherCd.name) &&
ObjectUtils.nullSafeEquals(this.filename, otherCd.filename) &&
ObjectUtils.nullSafeEquals(this.charset, otherCd.charset) &&
ObjectUtils.nullSafeEquals(this.size, otherCd.size));
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (filename != null ? filename.hashCode() : 0);
result = 31 * result + (charset != null ? charset.hashCode() : 0);
result = 31 * result + (size != null ? size.hashCode() : 0);
int result = ObjectUtils.nullSafeHashCode(this.type);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.name);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.filename);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.charset);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.size);
return result;
}
@@ -248,26 +244,29 @@ public class ContentDisposition {
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder(this.type);
StringBuilder sb = new StringBuilder();
if (this.type != null) {
sb.append(this.type);
}
if (this.name != null) {
builder.append("; name=\"");
builder.append(this.name).append('\"');
sb.append("; name=\"");
sb.append(this.name).append('\"');
}
if (this.filename != null) {
if(this.charset == null || StandardCharsets.US_ASCII.equals(this.charset)) {
builder.append("; filename=\"");
builder.append(this.filename).append('\"');
sb.append("; filename=\"");
sb.append(this.filename).append('\"');
}
else {
builder.append("; filename*=");
builder.append(encodeHeaderFieldParam(this.filename, this.charset));
sb.append("; filename*=");
sb.append(encodeHeaderFieldParam(this.filename, this.charset));
}
}
if (this.size != null) {
builder.append("; size=");
builder.append(this.size);
sb.append("; size=");
sb.append(this.size);
}
return builder.toString();
return sb.toString();
}
/**

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.
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -33,7 +35,7 @@ public class HttpCookie {
private final String value;
public HttpCookie(String name, String value) {
public HttpCookie(String name, @Nullable String value) {
Assert.hasLength(name, "'name' is required and must not be empty.");
this.name = name;
this.value = (value != null ? value : "");
@@ -47,7 +49,7 @@ public class HttpCookie {
}
/**
* Return the cookie value or an empty string, never {@code null}.
* Return the cookie value or an empty string (never {@code null}).
*/
public String getValue() {
return this.value;

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.
@@ -16,6 +16,7 @@
package org.springframework.http;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
@@ -94,7 +95,7 @@ public class HttpEntity<T> {
* @param body the entity body
* @param headers the entity headers
*/
public HttpEntity(T body, MultiValueMap<String, String> headers) {
public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers) {
this.body = body;
HttpHeaders tempHeaders = new HttpHeaders();
if (headers != null) {
@@ -114,6 +115,7 @@ public class HttpEntity<T> {
/**
* Returns the body of this entity.
*/
@Nullable
public T getBody() {
return this.body;
}
@@ -127,7 +129,7 @@ public class HttpEntity<T> {
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}

View File

@@ -467,7 +467,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
*/
public List<Locale.LanguageRange> getAcceptLanguage() {
String value = getFirst(ACCEPT_LANGUAGE);
return StringUtils.hasText(value) ? Locale.LanguageRange.parse(value) : Collections.emptyList();
return (StringUtils.hasText(value) ? Locale.LanguageRange.parse(value) : Collections.emptyList());
}
/**
@@ -560,6 +560,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Return the value of the {@code Access-Control-Allow-Origin} response header.
*/
@Nullable
public String getAccessControlAllowOrigin() {
return getFieldValues(ACCESS_CONTROL_ALLOW_ORIGIN);
}
@@ -618,6 +619,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Return the value of the {@code Access-Control-Request-Method} request header.
*/
@Nullable
public HttpMethod getAccessControlRequestMethod() {
return HttpMethod.resolve(getFirst(ACCESS_CONTROL_REQUEST_METHOD));
}
@@ -708,6 +710,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Return the value of the {@code Cache-Control} header.
*/
@Nullable
public String getCacheControl() {
return getFieldValues(CACHE_CONTROL);
}
@@ -759,9 +762,16 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
*/
public void setContentDispositionFormData(String name, @Nullable String filename, @Nullable Charset charset) {
Assert.notNull(name, "'name' must not be null");
ContentDisposition disposition = ContentDisposition.builder("form-data")
.name(name).filename(filename, charset).build();
setContentDisposition(disposition);
ContentDisposition.Builder disposition = ContentDisposition.builder("form-data").name(name);
if (filename != null) {
if (charset != null) {
disposition.filename(filename, charset);
}
else {
disposition.filename(filename);
}
}
setContentDisposition(disposition.build());
}
/**
@@ -884,18 +894,17 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Set the (new) entity tag of the body, as specified by the {@code ETag} header.
*/
public void setETag(String eTag) {
if (eTag != null) {
Assert.isTrue(eTag.startsWith("\"") || eTag.startsWith("W/"),
"Invalid eTag, does not start with W/ or \"");
Assert.isTrue(eTag.endsWith("\""), "Invalid eTag, does not end with \"");
}
set(ETAG, eTag);
public void setETag(String etag) {
Assert.isTrue(etag.startsWith("\"") || etag.startsWith("W/"),
"Invalid ETag: does not start with W/ or \"");
Assert.isTrue(etag.endsWith("\""), "Invalid ETag: does not end with \"");
set(ETAG, etag);
}
/**
* Return the entity tag of the body, as specified by the {@code ETag} header.
*/
@Nullable
public String getETag() {
return getFirst(ETAG);
}
@@ -1096,6 +1105,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Return the value of the {@code Origin} header.
*/
@Nullable
public String getOrigin() {
return getFirst(ORIGIN);
}
@@ -1110,6 +1120,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Return the value of the {@code Pragma} header.
*/
@Nullable
public String getPragma() {
return getFirst(PRAGMA);
}
@@ -1141,6 +1152,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/**
* Return the value of the {@code Upgrade} header.
*/
@Nullable
public String getUpgrade() {
return getFirst(UPGRADE);
}
@@ -1288,6 +1300,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* @return the combined result
* @since 4.3
*/
@Nullable
protected String getFieldValues(String headerName) {
List<String> headerValues = get(headerName);
return (headerValues != null ? toCommaDelimitedString(headerValues) : null);
@@ -1399,6 +1412,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
}
@Override
@Nullable
public List<String> get(Object key) {
return this.headers.get(key);
}

View File

@@ -51,7 +51,7 @@ public enum HttpMethod {
* @since 4.2.4
*/
@Nullable
public static HttpMethod resolve(String method) {
public static HttpMethod resolve(@Nullable String method) {
return (method != null ? mappings.get(method) : null);
}

View File

@@ -124,7 +124,7 @@ public abstract class HttpRange {
* @return the list of ranges
* @throws IllegalArgumentException if the string cannot be parsed
*/
public static List<HttpRange> parseRanges(String ranges) {
public static List<HttpRange> parseRanges(@Nullable String ranges) {
if (!StringUtils.hasLength(ranges)) {
return Collections.emptyList();
}
@@ -220,7 +220,7 @@ public abstract class HttpRange {
this.lastPos = lastPos;
}
private void assertPositions(long firstBytePos, Long lastBytePos) {
private void assertPositions(long firstBytePos, @Nullable Long lastBytePos) {
if (firstBytePos < 0) {
throw new IllegalArgumentException("Invalid first byte position: " + firstBytePos);
}

View File

@@ -425,7 +425,7 @@ public class MediaType extends MimeType implements Serializable {
* @param other the reference media type with which to compare
* @return {@code true} if this media type includes the given media type; {@code false} otherwise
*/
public boolean includes(MediaType other) {
public boolean includes(@Nullable MediaType other) {
return super.includes(other);
}
@@ -436,7 +436,7 @@ public class MediaType extends MimeType implements Serializable {
* @param other the reference media type with which to compare
* @return {@code true} if this media type is compatible with the given media type; {@code false} otherwise
*/
public boolean isCompatibleWith(MediaType other) {
public boolean isCompatibleWith(@Nullable MediaType other) {
return super.isCompatibleWith(other);
}
@@ -529,7 +529,7 @@ public class MediaType extends MimeType implements Serializable {
* @throws InvalidMediaTypeException if the media type value cannot be parsed
* @since 4.3.2
*/
public static List<MediaType> parseMediaTypes(List<String> mediaTypes) {
public static List<MediaType> parseMediaTypes(@Nullable List<String> mediaTypes) {
if (CollectionUtils.isEmpty(mediaTypes)) {
return Collections.emptyList();
}

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.
@@ -27,8 +27,7 @@ import org.springframework.util.ObjectUtils;
/**
* Extension of {@link HttpEntity} that adds a {@linkplain HttpMethod method} and
* {@linkplain URI uri}.
* Used in {@code RestTemplate} and {@code @Controller} methods.
* {@linkplain URI uri}. Used in {@code RestTemplate} and {@code @Controller} methods.
*
* <p>In {@code RestTemplate}, this class is used as parameter in
* {@link org.springframework.web.client.RestTemplate#exchange(RequestEntity, Class) exchange()}:
@@ -76,7 +75,7 @@ public class RequestEntity<T> extends HttpEntity<T> {
* @param url the URL
*/
public RequestEntity(HttpMethod method, URI url) {
this(null, null, method, url);
this(null, null, method, url, null);
}
/**
@@ -85,7 +84,7 @@ public class RequestEntity<T> extends HttpEntity<T> {
* @param method the method
* @param url the URL
*/
public RequestEntity(T body, HttpMethod method, URI url) {
public RequestEntity(@Nullable T body, HttpMethod method, URI url) {
this(body, null, method, url, null);
}
@@ -97,7 +96,7 @@ public class RequestEntity<T> extends HttpEntity<T> {
* @param type the type used for generic type resolution
* @since 4.3
*/
public RequestEntity(T body, HttpMethod method, URI url, Type type) {
public RequestEntity(@Nullable T body, HttpMethod method, URI url, Type type) {
this(body, null, method, url, type);
}
@@ -118,7 +117,9 @@ public class RequestEntity<T> extends HttpEntity<T> {
* @param method the method
* @param url the URL
*/
public RequestEntity(T body, MultiValueMap<String, String> headers, HttpMethod method, URI url) {
public RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers,
@Nullable HttpMethod method, URI url) {
this(body, headers, method, url, null);
}
@@ -131,7 +132,9 @@ public class RequestEntity<T> extends HttpEntity<T> {
* @param type the type used for generic type resolution
* @since 4.3
*/
public RequestEntity(T body, MultiValueMap<String, String> headers, HttpMethod method, URI url, Type type) {
public RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers,
@Nullable HttpMethod method, URI url, @Nullable Type type) {
super(body, headers);
this.method = method;
this.url = url;
@@ -143,6 +146,7 @@ public class RequestEntity<T> extends HttpEntity<T> {
* Return the HTTP method of the request.
* @return the HTTP method as an {@code HttpMethod} enum value
*/
@Nullable
public HttpMethod getMethod() {
return this.method;
}
@@ -173,7 +177,7 @@ public class RequestEntity<T> extends HttpEntity<T> {
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
@@ -204,13 +208,9 @@ public class RequestEntity<T> extends HttpEntity<T> {
HttpHeaders headers = getHeaders();
if (body != null) {
builder.append(body);
if (headers != null) {
builder.append(',');
}
}
if (headers != null) {
builder.append(headers);
builder.append(',');
}
builder.append(headers);
builder.append('>');
return builder.toString();
}

View File

@@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
@@ -66,7 +67,7 @@ import org.springframework.util.ObjectUtils;
*/
public class ResponseEntity<T> extends HttpEntity<T> {
private final Object statusCode;
private final Object status;
/**
@@ -82,7 +83,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
* @param body the entity body
* @param status the status code
*/
public ResponseEntity(T body, HttpStatus status) {
public ResponseEntity(@Nullable T body, HttpStatus status) {
this(body, null, status);
}
@@ -101,10 +102,10 @@ public class ResponseEntity<T> extends HttpEntity<T> {
* @param headers the entity headers
* @param status the status code
*/
public ResponseEntity(T body, MultiValueMap<String, String> headers, HttpStatus status) {
public ResponseEntity(@Nullable T body, @Nullable 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,12 @@ 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(@Nullable T body, @Nullable MultiValueMap<String, String> headers, Object status) {
super(body, headers);
this.statusCode = statusCode;
Assert.notNull(status, "HttpStatus must not be null");
this.status = status;
}
@@ -125,11 +127,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,17 +141,17 @@ 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;
}
}
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
@@ -157,34 +159,30 @@ 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();
HttpHeaders headers = getHeaders();
if (body != null) {
builder.append(body);
if (headers != null) {
builder.append(',');
}
}
if (headers != null) {
builder.append(headers);
builder.append(',');
}
builder.append(headers);
builder.append('>');
return builder.toString();
}
@@ -315,7 +313,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
* @since 4.1.2
* @see HttpHeaders#add(String, String)
*/
B headers(HttpHeaders headers);
B headers(@Nullable HttpHeaders headers);
/**
* Set the set of allowed {@link HttpMethod HTTP methods}, as specified
@@ -328,11 +326,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
@@ -415,7 +413,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
* @param body the body of the response entity
* @return the built response entity
*/
<T> ResponseEntity<T> body(T body);
<T> ResponseEntity<T> body(@Nullable T body);
}
@@ -438,7 +436,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
}
@Override
public BodyBuilder headers(HttpHeaders headers) {
public BodyBuilder headers(@Nullable HttpHeaders headers) {
if (headers != null) {
this.headers.putAll(headers);
}
@@ -464,16 +462,14 @@ public class ResponseEntity<T> extends HttpEntity<T> {
}
@Override
public BodyBuilder eTag(String eTag) {
if (eTag != null) {
if (!eTag.startsWith("\"") && !eTag.startsWith("W/\"")) {
eTag = "\"" + eTag;
}
if (!eTag.endsWith("\"")) {
eTag = eTag + "\"";
}
public BodyBuilder eTag(String etag) {
if (!etag.startsWith("\"") && !etag.startsWith("W/\"")) {
etag = "\"" + etag;
}
this.headers.setETag(eTag);
if (!etag.endsWith("\"")) {
etag = etag + "\"";
}
this.headers.setETag(etag);
return this;
}
@@ -510,7 +506,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
}
@Override
public <T> ResponseEntity<T> body(T body) {
public <T> ResponseEntity<T> body(@Nullable T body) {
return new ResponseEntity<>(body, this.headers, this.statusCode);
}
}

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.
@@ -97,6 +97,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest
* Return the {@code HttpClient} used for
* {@linkplain #createRequest(URI, HttpMethod) synchronous execution}.
*/
@Nullable
public HttpClient getHttpClient() {
return this.httpClient;
}
@@ -219,11 +220,9 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest
* the factory-level {@link RequestConfig}, if necessary.
* @param clientConfig the config held by the current
* @return the merged request config
* (may be {@code null} if the given client config is {@code null})
* @since 4.2
*/
@Nullable
protected RequestConfig mergeRequestConfig(@Nullable RequestConfig clientConfig) {
protected RequestConfig mergeRequestConfig(RequestConfig clientConfig) {
if (this.requestConfig == null) { // nothing to merge
return clientConfig;
}

View File

@@ -33,6 +33,7 @@ import org.apache.http.protocol.HttpContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.StreamingHttpOutputMessage;
import org.springframework.lang.Nullable;
/**
* {@link ClientHttpRequest} implementation based on
@@ -126,12 +127,14 @@ final class HttpComponentsStreamingClientHttpRequest extends AbstractClientHttpR
}
@Override
@Nullable
public Header getContentType() {
MediaType contentType = this.headers.getContentType();
return (contentType != null ? new BasicHeader("Content-Type", contentType.toString()) : null);
}
@Override
@Nullable
public Header getContentEncoding() {
String contentEncoding = this.headers.getFirst("Content-Encoding");
return (contentEncoding != null ? new BasicHeader("Content-Encoding", contentEncoding) : null);

View File

@@ -24,6 +24,7 @@ import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.util.concurrent.ListenableFuture;
@@ -49,12 +50,11 @@ class InterceptingAsyncClientHttpRequest extends AbstractBufferingAsyncClientHtt
/**
* Creates new instance of {@link InterceptingAsyncClientHttpRequest}.
*
* 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
* @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) {
@@ -107,11 +107,12 @@ class InterceptingAsyncClientHttpRequest extends AbstractBufferingAsyncClientHtt
}
else {
URI theUri = request.getURI();
HttpMethod theMethod = request.getMethod();
HttpHeaders theHeaders = request.getHeaders();
HttpMethod method = request.getMethod();
HttpHeaders headers = request.getHeaders();
AsyncClientHttpRequest delegate = requestFactory.createAsyncRequest(theUri, theMethod);
delegate.getHeaders().putAll(theHeaders);
Assert.state(method != null, "No standard HTTP method");
AsyncClientHttpRequest delegate = requestFactory.createAsyncRequest(theUri, method);
delegate.getHeaders().putAll(headers);
if (body.length > 0) {
StreamUtils.copy(body, delegate.getBody());
}

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.List;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
/**
* Wrapper for a {@link AsyncClientHttpRequestFactory} that has support for
@@ -46,7 +47,7 @@ public class InterceptingAsyncClientHttpRequestFactory implements AsyncClientHtt
* @param interceptors the list of interceptors to use
*/
public InterceptingAsyncClientHttpRequestFactory(AsyncClientHttpRequestFactory delegate,
List<AsyncClientHttpRequestInterceptor> interceptors) {
@Nullable List<AsyncClientHttpRequestInterceptor> interceptors) {
this.delegate = delegate;
this.interceptors = (interceptors != null ? interceptors : Collections.emptyList());

View File

@@ -25,6 +25,7 @@ import java.util.Map;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
/**
@@ -91,7 +92,9 @@ class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest {
return nextInterceptor.intercept(request, body, this);
}
else {
ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod());
HttpMethod method = request.getMethod();
Assert.state(method != null, "No standard HTTP method");
ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method);
for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) {
delegate.getHeaders().addAll(entry.getKey(), entry.getValue());
}

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.
@@ -57,7 +59,8 @@ 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
@@ -76,7 +79,10 @@ class OkHttp3ClientHttpResponse extends AbstractClientHttpResponse {
@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-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.
@@ -23,6 +23,7 @@ import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
@@ -45,7 +46,7 @@ public class BasicAuthorizationInterceptor implements ClientHttpRequestIntercept
* @param username the username to use
* @param password the password to use
*/
public BasicAuthorizationInterceptor(String username, String password) {
public BasicAuthorizationInterceptor(String username, @Nullable String password) {
Assert.hasLength(username, "Username must not be empty");
this.username = username;
this.password = (password != null ? password : "");

View File

@@ -128,12 +128,12 @@ public class DecoderHttpMessageReader<T> implements HttpMessageReader<T> {
* or annotations from controller method parameters. By default, delegate to
* the decoder if it is an instance of {@link HttpMessageDecoder}.
*/
protected Map<String, Object> getReadHints(ResolvableType streamType,
protected Map<String, Object> getReadHints(ResolvableType actualType,
ResolvableType elementType, ServerHttpRequest request, ServerHttpResponse response) {
if (this.decoder instanceof HttpMessageDecoder) {
HttpMessageDecoder<?> httpDecoder = (HttpMessageDecoder<?>) this.decoder;
return httpDecoder.getDecodeHints(streamType, elementType, request, response);
return httpDecoder.getDecodeHints(actualType, elementType, request, response);
}
return Collections.emptyMap();
}

View File

@@ -85,7 +85,7 @@ class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements Cl
if (this.sseDecoder != null) {
return this.sseDecoder;
}
return jackson2Present ? jackson2Decoder() : null;
return (jackson2Present ? jackson2Decoder() : null);
}
@Override

View File

@@ -103,13 +103,14 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
message.writeAndFlushWith(body.map(Flux::just)) : message.writeWith(body));
}
private MediaType updateContentType(ReactiveHttpOutputMessage message, MediaType mediaType) {
@Nullable
private MediaType updateContentType(ReactiveHttpOutputMessage message, @Nullable MediaType mediaType) {
MediaType result = message.getHeaders().getContentType();
if (result != null) {
return result;
}
MediaType fallback = this.defaultMediaType;
result = useFallback(mediaType, fallback) ? fallback : mediaType;
result = (useFallback(mediaType, fallback) ? fallback : mediaType);
if (result != null) {
result = addDefaultCharset(result, fallback);
message.getHeaders().setContentType(result);
@@ -117,29 +118,29 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
return result;
}
private static boolean useFallback(MediaType main, MediaType fallback) {
private static boolean useFallback(@Nullable MediaType main, @Nullable MediaType fallback) {
return (main == null || !main.isConcrete() ||
main.equals(MediaType.APPLICATION_OCTET_STREAM) && fallback != null);
}
private static MediaType addDefaultCharset(MediaType main, MediaType defaultType) {
private static MediaType addDefaultCharset(MediaType main, @Nullable MediaType defaultType) {
if (main.getCharset() == null && defaultType != null && defaultType.getCharset() != null) {
return new MediaType(main, defaultType.getCharset());
}
return main;
}
private boolean isStreamingMediaType(MediaType contentType) {
return this.encoder instanceof HttpMessageEncoder &&
private boolean isStreamingMediaType(@Nullable MediaType contentType) {
return (contentType != null && this.encoder instanceof HttpMessageEncoder &&
((HttpMessageEncoder<?>) this.encoder).getStreamingMediaTypes().stream()
.anyMatch(contentType::isCompatibleWith);
.anyMatch(contentType::isCompatibleWith));
}
// Server side only...
@Override
public Mono<Void> write(Publisher<? extends T> inputStream, @Nullable ResolvableType actualType,
public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType actualType,
ResolvableType elementType, @Nullable MediaType mediaType, ServerHttpRequest request,
ServerHttpResponse response, Map<String, Object> hints) {
@@ -156,7 +157,7 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
* the encoder if it is an instance of {@link HttpMessageEncoder}.
*/
protected Map<String, Object> getWriteHints(ResolvableType streamType, ResolvableType elementType,
MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
@Nullable MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
if (this.encoder instanceof HttpMessageEncoder) {
HttpMessageEncoder<?> httpEncoder = (HttpMessageEncoder<?>) this.encoder;

View File

@@ -105,7 +105,7 @@ public class FormHttpMessageReader implements HttpMessageReader<MultiValueMap<St
});
}
private Charset getMediaTypeCharset(MediaType mediaType) {
private Charset getMediaTypeCharset(@Nullable MediaType mediaType) {
if (mediaType != null && mediaType.getCharset() != null) {
return mediaType.getCharset();
}

View File

@@ -107,7 +107,7 @@ public class FormHttpMessageWriter implements HttpMessageWriter<MultiValueMap<St
}
private Charset getMediaTypeCharset(MediaType mediaType) {
private Charset getMediaTypeCharset(@Nullable MediaType mediaType) {
if (mediaType != null && mediaType.getCharset() != null) {
return mediaType.getCharset();
}

View File

@@ -37,9 +37,9 @@ public interface HttpMessageDecoder<T> extends Decoder<T> {
* target controller method parameter.
* @param actualType the actual target type to decode to, possibly a reactive
* wrapper and sourced from {@link org.springframework.core.MethodParameter},
* i.e. providing access to method parameter annotations.
* i.e. providing access to method parameter annotations
* @param elementType the element type within {@code Flux/Mono} that we're
* trying to decode to.
* trying to decode to
* @param request the current request
* @param response the current response
* @return a Map with hints, possibly empty

View File

@@ -25,6 +25,7 @@ import org.springframework.core.codec.Encoder;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
/**
* Extension of {@code Encoder} exposing extra methods relevant in the context
@@ -54,7 +55,7 @@ public interface HttpMessageEncoder<T> extends Encoder<T> {
* @return a Map with hints, possibly empty
*/
default Map<String, Object> getEncodeHints(ResolvableType actualType, ResolvableType elementType,
MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
@Nullable MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
return Collections.emptyMap();
}

View File

@@ -51,7 +51,7 @@ public interface HttpMessageReader<T> {
/**
* Whether the given object type is supported by this reader.
* @param elementType the type of object to check
* @param mediaType the media type for the read, possibly {@code null}
* @param mediaType the media type for the read (possibly {@code null})
* @return {@code true} if readable, {@code false} otherwise
*/
boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType);

View File

@@ -74,7 +74,6 @@ public interface HttpMessageWriter<T> {
* Server-side only alternative to
* {@link #write(Publisher, ResolvableType, MediaType, ReactiveHttpOutputMessage, Map)}
* with additional context available.
*
* @param actualType the actual return type of the method that returned the
* value; for annotated controllers, the {@link MethodParameter} can be
* accessed via {@link ResolvableType#getSource()}.
@@ -85,7 +84,7 @@ public interface HttpMessageWriter<T> {
* @param response the current response
* @return a {@link Mono} that indicates completion of writing or error
*/
default Mono<Void> write(Publisher<? extends T> inputStream, @Nullable ResolvableType actualType,
default Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType actualType,
ResolvableType elementType, @Nullable MediaType mediaType, ServerHttpRequest request,
ServerHttpResponse response, Map<String, Object> hints) {

View File

@@ -113,7 +113,7 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter<Resource> {
writeResource(resource, elementType, mediaType, message, hints));
}
private Mono<Void> writeResource(Resource resource, ResolvableType type, MediaType mediaType,
private Mono<Void> writeResource(Resource resource, ResolvableType type, @Nullable MediaType mediaType,
ReactiveHttpOutputMessage message, Map<String, Object> hints) {
HttpHeaders headers = message.getHeaders();
@@ -133,9 +133,9 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter<Resource> {
});
}
private static MediaType getResourceMediaType(MediaType type, Resource resource) {
if (type != null && type.isConcrete() && !type.equals(MediaType.APPLICATION_OCTET_STREAM)) {
return type;
private static MediaType getResourceMediaType(@Nullable MediaType mediaType, Resource resource) {
if (mediaType != null && mediaType.isConcrete() && !mediaType.equals(MediaType.APPLICATION_OCTET_STREAM)) {
return mediaType;
}
return MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM);
}
@@ -236,7 +236,7 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter<Resource> {
}
private Mono<Void> encodeAndWriteRegions(Publisher<? extends ResourceRegion> publisher,
MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) {
@Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) {
Flux<DataBuffer> body = this.regionEncoder.encode(
publisher, message.bufferFactory(), REGION_TYPE, mediaType, hints);

View File

@@ -40,19 +40,19 @@ public class ServerSentEvent<T> {
private final String event;
private final T data;
private final Duration retry;
private final String comment;
private final T data;
private ServerSentEvent(String id, String event, T data, Duration retry, String comment) {
private ServerSentEvent(String id, String event, Duration retry, String comment, T data) {
this.id = id;
this.event = event;
this.data = data;
this.retry = retry;
this.comment = comment;
this.data = data;
}
@@ -72,14 +72,6 @@ public class ServerSentEvent<T> {
return this.event;
}
/**
* Return the {@code data} field of this event, if available.
*/
@Nullable
public T data() {
return this.data;
}
/**
* Return the {@code retry} field of this event, if available.
*/
@@ -96,11 +88,19 @@ public class ServerSentEvent<T> {
return this.comment;
}
/**
* Return the {@code data} field of this event, if available.
*/
@Nullable
public T data() {
return this.data;
}
@Override
public String toString() {
return ("ServerSentEvent [id = '" + this.id + '\'' + ", event='" + this.event + '\'' +
", data=" + this.data + ", retry=" + this.retry + ", comment='" + this.comment + '\'' + ']');
return ("ServerSentEvent [id = '" + this.id + "\', event='" + this.event + "\', retry=" +
this.retry + ", comment='" + this.comment + "', data=" + this.data + ']');
}
@@ -132,7 +132,6 @@ public class ServerSentEvent<T> {
/**
* Set the value of the {@code id} field.
*
* @param id the value of the id field
* @return {@code this} builder
*/
@@ -140,26 +139,13 @@ public class ServerSentEvent<T> {
/**
* Set the value of the {@code event} field.
*
* @param event the value of the event field
* @return {@code this} builder
*/
Builder<T> event(String event);
/**
* Set the value of the {@code data} field. If the {@code data} argument is a multi-line {@code String}, it
* will be turned into multiple {@code data} field lines as defined in Server-Sent Events
* W3C recommendation. If {@code data} is not a String, it will be
* {@linkplain Jackson2JsonEncoder encoded} into JSON.
*
* @param data the value of the data field
* @return {@code this} builder
*/
Builder<T> data(T data);
/**
* Set the value of the {@code retry} field.
*
* @param retry the value of the retry field
* @return {@code this} builder
*/
@@ -167,17 +153,24 @@ public class ServerSentEvent<T> {
/**
* Set SSE comment. If a multi-line comment is provided, it will be turned into multiple
* SSE comment lines as defined in Server-Sent Events W3C
* recommendation.
*
* SSE comment lines as defined in Server-Sent Events W3C recommendation.
* @param comment the comment to set
* @return {@code this} builder
*/
Builder<T> comment(String comment);
/**
* Set the value of the {@code data} field. If the {@code data} argument is a
* multi-line {@code String}, it will be turned into multiple {@code data} field lines
* as defined in the Server-Sent Events W3C recommendation. If {@code data} is not a
* String, it will be {@linkplain Jackson2JsonEncoder encoded} into JSON.
* @param data the value of the data field
* @return {@code this} builder
*/
Builder<T> data(T data);
/**
* Builds the event.
*
* @return the built event
*/
ServerSentEvent<T> build();
@@ -186,8 +179,6 @@ public class ServerSentEvent<T> {
private static class BuilderImpl<T> implements Builder<T> {
private T data;
private String id;
private String event;
@@ -196,7 +187,9 @@ public class ServerSentEvent<T> {
private String comment;
public BuilderImpl() {
private T data;
public BuilderImpl() {
}
public BuilderImpl(T data) {
@@ -215,12 +208,6 @@ public class ServerSentEvent<T> {
return this;
}
@Override
public Builder<T> data(T data) {
this.data = data;
return this;
}
@Override
public Builder<T> retry(Duration retry) {
this.retry = retry;
@@ -233,9 +220,15 @@ public class ServerSentEvent<T> {
return this;
}
@Override
public Builder<T> data(T data) {
this.data = data;
return this;
}
@Override
public ServerSentEvent<T> build() {
return new ServerSentEvent<T>(this.id, this.event, this.data, this.retry, this.comment);
return new ServerSentEvent<T>(this.id, this.event, this.retry, this.comment, this.data);
}
}

View File

@@ -71,10 +71,10 @@ public class ServerSentEventHttpMessageReader implements HttpMessageReader<Objec
}
/**
* Constructor with JSON {@code Decoder} for decoding to Objects. Support
* for decoding to {@code String} event data is built-in.
* Constructor with JSON {@code Decoder} for decoding to Objects.
* Support for decoding to {@code String} event data is built-in.
*/
public ServerSentEventHttpMessageReader(Decoder<?> decoder) {
public ServerSentEventHttpMessageReader(@Nullable Decoder<?> decoder) {
this.decoder = decoder;
}
@@ -82,6 +82,7 @@ public class ServerSentEventHttpMessageReader implements HttpMessageReader<Objec
/**
* Return the configured {@code Decoder}.
*/
@Nullable
public Decoder<?> getDecoder() {
return this.decoder;
}
@@ -93,8 +94,12 @@ public class ServerSentEventHttpMessageReader implements HttpMessageReader<Objec
@Override
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
return MediaType.TEXT_EVENT_STREAM.includes(mediaType) ||
ServerSentEvent.class.isAssignableFrom(elementType.getRawClass());
return (MediaType.TEXT_EVENT_STREAM.includes(mediaType) || isServerSentEvent(elementType));
}
private boolean isServerSentEvent(ResolvableType elementType) {
Class<?> rawClass = elementType.getRawClass();
return (rawClass != null && ServerSentEvent.class.isAssignableFrom(rawClass));
}
@@ -102,8 +107,8 @@ public class ServerSentEventHttpMessageReader implements HttpMessageReader<Objec
public Flux<Object> read(ResolvableType elementType, ReactiveHttpInputMessage message,
Map<String, Object> hints) {
boolean shouldWrap = ServerSentEvent.class.isAssignableFrom(elementType.getRawClass());
ResolvableType valueType = shouldWrap ? elementType.getGeneric(0) : elementType;
boolean shouldWrap = isServerSentEvent(elementType);
ResolvableType valueType = (shouldWrap ? elementType.getGeneric(0) : elementType);
return Flux.from(message.getBody())
.concatMap(ServerSentEventHttpMessageReader::splitOnNewline)
@@ -174,8 +179,7 @@ public class ServerSentEventHttpMessageReader implements HttpMessageReader<Objec
}
private Object decodeData(String data, ResolvableType dataType, Map<String, Object> hints) {
if (String.class.isAssignableFrom(dataType.getRawClass())) {
if (String.class == dataType.resolve()) {
return data.substring(0, data.length() - 1);
}

View File

@@ -17,6 +17,7 @@
package org.springframework.http.codec;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -67,7 +68,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
* Support for {@code String} event data is built-in.
* @param encoder the Encoder to use (may be {@code null})
*/
public ServerSentEventHttpMessageWriter(Encoder<?> encoder) {
public ServerSentEventHttpMessageWriter(@Nullable Encoder<?> encoder) {
this.encoder = encoder;
}
@@ -103,7 +104,8 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
private Flux<Publisher<DataBuffer>> encode(Publisher<?> input, DataBufferFactory factory,
ResolvableType elementType, Map<String, Object> hints) {
ResolvableType valueType = (ServerSentEvent.class.isAssignableFrom(elementType.getRawClass()) ?
Class<?> elementClass = elementType.getRawClass();
ResolvableType valueType = (elementClass != null && ServerSentEvent.class.isAssignableFrom(elementClass) ?
elementType.getGeneric() : elementType);
return Flux.from(input).map(element -> {
@@ -112,24 +114,29 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
(ServerSentEvent<?>) element : ServerSentEvent.builder().data(element).build());
StringBuilder sb = new StringBuilder();
if (sse.id() != null) {
writeField("id", sse.id(), sb);
String id = sse.id();
String event = sse.event();
Duration retry = sse.retry();
String comment = sse.comment();
Object data = sse.data();
if (id != null) {
writeField("id", id, sb);
}
if (sse.event() != null) {
writeField("event", sse.event(), sb);
if (event != null) {
writeField("event", event, sb);
}
if (sse.retry() != null) {
writeField("retry", sse.retry().toMillis(), sb);
if (retry != null) {
writeField("retry", retry.toMillis(), sb);
}
if (sse.comment() != null) {
sb.append(':').append(sse.comment().replaceAll("\\n", "\n:")).append("\n");
if (comment != null) {
sb.append(':').append(comment.replaceAll("\\n", "\n:")).append("\n");
}
if (sse.data() != null) {
if (data != null) {
sb.append("data:");
}
return Flux.concat(encodeText(sb, factory),
encodeData(sse.data(), valueType, factory, hints),
encodeData(data, valueType, factory, hints),
encodeText("\n", factory));
});
}
@@ -142,7 +149,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
}
@SuppressWarnings("unchecked")
private <T> Flux<DataBuffer> encodeData(T data, ResolvableType valueType,
private <T> Flux<DataBuffer> encodeData(@Nullable T data, ResolvableType valueType,
DataBufferFactory factory, Map<String, Object> hints) {
if (data == null) {
@@ -170,7 +177,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
}
@Override
public Mono<Void> write(Publisher<?> input, @Nullable ResolvableType actualType, ResolvableType elementType,
public Mono<Void> write(Publisher<?> input, ResolvableType actualType, ResolvableType elementType,
@Nullable MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response,
Map<String, Object> hints) {
@@ -182,7 +189,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
}
private Map<String, Object> getEncodeHints(ResolvableType actualType, ResolvableType elementType,
MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
@Nullable MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
if (this.encoder instanceof HttpMessageEncoder) {
HttpMessageEncoder<?> httpEncoder = (HttpMessageEncoder<?>) this.encoder;

View File

@@ -77,7 +77,7 @@ public abstract class Jackson2CodecSupport {
}
protected boolean supportsMimeType(MimeType mimeType) {
protected boolean supportsMimeType(@Nullable MimeType mimeType) {
return (mimeType == null || this.mimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType)));
}
@@ -86,8 +86,8 @@ public abstract class Jackson2CodecSupport {
return typeFactory.constructType(GenericTypeResolver.resolveType(type, contextClass));
}
protected Map<String, Object> getHints(ResolvableType actualType) {
return getParameter(actualType)
protected Map<String, Object> getHints(ResolvableType resolvableType) {
return getParameter(resolvableType)
.flatMap(parameter -> Optional.ofNullable(getAnnotation(parameter, JsonView.class))
.map(annotation -> {
Class<?>[] classes = annotation.value();
@@ -102,6 +102,7 @@ public abstract class Jackson2CodecSupport {
(MethodParameter) type.getSource() : null);
}
@Nullable
protected abstract <A extends Annotation> A getAnnotation(MethodParameter parameter, Class<A> annotType);
}

View File

@@ -83,7 +83,7 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMes
}
@Override
public Flux<Object> decode(Publisher<DataBuffer> input, @Nullable ResolvableType elementType,
public Flux<Object> decode(Publisher<DataBuffer> input, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
return decodeInternal(this.fluxDecoder, input, elementType, mimeType, hints);
@@ -97,14 +97,14 @@ public class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMes
}
private Flux<Object> decodeInternal(JsonObjectDecoder objectDecoder, Publisher<DataBuffer> inputStream,
ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
Assert.notNull(inputStream, "'inputStream' must not be null");
Assert.notNull(elementType, "'elementType' must not be null");
Class<?> contextClass = getParameter(elementType).map(MethodParameter::getContainingClass).orElse(null);
JavaType javaType = getJavaType(elementType.getType(), contextClass);
Class<?> jsonView = (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT);
Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
ObjectReader reader = (jsonView != null ?
this.objectMapper.readerWithView(jsonView).forType(javaType) :

View File

@@ -139,8 +139,8 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMes
}
}
private DataBuffer encodeValue(Object value, MimeType mimeType, DataBufferFactory bufferFactory,
ResolvableType elementType, Map<String, Object> hints) {
private DataBuffer encodeValue(Object value, @Nullable MimeType mimeType, DataBufferFactory bufferFactory,
ResolvableType elementType, @Nullable Map<String, Object> hints) {
TypeFactory typeFactory = this.objectMapper.getTypeFactory();
JavaType javaType = typeFactory.constructType(elementType.getType());
@@ -148,7 +148,7 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMes
javaType = getJavaType(elementType.getType(), null);
}
Class<?> jsonView = (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT);
Class<?> jsonView = (hints != null ? (Class<?>) hints.get(Jackson2CodecSupport.JSON_VIEW_HINT) : null);
ObjectWriter writer = (jsonView != null ?
this.objectMapper.writerWithView(jsonView) : this.objectMapper.writer());
@@ -189,10 +189,10 @@ public class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMes
}
@Override
public Map<String, Object> getEncodeHints(ResolvableType actualType, ResolvableType elementType,
MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
public Map<String, Object> getEncodeHints(@Nullable ResolvableType actualType, ResolvableType elementType,
@Nullable MediaType mediaType, ServerHttpRequest request, ServerHttpResponse response) {
return getHints(actualType);
return (actualType != null ? getHints(actualType) : Collections.emptyMap());
}
@Override

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.
@@ -147,9 +147,7 @@ class JsonObjectDecoder extends AbstractDecoder<DataBuffer> {
if (this.openBraces == 0) {
ByteBuf json = extractObject(this.input, this.input.readerIndex(),
this.index + 1 - this.input.readerIndex());
if (json != null) {
chunks.add(dataBufferFactory.wrap(json.nioBuffer()));
}
chunks.add(dataBufferFactory.wrap(json.nioBuffer()));
// The JSON object/array was extracted => discard the bytes from
// the input buffer.
@@ -174,16 +172,12 @@ class JsonObjectDecoder extends AbstractDecoder<DataBuffer> {
int idxNoSpaces = this.index - 1;
while (idxNoSpaces >= this.input.readerIndex() &&
Character.isWhitespace(this.input.getByte(idxNoSpaces))) {
idxNoSpaces--;
}
ByteBuf json = extractObject(this.input, this.input.readerIndex(),
idxNoSpaces + 1 - this.input.readerIndex());
if (json != null) {
chunks.add(dataBufferFactory.wrap(json.nioBuffer()));
}
chunks.add(dataBufferFactory.wrap(json.nioBuffer()));
this.input.readerIndex(this.index + 1);

View File

@@ -111,8 +111,9 @@ public class MultipartHttpMessageWriter implements HttpMessageWriter<MultiValueM
@Override
public boolean canWrite(ResolvableType elementType, @Nullable MediaType mediaType) {
return MultiValueMap.class.isAssignableFrom(elementType.getRawClass()) &&
(mediaType == null || MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType));
Class<?> rawClass = elementType.getRawClass();
return (rawClass != null && MultiValueMap.class.isAssignableFrom(rawClass) &&
(mediaType == null || MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)));
}
@Override
@@ -156,6 +157,7 @@ public class MultipartHttpMessageWriter implements HttpMessageWriter<MultiValueM
if (value instanceof HttpEntity) {
outputMessage.getHeaders().putAll(((HttpEntity<T>) value).getHeaders());
body = ((HttpEntity<T>) value).getBody();
Assert.state(body != null, "MultipartHttpMessageWriter only supports HttpEntity with body");
}
else {
body = value;

View File

@@ -112,18 +112,17 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
private final DataBufferFactory bufferFactory;
SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage, DataBufferFactory factory) {
this.inputMessage = inputMessage;
this.bufferFactory = factory;
}
@Override
public void accept(FluxSink<Part> emitter) {
HttpHeaders headers = this.inputMessage.getHeaders();
MediaType mediaType = headers.getContentType();
Assert.state(mediaType != null, "No content type set");
int length = Math.toIntExact(headers.getContentLength());
Charset charset = Optional.ofNullable(mediaType.getCharset()).orElse(StandardCharsets.UTF_8);
MultipartContext context = new MultipartContext(mediaType.toString(), length, charset.name());
@@ -159,6 +158,8 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
}
}
/**
* Listen for parser output and adapt to {@code Flux<Sink<Part>>}.
*/
@@ -172,14 +173,12 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
private final AtomicInteger terminated = new AtomicInteger(0);
FluxSinkAdapterListener(FluxSink<Part> sink, DataBufferFactory bufferFactory, MultipartContext context) {
this.sink = sink;
this.bufferFactory = bufferFactory;
this.context = context;
}
@Override
public void onPartFinished(StreamStorage storage, Map<String, List<String>> headers) {
HttpHeaders httpHeaders = new HttpHeaders();
@@ -238,7 +237,6 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
private final DataBufferFactory bufferFactory;
AbstractSynchronossPart(HttpHeaders headers, DataBufferFactory bufferFactory) {
Assert.notNull(headers, "HttpHeaders is required");
Assert.notNull(bufferFactory, "'bufferFactory' is required");
@@ -246,7 +244,6 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
this.bufferFactory = bufferFactory;
}
@Override
public String name() {
return MultipartUtils.getFieldName(this.headers);
@@ -262,18 +259,17 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
}
}
private static class DefaultSynchronossPart extends AbstractSynchronossPart {
private final StreamStorage storage;
DefaultSynchronossPart(HttpHeaders headers, StreamStorage storage, DataBufferFactory factory) {
super(headers, factory);
Assert.notNull(storage, "'storage' is required");
this.storage = storage;
}
@Override
public Flux<DataBuffer> content() {
InputStream inputStream = this.storage.getInputStream();
@@ -285,8 +281,8 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
}
}
private static class SynchronossFilePart extends DefaultSynchronossPart implements FilePart {
private static class SynchronossFilePart extends DefaultSynchronossPart implements FilePart {
public SynchronossFilePart(HttpHeaders headers, StreamStorage storage,
String fileName, DataBufferFactory factory) {
@@ -294,7 +290,6 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
super(headers, storage, factory);
}
@Override
public String filename() {
return MultipartUtils.getFileName(headers());
@@ -341,17 +336,16 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
}
}
private static class SynchronossFormFieldPart extends AbstractSynchronossPart implements FormFieldPart {
private final String content;
SynchronossFormFieldPart(HttpHeaders headers, DataBufferFactory bufferFactory, String content) {
super(headers, bufferFactory);
this.content = content;
}
@Override
public String value() {
return this.content;

View File

@@ -42,6 +42,7 @@ import org.springframework.core.codec.CodecException;
import org.springframework.core.codec.DecodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
@@ -82,8 +83,8 @@ public class Jaxb2XmlDecoder extends AbstractDecoder<Object> {
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
if (super.canDecode(elementType, mimeType)) {
Class<?> outputClass = elementType.getRawClass();
return outputClass.isAnnotationPresent(XmlRootElement.class) ||
outputClass.isAnnotationPresent(XmlType.class);
return (outputClass != null && (outputClass.isAnnotationPresent(XmlRootElement.class) ||
outputClass.isAnnotationPresent(XmlType.class)));
}
else {
return false;
@@ -91,11 +92,14 @@ public class Jaxb2XmlDecoder extends AbstractDecoder<Object> {
}
@Override
public Flux<Object> decode(Publisher<DataBuffer> inputStream, @Nullable ResolvableType elementType,
public Flux<Object> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
Class<?> outputClass = elementType.getRawClass();
Flux<XMLEvent> xmlEventFlux = this.xmlEventDecoder.decode(inputStream, null, mimeType, hints);
Assert.state(outputClass != null, "Unresolvable output class");
Flux<XMLEvent> xmlEventFlux = this.xmlEventDecoder.decode(
inputStream, ResolvableType.forClass(XMLEvent.class), mimeType, hints);
QName typeName = toQName(outputClass);
Flux<List<XMLEvent>> splitEvents = split(xmlEventFlux, typeName);

View File

@@ -71,7 +71,7 @@ public class Jaxb2XmlEncoder extends AbstractSingleValueEncoder<Object> {
@Override
protected Flux<DataBuffer> encode(Object value, DataBufferFactory dataBufferFactory,
ResolvableType type, MimeType mimeType, Map<String, Object> hints) {
ResolvableType type, MimeType mimeType, @Nullable Map<String, Object> hints) {
try {
DataBuffer buffer = dataBufferFactory.allocateBuffer(1024);
OutputStream outputStream = buffer.asOutputStream();

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.
@@ -90,7 +90,7 @@ public class XmlEventDecoder extends AbstractDecoder<XMLEvent> {
@Override
@SuppressWarnings("unchecked")
public Flux<XMLEvent> decode(Publisher<DataBuffer> inputStream, @Nullable ResolvableType elementType,
public Flux<XMLEvent> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
Flux<DataBuffer> flux = Flux.from(inputStream);

View File

@@ -71,7 +71,7 @@ public abstract class AbstractGenericHttpMessageConverter<T> extends AbstractHtt
}
@Override
public boolean canWrite(@Nullable Type type, @Nullable Class<?> clazz, @Nullable MediaType mediaType) {
public boolean canWrite(@Nullable Type type, Class<?> clazz, @Nullable MediaType mediaType) {
return canWrite(clazz, mediaType);
}

View File

@@ -191,7 +191,7 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
* Future implementations might add some default behavior, however.
*/
@Override
public final T read(@Nullable Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
return readInternal(clazz, inputMessage);
}

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.
@@ -132,7 +132,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
return (BufferedImage.class == clazz && isReadable(mediaType));
}
private boolean isReadable(MediaType mediaType) {
private boolean isReadable(@Nullable MediaType mediaType) {
if (mediaType == null) {
return true;
}
@@ -145,7 +145,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
return (BufferedImage.class == clazz && isWritable(mediaType));
}
private boolean isWritable(MediaType mediaType) {
private boolean isWritable(@Nullable MediaType mediaType) {
if (mediaType == null || MediaType.ALL.equals(mediaType)) {
return true;
}
@@ -167,6 +167,9 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
try {
imageInputStream = createImageInputStream(inputMessage.getBody());
MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
throw new HttpMessageNotReadableException("No Content-Type header");
}
Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByMIMEType(contentType.toString());
if (imageReaders.hasNext()) {
imageReader = imageReaders.next();
@@ -226,7 +229,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
}
}
private MediaType getContentType(MediaType contentType) {
private MediaType getContentType(@Nullable MediaType contentType) {
if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
contentType = getDefaultContentType();
}

View File

@@ -29,7 +29,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.mail.internet.MimeUtility;
import org.springframework.core.io.Resource;
@@ -151,19 +150,16 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
/**
* Set the default character set to use for reading and writing form data when
* the request or response Content-Type header does not explicitly specify it.
*
* <p>As of 4.3, this is also used as the default charset for the conversion
* of text bodies in a multipart request.
*
* <p>As of 5.0 this is also used for part headers including
* "Content-Disposition" (and its filename parameter) unless (the mutually
* exclusive) {@link #setMultipartCharset} is also set, in which case part
* headers are encoded as ASCII and <i>filename</i> is encoded with the
* "encoded-word" syntax from RFC 2047.
*
* <p>By default this is set to "UTF-8".
*/
public void setCharset(Charset charset) {
public void setCharset(@Nullable Charset charset) {
if (charset != this.charset) {
this.charset = (charset != null ? charset : DEFAULT_CHARSET);
applyDefaultCharset();
@@ -240,7 +236,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
MediaType contentType = inputMessage.getHeaders().getContentType();
Charset charset = (contentType.getCharset() != null ? contentType.getCharset() : this.charset);
Charset charset = (contentType != null && contentType.getCharset() != null ?
contentType.getCharset() : this.charset);
String body = StreamUtils.copyToString(inputMessage.getBody(), charset);
String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
@@ -273,7 +270,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
}
private boolean isMultipart(MultiValueMap<String, ?> map, MediaType contentType) {
private boolean isMultipart(MultiValueMap<String, ?> map, @Nullable MediaType contentType) {
if (contentType != null) {
return MediaType.MULTIPART_FORM_DATA.includes(contentType);
}
@@ -287,7 +284,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
return false;
}
private void writeForm(MultiValueMap<String, String> form, MediaType contentType,
private void writeForm(MultiValueMap<String, String> form, @Nullable MediaType contentType,
HttpOutputMessage outputMessage) throws IOException {
Charset charset;
@@ -387,6 +384,9 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@SuppressWarnings("unchecked")
private void writePart(String name, HttpEntity<?> partEntity, OutputStream os) throws IOException {
Object partBody = partEntity.getBody();
if (partBody == null) {
throw new IllegalStateException("Empty body for part '" + name + "': " + partEntity);
}
Class<?> partType = partBody.getClass();
HttpHeaders partHeaders = partEntity.getHeaders();
MediaType partContentType = partHeaders.getContentType();

View File

@@ -79,7 +79,7 @@ public interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T>
* @return {@code true} if writable; {@code false} otherwise
* @since 4.2
*/
boolean canWrite(@Nullable Type type, @Nullable Class<?> clazz, @Nullable MediaType mediaType);
boolean canWrite(@Nullable Type type, Class<?> clazz, @Nullable MediaType mediaType);
/**
* Write an given object to the given output message.

View File

@@ -66,7 +66,7 @@ public interface HttpMessageConverter<T> {
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
*/
T read(@Nullable Class<? extends T> clazz, HttpInputMessage inputMessage)
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/**

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.
@@ -91,12 +91,12 @@ public class ObjectToStringHttpMessageConverter extends AbstractHttpMessageConve
@Override
public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
return this.conversionService.canConvert(String.class, clazz) && canRead(mediaType);
return canRead(mediaType) && this.conversionService.canConvert(String.class, clazz);
}
@Override
public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
return this.conversionService.canConvert(clazz, String.class) && canWrite(mediaType);
return canWrite(mediaType) && this.conversionService.canConvert(clazz, String.class);
}
@Override
@@ -108,18 +108,28 @@ public class ObjectToStringHttpMessageConverter extends AbstractHttpMessageConve
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException {
String value = this.stringHttpMessageConverter.readInternal(String.class, inputMessage);
return this.conversionService.convert(value, clazz);
Object result = this.conversionService.convert(value, clazz);
if (result == null) {
throw new HttpMessageConversionException(
"Unexpected null conversion result for '" + value + "' to " + clazz);
}
return result;
}
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException {
String value = this.conversionService.convert(obj, String.class);
this.stringHttpMessageConverter.writeInternal(value, outputMessage);
if (value != null) {
this.stringHttpMessageConverter.writeInternal(value, outputMessage);
}
}
@Override
protected Long getContentLength(Object obj, @Nullable MediaType contentType) {
String value = this.conversionService.convert(obj, String.class);
if (value == null) {
return 0L;
}
return this.stringHttpMessageConverter.getContentLength(value, contentType);
}

View File

@@ -78,12 +78,11 @@ public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<R
protected Resource readInternal(Class<? extends Resource> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
final String filename = inputMessage.getHeaders().getContentDisposition().getFilename();
if (this.supportsReadStreaming && InputStreamResource.class == clazz) {
return new InputStreamResource(inputMessage.getBody()) {
@Override
public String getFilename() {
return filename;
return inputMessage.getHeaders().getContentDisposition().getFilename();
}
};
}
@@ -92,7 +91,7 @@ public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<R
return new ByteArrayResource(body) {
@Override
public String getFilename() {
return filename;
return inputMessage.getHeaders().getContentDisposition().getFilename();
}
};
}

View File

@@ -99,8 +99,9 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
@Override
public boolean canWrite(@Nullable Type type, @Nullable Class<?> clazz, @Nullable MediaType mediaType) {
if (!(type instanceof ParameterizedType)) {
return ResourceRegion.class.isAssignableFrom((Class<?>) type);
return (type instanceof Class && ResourceRegion.class.isAssignableFrom((Class<?>) type));
}
ParameterizedType parameterizedType = (ParameterizedType) type;
if (!(parameterizedType.getRawType() instanceof Class)) {
return false;
@@ -116,6 +117,7 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
if (!(typeArgument instanceof Class)) {
return false;
}
Class<?> typeArgumentClass = (Class<?>) typeArgument;
return typeArgumentClass.isAssignableFrom(ResourceRegion.class);
}

View File

@@ -26,6 +26,7 @@ import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
/**
@@ -116,12 +117,14 @@ public class StringHttpMessageConverter extends AbstractHttpMessageConverter<Str
return this.availableCharsets;
}
private Charset getContentTypeCharset(MediaType contentType) {
private Charset getContentTypeCharset(@Nullable MediaType contentType) {
if (contentType != null && contentType.getCharset() != null) {
return contentType.getCharset();
}
else {
return getDefaultCharset();
Charset charset = getDefaultCharset();
Assert.state(charset != null, "No default charset");
return charset;
}
}

View File

@@ -190,7 +190,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
* (typically a {@link JsonMappingException})
* @since 4.3
*/
protected void logWarningIfNecessary(Type type, Throwable cause) {
protected void logWarningIfNecessary(Type type, @Nullable Throwable cause) {
if (cause != null && !(cause instanceof JsonMappingException && cause.getMessage().startsWith("Can not find"))) {
String msg = "Failed to evaluate Jackson " + (type instanceof JavaType ? "de" : "") +
"serialization for type [" + type + "]";
@@ -258,7 +258,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
serializationView = container.getSerializationView();
filters = container.getFilters();
}
if (type != null && value != null && TypeUtils.isAssignable(type, value.getClass())) {
if (type != null && TypeUtils.isAssignable(type, value.getClass())) {
javaType = getJavaType(type, null);
}
ObjectWriter objectWriter;
@@ -326,7 +326,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
* @param contentType the media type as requested by the caller
* @return the JSON encoding to use (never {@code null})
*/
protected JsonEncoding getJsonEncoding(MediaType contentType) {
protected JsonEncoding getJsonEncoding(@Nullable MediaType contentType) {
if (contentType != null && contentType.getCharset() != null) {
Charset charset = contentType.getCharset();
for (JsonEncoding encoding : JsonEncoding.values()) {

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.
@@ -276,9 +276,7 @@ public class Jackson2ObjectMapperBuilder {
* @see com.fasterxml.jackson.databind.ObjectMapper#addMixInAnnotations(Class, Class)
*/
public Jackson2ObjectMapperBuilder mixIn(Class<?> target, Class<?> mixinSource) {
if (mixinSource != null) {
this.mixIns.put(target, mixinSource);
}
this.mixIns.put(target, mixinSource);
return this;
}
@@ -291,9 +289,7 @@ public class Jackson2ObjectMapperBuilder {
* @see com.fasterxml.jackson.databind.ObjectMapper#addMixInAnnotations(Class, Class)
*/
public Jackson2ObjectMapperBuilder mixIns(Map<Class<?>, Class<?>> mixIns) {
if (mixIns != null) {
this.mixIns.putAll(mixIns);
}
this.mixIns.putAll(mixIns);
return this;
}
@@ -303,14 +299,12 @@ public class Jackson2ObjectMapperBuilder {
* @see #serializersByType(Map)
*/
public Jackson2ObjectMapperBuilder serializers(JsonSerializer<?>... serializers) {
if (serializers != null) {
for (JsonSerializer<?> serializer : serializers) {
Class<?> handledType = serializer.handledType();
if (handledType == null || handledType == Object.class) {
throw new IllegalArgumentException("Unknown handled type in " + serializer.getClass().getName());
}
this.serializers.put(serializer.handledType(), serializer);
for (JsonSerializer<?> serializer : serializers) {
Class<?> handledType = serializer.handledType();
if (handledType == null || handledType == Object.class) {
throw new IllegalArgumentException("Unknown handled type in " + serializer.getClass().getName());
}
this.serializers.put(serializer.handledType(), serializer);
}
return this;
}
@@ -321,9 +315,7 @@ public class Jackson2ObjectMapperBuilder {
* @since 4.1.2
*/
public Jackson2ObjectMapperBuilder serializerByType(Class<?> type, JsonSerializer<?> serializer) {
if (serializer != null) {
this.serializers.put(type, serializer);
}
this.serializers.put(type, serializer);
return this;
}
@@ -332,9 +324,7 @@ public class Jackson2ObjectMapperBuilder {
* @see #serializers(JsonSerializer...)
*/
public Jackson2ObjectMapperBuilder serializersByType(Map<Class<?>, JsonSerializer<?>> serializers) {
if (serializers != null) {
this.serializers.putAll(serializers);
}
this.serializers.putAll(serializers);
return this;
}
@@ -345,14 +335,12 @@ public class Jackson2ObjectMapperBuilder {
* @see #deserializersByType(Map)
*/
public Jackson2ObjectMapperBuilder deserializers(JsonDeserializer<?>... deserializers) {
if (deserializers != null) {
for (JsonDeserializer<?> deserializer : deserializers) {
Class<?> handledType = deserializer.handledType();
if (handledType == null || handledType == Object.class) {
throw new IllegalArgumentException("Unknown handled type in " + deserializer.getClass().getName());
}
this.deserializers.put(deserializer.handledType(), deserializer);
for (JsonDeserializer<?> deserializer : deserializers) {
Class<?> handledType = deserializer.handledType();
if (handledType == null || handledType == Object.class) {
throw new IllegalArgumentException("Unknown handled type in " + deserializer.getClass().getName());
}
this.deserializers.put(deserializer.handledType(), deserializer);
}
return this;
}
@@ -362,9 +350,7 @@ public class Jackson2ObjectMapperBuilder {
* @since 4.1.2
*/
public Jackson2ObjectMapperBuilder deserializerByType(Class<?> type, JsonDeserializer<?> deserializer) {
if (deserializer != null) {
this.deserializers.put(type, deserializer);
}
this.deserializers.put(type, deserializer);
return this;
}
@@ -372,9 +358,7 @@ public class Jackson2ObjectMapperBuilder {
* Configure custom deserializers for the given types.
*/
public Jackson2ObjectMapperBuilder deserializersByType(Map<Class<?>, JsonDeserializer<?>> deserializers) {
if (deserializers != null) {
this.deserializers.putAll(deserializers);
}
this.deserializers.putAll(deserializers);
return this;
}
@@ -449,10 +433,8 @@ public class Jackson2ObjectMapperBuilder {
* @see com.fasterxml.jackson.databind.MapperFeature
*/
public Jackson2ObjectMapperBuilder featuresToEnable(Object... featuresToEnable) {
if (featuresToEnable != null) {
for (Object feature : featuresToEnable) {
this.features.put(feature, Boolean.TRUE);
}
for (Object feature : featuresToEnable) {
this.features.put(feature, Boolean.TRUE);
}
return this;
}
@@ -466,10 +448,8 @@ public class Jackson2ObjectMapperBuilder {
* @see com.fasterxml.jackson.databind.MapperFeature
*/
public Jackson2ObjectMapperBuilder featuresToDisable(Object... featuresToDisable) {
if (featuresToDisable != null) {
for (Object feature : featuresToDisable) {
this.features.put(feature, Boolean.FALSE);
}
for (Object feature : featuresToDisable) {
this.features.put(feature, Boolean.FALSE);
}
return this;
}

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.
@@ -422,7 +422,7 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
}
@Override
public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.builder.moduleClassLoader(beanClassLoader);
}

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.
@@ -21,6 +21,7 @@ import java.io.InputStream;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.lang.Nullable;
/**
* {@link HttpInputMessage} that can eventually stores a Jackson view that will be used
@@ -38,12 +39,12 @@ public class MappingJacksonInputMessage implements HttpInputMessage {
private Class<?> deserializationView;
public MappingJacksonInputMessage(InputStream body, HttpHeaders headers) {
public MappingJacksonInputMessage(@Nullable InputStream body, HttpHeaders headers) {
this.body = body;
this.headers = headers;
}
public MappingJacksonInputMessage(InputStream body, HttpHeaders headers, Class<?> deserializationView) {
public MappingJacksonInputMessage(@Nullable InputStream body, HttpHeaders headers, Class<?> deserializationView) {
this(body, headers);
this.deserializationView = deserializationView;
}
@@ -63,6 +64,7 @@ public class MappingJacksonInputMessage implements HttpInputMessage {
this.deserializationView = deserializationView;
}
@Nullable
public Class<?> getDeserializationView() {
return this.deserializationView;
}

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.
@@ -18,6 +18,8 @@ package org.springframework.http.converter.json;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import org.springframework.lang.Nullable;
/**
* A simple holder for the POJO to serialize via
* {@link MappingJackson2HttpMessageConverter} along with further
@@ -72,7 +74,7 @@ public class MappingJacksonValue {
* @see com.fasterxml.jackson.databind.ObjectMapper#writerWithView(Class)
* @see com.fasterxml.jackson.annotation.JsonView
*/
public void setSerializationView(Class<?> serializationView) {
public void setSerializationView(@Nullable Class<?> serializationView) {
this.serializationView = serializationView;
}
@@ -81,6 +83,7 @@ public class MappingJacksonValue {
* @see com.fasterxml.jackson.databind.ObjectMapper#writerWithView(Class)
* @see com.fasterxml.jackson.annotation.JsonView
*/
@Nullable
public Class<?> getSerializationView() {
return this.serializationView;
}
@@ -102,6 +105,7 @@ public class MappingJacksonValue {
* @see com.fasterxml.jackson.databind.ObjectMapper#writer(FilterProvider)
* @see com.fasterxml.jackson.annotation.JsonFilter
*/
@Nullable
public FilterProvider getFilters() {
return this.filters;
}
@@ -116,6 +120,7 @@ public class MappingJacksonValue {
/**
* Return the configured JSONP function name.
*/
@Nullable
public String getJsonpFunction() {
return this.jsonpFunction;
}

View File

@@ -42,6 +42,7 @@ import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import static org.springframework.http.MediaType.*;
@@ -105,11 +106,13 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
* initializer that allows the registration of message extensions.
* @param registryInitializer an initializer for message extensions
*/
public ProtobufHttpMessageConverter(ExtensionRegistryInitializer registryInitializer) {
public ProtobufHttpMessageConverter(@Nullable ExtensionRegistryInitializer registryInitializer) {
this(null, registryInitializer);
}
ProtobufHttpMessageConverter(ProtobufFormatSupport formatSupport, ExtensionRegistryInitializer registryInitializer) {
ProtobufHttpMessageConverter(@Nullable ProtobufFormatSupport formatSupport,
@Nullable ExtensionRegistryInitializer registryInitializer) {
if (formatSupport != null) {
this.protobufFormatSupport = formatSupport;
}
@@ -188,6 +191,7 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = getDefaultContentType(message);
Assert.state(contentType != null, "No content type");
}
Charset charset = contentType.getCharset();
if (charset == null) {
@@ -242,12 +246,13 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
MediaType[] supportedMediaTypes();
boolean supportsWriteOnly(MediaType mediaType);
boolean supportsWriteOnly(@Nullable MediaType mediaType);
void merge(InputStream input, Charset charset, MediaType contentType, ExtensionRegistry extensionRegistry,
Message.Builder builder) throws IOException;
void merge(InputStream input, Charset charset, MediaType contentType,
ExtensionRegistry extensionRegistry, Message.Builder builder) throws IOException;
void print(Message message, OutputStream output, MediaType contentType, Charset charset) throws IOException;
void print(Message message, OutputStream output, MediaType contentType, Charset charset)
throws IOException;
}
@@ -272,7 +277,7 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
}
@Override
public boolean supportsWriteOnly(MediaType mediaType) {
public boolean supportsWriteOnly(@Nullable MediaType mediaType) {
return TEXT_HTML.isCompatibleWith(mediaType);
}
@@ -328,7 +333,7 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
}
@Override
public boolean supportsWriteOnly(MediaType mediaType) {
public boolean supportsWriteOnly(@Nullable MediaType mediaType) {
return false;
}

View File

@@ -18,6 +18,8 @@ package org.springframework.http.converter.protobuf;
import com.google.protobuf.util.JsonFormat;
import org.springframework.lang.Nullable;
/**
* Subclass of {@link ProtobufHttpMessageConverter} which enforces the use of Protobuf 3 and
* its official library {@code "com.google.protobuf:protobuf-java-util"} for JSON processing.
@@ -51,7 +53,9 @@ public class ProtobufJsonFormatHttpMessageConverter extends ProtobufHttpMessageC
* @param parser the JSON parser configuration
* @param printer the JSON printer configuration
*/
public ProtobufJsonFormatHttpMessageConverter(JsonFormat.Parser parser, JsonFormat.Printer printer) {
public ProtobufJsonFormatHttpMessageConverter(
@Nullable JsonFormat.Parser parser, @Nullable JsonFormat.Printer printer) {
this(parser, printer, null);
}
@@ -63,8 +67,8 @@ public class ProtobufJsonFormatHttpMessageConverter extends ProtobufHttpMessageC
* @param printer the JSON printer configuration
* @param registryInitializer an initializer for message extensions
*/
public ProtobufJsonFormatHttpMessageConverter(JsonFormat.Parser parser, JsonFormat.Printer printer,
ExtensionRegistryInitializer registryInitializer) {
public ProtobufJsonFormatHttpMessageConverter(@Nullable JsonFormat.Parser parser,
@Nullable JsonFormat.Printer printer, @Nullable ExtensionRegistryInitializer registryInitializer) {
super(new ProtobufJavaUtilSupport(parser, printer), registryInitializer);
}

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.
@@ -195,7 +195,7 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
}
}
private void setCharset(MediaType contentType, Marshaller marshaller) throws PropertyException {
private void setCharset(@Nullable MediaType contentType, Marshaller marshaller) throws PropertyException {
if (contentType != null && contentType.getCharset() != null) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, contentType.getCharset().name());
}

View File

@@ -90,11 +90,11 @@ public abstract class AbstractServerHttpRequest implements ServerHttpRequest {
if (query != null) {
Matcher matcher = QUERY_PATTERN.matcher(query);
while (matcher.find()) {
String name = matcher.group(1);
String name = decodeQueryParam(matcher.group(1));
String eq = matcher.group(2);
String value = matcher.group(3);
value = (value != null ? value : (StringUtils.hasLength(eq) ? "" : null));
queryParams.add(decodeQueryParam(name), decodeQueryParam(value));
value = (value != null ? decodeQueryParam(value) : (StringUtils.hasLength(eq) ? "" : null));
queryParams.add(name, value);
}
}
return queryParams;

View File

@@ -146,9 +146,7 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
@Override
public void beforeCommit(Supplier<? extends Mono<Void>> action) {
if (action != null) {
this.commitActions.add(action);
}
this.commitActions.add(action);
}
@Override

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.
@@ -21,7 +21,6 @@ import java.util.function.Function;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.Exceptions;
import reactor.core.publisher.MonoSource;
import reactor.core.publisher.Operators;
@@ -246,17 +245,11 @@ public class ChannelSendOperator<T> extends MonoSource<T, Void> {
@Override
public final void onError(Throwable t) {
if (t == null) {
throw Exceptions.argumentIsNullException();
}
doError(t);
}
@Override
public final void onNext(I i) {
if (i == null) {
throw Exceptions.argumentIsNullException();
}
try {
doNext(i);
}

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.
@@ -21,6 +21,7 @@ import java.net.URISyntaxException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -108,7 +109,7 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
private final HttpHeaders httpHeaders;
public MutativeDecorator(ServerHttpRequest delegate, HttpMethod httpMethod,
URI uri, String contextPath, HttpHeaders httpHeaders) {
@Nullable URI uri, String contextPath, @Nullable HttpHeaders httpHeaders) {
super(delegate);
this.httpMethod = httpMethod;

View File

@@ -17,6 +17,8 @@
package org.springframework.http.server.reactive;
import java.io.File;
import java.util.List;
import java.util.Map;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpResponseStatus;
@@ -82,9 +84,9 @@ public class ReactorServerHttpResponse extends AbstractServerHttpResponse implem
@Override
protected void applyHeaders() {
for (String name : getHeaders().keySet()) {
for (String value : getHeaders().get(name)) {
this.response.responseHeaders().add(name, value);
for (Map.Entry<String, List<String>> entry : getHeaders().entrySet()) {
for (String value : entry.getValue()) {
this.response.responseHeaders().add(entry.getKey(), value);
}
}
}

View File

@@ -26,7 +26,6 @@ import io.undertow.connector.PooledByteBuffer;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.Cookie;
import io.undertow.util.HeaderValues;
import org.xnio.ChannelListener;
import org.xnio.channels.StreamSourceChannel;
import reactor.core.publisher.Flux;
@@ -118,7 +117,6 @@ public class UndertowServerHttpRequest extends AbstractServerHttpRequest {
private PooledByteBuffer pooledByteBuffer;
public RequestBodyPublisher(HttpServerExchange exchange, DataBufferFactory bufferFactory) {
this.channel = exchange.getRequestChannel();
this.bufferFactory = bufferFactory;
@@ -130,13 +128,15 @@ public class UndertowServerHttpRequest extends AbstractServerHttpRequest {
onAllDataRead();
next.proceed();
});
this.channel.getReadSetter().set((ChannelListener<StreamSourceChannel>) c -> onDataAvailable());
this.channel.getCloseSetter().set((ChannelListener<StreamSourceChannel>) c -> onAllDataRead());
this.channel.getReadSetter().set(c -> onDataAvailable());
this.channel.getCloseSetter().set(c -> onAllDataRead());
this.channel.resumeReads();
}
@Override
protected void checkOnDataAvailable() {
// TODO: The onDataAvailable() call below can cause a StackOverflowError
// since this method is being called from onDataAvailable() itself.
onDataAvailable();
}

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.
@@ -30,6 +30,7 @@ import com.caucho.hessian.io.SerializerFactory;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteConnectFailureException;
import org.springframework.remoting.RemoteLookupFailureException;
@@ -76,7 +77,7 @@ public class HessianClientInterceptor extends UrlBasedRemoteAccessor implements
* <p>Allows to use an externally configured factory instance,
* in particular a custom HessianProxyFactory subclass.
*/
public void setProxyFactory(HessianProxyFactory proxyFactory) {
public void setProxyFactory(@Nullable HessianProxyFactory proxyFactory) {
this.proxyFactory = (proxyFactory != null ? proxyFactory : new HessianProxyFactory());
}

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.
@@ -36,6 +36,7 @@ import com.caucho.hessian.server.HessianSkeleton;
import org.apache.commons.logging.Log;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.remoting.support.RemoteExporter;
import org.springframework.util.Assert;
import org.springframework.util.CommonsLogWriter;
@@ -74,7 +75,7 @@ public class HessianExporter extends RemoteExporter implements InitializingBean
* of type {@code com.caucho.hessian.io.SerializerFactory},
* with custom bean property values applied.
*/
public void setSerializerFactory(SerializerFactory serializerFactory) {
public void setSerializerFactory(@Nullable SerializerFactory serializerFactory) {
this.serializerFactory = (serializerFactory != null ? serializerFactory : new SerializerFactory());
}

View File

@@ -113,7 +113,7 @@ public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerR
}
@Override
public void setBeanClassLoader(@Nullable ClassLoader classLoader) {
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@@ -234,7 +234,7 @@ public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerR
* @see #createObjectInputStream
* @see #doReadRemoteInvocationResult
*/
protected RemoteInvocationResult readRemoteInvocationResult(InputStream is, String codebaseUrl)
protected RemoteInvocationResult readRemoteInvocationResult(InputStream is, @Nullable String codebaseUrl)
throws IOException, ClassNotFoundException {
ObjectInputStream ois = createObjectInputStream(decorateInputStream(is), codebaseUrl);

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.
@@ -94,7 +94,7 @@ public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvoke
this(httpClient, null);
}
private HttpComponentsHttpInvokerRequestExecutor(HttpClient httpClient, RequestConfig requestConfig) {
private HttpComponentsHttpInvokerRequestExecutor(HttpClient httpClient, @Nullable RequestConfig requestConfig) {
this.httpClient = httpClient;
this.requestConfig = requestConfig;
}

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.
@@ -42,6 +42,7 @@ import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteConnectFailureException;
import org.springframework.remoting.RemoteLookupFailureException;
import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -129,6 +130,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
/**
* Return the name of the port.
*/
@Nullable
public String getPortName() {
return this.portName;
}
@@ -144,6 +146,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
/**
* Return the username to specify on the stub.
*/
@Nullable
public String getUsername() {
return this.username;
}
@@ -159,6 +162,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
/**
* Return the password to specify on the stub.
*/
@Nullable
public String getPassword() {
return this.password;
}
@@ -174,6 +178,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
/**
* Return the endpoint address to specify on the stub.
*/
@Nullable
public String getEndpointAddress() {
return this.endpointAddress;
}
@@ -219,6 +224,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
/**
* Return the SOAP action URI to specify on the stub.
*/
@Nullable
public String getSoapActionUri() {
return this.soapActionUri;
}
@@ -272,7 +278,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
* Set the interface of the service that this factory should create a proxy for.
*/
public void setServiceInterface(Class<?> serviceInterface) {
if (serviceInterface != null && !serviceInterface.isInterface()) {
if (!serviceInterface.isInterface()) {
throw new IllegalArgumentException("'serviceInterface' must be an interface");
}
this.serviceInterface = serviceInterface;
@@ -281,6 +287,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
/**
* Return the interface of the service that this factory should create a proxy for.
*/
@Nullable
public Class<?> getServiceInterface() {
return this.serviceInterface;
}
@@ -300,7 +307,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
* building a client proxy in the {@link JaxWsPortProxyFactoryBean} subclass.
*/
@Override
public void setBeanClassLoader(@Nullable ClassLoader classLoader) {
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@@ -324,18 +331,19 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
*/
public void prepare() {
Class<?> ifc = getServiceInterface();
if (ifc == null) {
throw new IllegalArgumentException("Property 'serviceInterface' is required");
}
Assert.notNull(ifc, "Property 'serviceInterface' is required");
WebService ann = ifc.getAnnotation(WebService.class);
if (ann != null) {
applyDefaultsFromAnnotation(ann);
}
Service serviceToUse = getJaxWsService();
if (serviceToUse == null) {
serviceToUse = createJaxWsService();
}
this.portQName = getQName(getPortName() != null ? getPortName() : getServiceInterface().getName());
this.portQName = getQName(getPortName() != null ? getPortName() : ifc.getName());
Object stub = getPortStub(serviceToUse, (getPortName() != null ? this.portQName : null));
preparePortStub(stub);
this.portStub = stub;
@@ -407,7 +415,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
* @return the corresponding port object as returned from
* {@code Service.getPort(...)}
*/
protected Object getPortStub(Service service, QName portQName) {
protected Object getPortStub(Service service, @Nullable QName portQName) {
if (this.portFeatures != null) {
return (portQName != null ? service.getPort(portQName, getServiceInterface(), this.portFeatures) :
service.getPort(getServiceInterface(), this.portFeatures));

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,6 +20,7 @@ import javax.xml.ws.BindingProvider;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.Assert;
/**
* {@link org.springframework.beans.factory.FactoryBean} for a specific port of a
@@ -40,9 +41,12 @@ public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor implem
public void afterPropertiesSet() {
super.afterPropertiesSet();
Class<?> ifc = getServiceInterface();
Assert.notNull(ifc, "Property 'serviceInterface' is required");
// Build a proxy that also exposes the JAX-WS BindingProvider interface.
ProxyFactory pf = new ProxyFactory();
pf.addInterface(getServiceInterface());
pf.addInterface(ifc);
pf.addInterface(BindingProvider.class);
pf.addAdvice(this);
this.serviceProxy = pf.getProxy(getBeanClassLoader());

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.
@@ -25,6 +25,7 @@ import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.handler.HandlerResolver;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -77,6 +78,7 @@ public class LocalJaxWsServiceFactory {
/**
* Return the URL of the WSDL document that describes the service.
*/
@Nullable
public URL getWsdlDocumentUrl() {
return this.wsdlDocumentUrl;
}
@@ -85,13 +87,14 @@ public class LocalJaxWsServiceFactory {
* Set the namespace URI of the service.
* Corresponds to the WSDL "targetNamespace".
*/
public void setNamespaceUri(String namespaceUri) {
public void setNamespaceUri(@Nullable String namespaceUri) {
this.namespaceUri = (namespaceUri != null ? namespaceUri.trim() : null);
}
/**
* Return the namespace URI of the service.
*/
@Nullable
public String getNamespaceUri() {
return this.namespaceUri;
}
@@ -107,6 +110,7 @@ public class LocalJaxWsServiceFactory {
/**
* Return the name of the service.
*/
@Nullable
public String getServiceName() {
return this.serviceName;
}

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.
@@ -19,6 +19,7 @@ package org.springframework.web;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
* Exception thrown when a client POSTs, PUTs, or PATCHes content of a type
@@ -47,8 +48,8 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException {
* @param contentType the unsupported content type
* @param supportedMediaTypes the list of supported media types
*/
public HttpMediaTypeNotSupportedException(MediaType contentType, List<MediaType> supportedMediaTypes) {
this(contentType, supportedMediaTypes, "Content type '" + contentType + "' not supported");
public HttpMediaTypeNotSupportedException(@Nullable MediaType contentType, List<MediaType> supportedMediaTypes) {
this(contentType, supportedMediaTypes, "Content type '" + (contentType != null ? contentType : "") + "' not supported");
}
/**
@@ -57,7 +58,7 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException {
* @param supportedMediaTypes the list of supported media types
* @param msg the detail message
*/
public HttpMediaTypeNotSupportedException(MediaType contentType, List<MediaType> supportedMediaTypes, String msg) {
public HttpMediaTypeNotSupportedException(@Nullable MediaType contentType, List<MediaType> supportedMediaTypes, String msg) {
super(msg, supportedMediaTypes);
this.contentType = contentType;
}

View File

@@ -21,7 +21,6 @@ import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletException;
import org.springframework.http.HttpMethod;
@@ -66,7 +65,7 @@ public class HttpRequestMethodNotSupportedException extends ServletException {
* @param supportedMethods the actually supported HTTP methods (may be {@code null})
*/
public HttpRequestMethodNotSupportedException(String method, @Nullable Collection<String> supportedMethods) {
this(method, StringUtils.toStringArray(supportedMethods));
this(method, (supportedMethods != null ? StringUtils.toStringArray(supportedMethods) : null));
}
/**
@@ -84,7 +83,7 @@ public class HttpRequestMethodNotSupportedException extends ServletException {
* @param supportedMethods the actually supported HTTP methods
* @param msg the detail message
*/
public HttpRequestMethodNotSupportedException(String method, String[] supportedMethods, String msg) {
public HttpRequestMethodNotSupportedException(String method, @Nullable String[] supportedMethods, String msg) {
super(msg);
this.method = method;
this.supportedMethods = supportedMethods;

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.
@@ -27,6 +27,7 @@ import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
/**
@@ -138,7 +139,7 @@ public class SpringServletContainerInitializer implements ServletContainerInitia
* @see AnnotationAwareOrderComparator
*/
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();

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,7 +50,7 @@ public abstract class AbstractMappingContentNegotiationStrategy extends MappingM
/**
* Create an instance with the given map of file extensions and media types.
*/
public AbstractMappingContentNegotiationStrategy(Map<String, MediaType> mediaTypes) {
public AbstractMappingContentNegotiationStrategy(@Nullable Map<String, MediaType> mediaTypes) {
super(mediaTypes);
}
@@ -67,7 +67,7 @@ public abstract class AbstractMappingContentNegotiationStrategy extends MappingM
* an already extracted key.
* @since 3.2.16
*/
public List<MediaType> resolveMediaTypeKey(@Nullable NativeWebRequest webRequest, String key)
public List<MediaType> resolveMediaTypeKey(NativeWebRequest webRequest, @Nullable String key)
throws HttpMediaTypeNotAcceptableException {
if (StringUtils.hasText(key)) {
@@ -88,7 +88,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
*/
@Nullable
protected abstract String getMediaTypeKey(NativeWebRequest request);
@@ -113,4 +113,4 @@ public abstract class AbstractMappingContentNegotiationStrategy extends MappingM
return null;
}
}
}

View File

@@ -29,6 +29,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.ServletContextAware;
@@ -160,7 +161,7 @@ public class ContentNegotiationManagerFactoryBean
* @see #setMediaTypes
* @see #addMediaType
*/
public void addMediaTypes(Map<String, MediaType> mediaTypes) {
public void addMediaTypes(@Nullable Map<String, MediaType> mediaTypes) {
if (mediaTypes != null) {
this.mediaTypes.putAll(mediaTypes);
}
@@ -267,6 +268,11 @@ public class ContentNegotiationManagerFactoryBean
}
public ContentNegotiationManager build() {
afterPropertiesSet();
return this.contentNegotiationManager;
}
@Override
public void afterPropertiesSet() {
List<ContentNegotiationStrategy> strategies = new ArrayList<>();

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.
@@ -55,7 +55,7 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
/**
* Create an instance with the given map of file extensions and media types.
*/
public MappingMediaTypeFileExtensionResolver(Map<String, MediaType> mediaTypes) {
public MappingMediaTypeFileExtensionResolver(@Nullable Map<String, MediaType> mediaTypes) {
if (mediaTypes != null) {
for (Entry<String, MediaType> entries : mediaTypes.entrySet()) {
String extension = entries.getKey().toLowerCase(Locale.ENGLISH);

View File

@@ -69,7 +69,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
/**
* Create an instance with the given map of file extensions and media types.
*/
public PathExtensionContentNegotiationStrategy(Map<String, MediaType> mediaTypes) {
public PathExtensionContentNegotiationStrategy(@Nullable Map<String, MediaType> mediaTypes) {
super(mediaTypes);
this.urlPathHelper.setUrlDecode(false);
}

View File

@@ -22,6 +22,7 @@ import javax.servlet.ServletContext;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
@@ -39,17 +40,6 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
private final ServletContext servletContext;
/**
* Create an instance with the given extension-to-MediaType lookup.
*/
public ServletPathExtensionContentNegotiationStrategy(
ServletContext servletContext, Map<String, MediaType> mediaTypes) {
super(mediaTypes);
Assert.notNull(servletContext, "ServletContext is required");
this.servletContext = servletContext;
}
/**
* Create an instance without any mappings to start with. Mappings may be
* added later when extensions are resolved through
@@ -60,6 +50,17 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
this(context, null);
}
/**
* Create an instance with the given extension-to-MediaType lookup.
*/
public ServletPathExtensionContentNegotiationStrategy(
ServletContext servletContext, @Nullable Map<String, MediaType> mediaTypes) {
super(mediaTypes);
Assert.notNull(servletContext, "ServletContext is required");
this.servletContext = servletContext;
}
/**
* Resolve file extension via {@link ServletContext#getMimeType(String)}

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,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
@@ -48,9 +49,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;
}
@@ -65,7 +64,7 @@ public class EscapedErrors implements Errors {
}
@Override
public void setNestedPath(@Nullable String nestedPath) {
public void setNestedPath(String nestedPath) {
this.source.setNestedPath(nestedPath);
}
@@ -203,15 +202,20 @@ public class EscapedErrors implements Errors {
}
@Override
public Class<?> getFieldType(@Nullable String field) {
public Class<?> getFieldType(String field) {
return this.source.getFieldType(field);
}
@SuppressWarnings("unchecked")
private <T extends ObjectError> T escapeObjectError(T source) {
@Nullable
private <T extends ObjectError> T escapeObjectError(@Nullable T source) {
if (source == null) {
return null;
}
String defaultMessage = source.getDefaultMessage();
if (defaultMessage != null) {
defaultMessage = HtmlUtils.htmlEscape(defaultMessage);
}
if (source instanceof FieldError) {
FieldError fieldError = (FieldError) source;
Object value = fieldError.getRejectedValue();
@@ -219,14 +223,12 @@ public class EscapedErrors implements Errors {
value = HtmlUtils.htmlEscape((String) value);
}
return (T) new FieldError(
fieldError.getObjectName(), fieldError.getField(), value,
fieldError.isBindingFailure(), fieldError.getCodes(),
fieldError.getArguments(), HtmlUtils.htmlEscape(fieldError.getDefaultMessage()));
fieldError.getObjectName(), fieldError.getField(), value, fieldError.isBindingFailure(),
fieldError.getCodes(), fieldError.getArguments(), defaultMessage);
}
else {
return (T) new ObjectError(
source.getObjectName(), source.getCodes(), source.getArguments(),
HtmlUtils.htmlEscape(source.getDefaultMessage()));
source.getObjectName(), source.getCodes(), source.getArguments(), defaultMessage);
}
}

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.
@@ -63,7 +63,7 @@ public class MethodArgumentNotValidException extends Exception {
public String getMessage() {
StringBuilder sb = new StringBuilder("Validation failed for argument at index ")
.append(this.parameter.getParameterIndex()).append(" in method: ")
.append(this.parameter.getMethod().toGenericString())
.append(this.parameter.getExecutable().toGenericString())
.append(", with ").append(this.bindingResult.getErrorCount()).append(" error(s): ");
for (ObjectError error : this.bindingResult.getAllErrors()) {
sb.append("[").append(error).append("] ");

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.
@@ -75,7 +75,7 @@ public class ServletRequestDataBinder extends WebDataBinder {
* if the binder is just used to convert a plain parameter value)
* @param objectName the name of the target object
*/
public ServletRequestDataBinder(@Nullable Object target, String objectName) {
public ServletRequestDataBinder(@Nullable Object target, @Nullable String objectName) {
super(target, objectName);
}

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 javax.servlet.ServletRequest;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.lang.Nullable;
import org.springframework.web.util.WebUtils;
/**
@@ -60,7 +61,7 @@ public class ServletRequestParameterPropertyValues extends MutablePropertyValues
* consist of this plus the separator)
* @see #DEFAULT_PREFIX_SEPARATOR
*/
public ServletRequestParameterPropertyValues(ServletRequest request, String prefix) {
public ServletRequestParameterPropertyValues(ServletRequest request, @Nullable String prefix) {
this(request, prefix, DEFAULT_PREFIX_SEPARATOR);
}
@@ -73,7 +74,9 @@ public class ServletRequestParameterPropertyValues extends MutablePropertyValues
* @param prefixSeparator separator delimiting prefix (e.g. "spring")
* and the rest of the parameter name ("param1", "param2")
*/
public ServletRequestParameterPropertyValues(ServletRequest request, String prefix, String prefixSeparator) {
public ServletRequestParameterPropertyValues(
ServletRequest request, @Nullable String prefix, @Nullable String prefixSeparator) {
super(WebUtils.getParametersStartingWith(
request, (prefix != null ? prefix + prefixSeparator : null)));
}

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.
@@ -538,7 +538,7 @@ public abstract class ServletRequestUtils {
}
}
protected final void validateRequiredParameter(String name, Object parameter)
protected final void validateRequiredParameter(String name, @Nullable Object parameter)
throws ServletRequestBindingException {
if (parameter == null) {

View File

@@ -98,7 +98,7 @@ public class WebDataBinder extends DataBinder {
* if the binder is just used to convert a plain parameter value)
* @param objectName the name of the target object
*/
public WebDataBinder(@Nullable Object target, String objectName) {
public WebDataBinder(@Nullable Object target, @Nullable String objectName) {
super(target, objectName);
}
@@ -131,6 +131,7 @@ public class WebDataBinder extends DataBinder {
/**
* Return the prefix for parameters that mark potentially empty fields.
*/
@Nullable
public String getFieldMarkerPrefix() {
return this.fieldMarkerPrefix;
}
@@ -156,6 +157,7 @@ public class WebDataBinder extends DataBinder {
/**
* Return the prefix for parameters that mark default fields.
*/
@Nullable
public String getFieldDefaultPrefix() {
return this.fieldDefaultPrefix;
}

View File

@@ -68,8 +68,8 @@ public class DefaultDataBinderFactory implements WebDataBinderFactory {
* @param webRequest the current request
* @throws Exception in case of invalid state or arguments
*/
protected WebDataBinder createBinderInstance(@Nullable Object target, String objectName,
NativeWebRequest webRequest) throws Exception {
protected WebDataBinder createBinderInstance(
@Nullable Object target, @Nullable String objectName, NativeWebRequest webRequest) throws Exception {
return new WebRequestDataBinder(target, objectName);
}

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,6 +16,7 @@
package org.springframework.web.bind.support;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.context.request.WebRequest;
@@ -41,7 +42,7 @@ public class DefaultSessionAttributeStore implements SessionAttributeStore {
* <p>Default is to use no prefix, storing the session attributes with the
* same name as in the model.
*/
public void setAttributeNamePrefix(String attributeNamePrefix) {
public void setAttributeNamePrefix(@Nullable String attributeNamePrefix) {
this.attributeNamePrefix = (attributeNamePrefix != null ? attributeNamePrefix : "");
}

View File

@@ -36,7 +36,7 @@ public interface SessionAttributeStore {
* @param attributeName the name of the attribute
* @param attributeValue the attribute value to store
*/
void storeAttribute(WebRequest request, String attributeName, Object attributeValue);
void storeAttribute(WebRequest request, String attributeName, @Nullable Object attributeValue);
/**
* Retrieve the specified attribute from the backend session.

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.
@@ -17,6 +17,7 @@
package org.springframework.web.bind.support;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.context.request.NativeWebRequest;
/**
@@ -58,6 +59,7 @@ public interface WebArgumentResolver {
* @return the argument value, or {@code UNRESOLVED} if not resolvable
* @throws Exception in case of resolution failure
*/
@Nullable
Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception;
}

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
@@ -67,7 +68,7 @@ public class WebExchangeBindException extends ServerWebInputException implements
}
@Override
public void setNestedPath(@Nullable String nestedPath) {
public void setNestedPath(String nestedPath) {
this.bindingResult.setNestedPath(nestedPath);
}
@@ -113,7 +114,9 @@ public class WebExchangeBindException extends ServerWebInputException implements
}
@Override
public void rejectValue(@Nullable String field, String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage) {
public void rejectValue(
@Nullable String field, String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage) {
this.bindingResult.rejectValue(field, errorCode, errorArgs, defaultMessage);
}
@@ -204,7 +207,7 @@ public class WebExchangeBindException extends ServerWebInputException implements
}
@Override
public Class<?> getFieldType(@Nullable String field) {
public Class<?> getFieldType(String field) {
return this.bindingResult.getFieldType(field);
}
@@ -266,9 +269,10 @@ public class WebExchangeBindException extends ServerWebInputException implements
@Override
public String getMessage() {
MethodParameter parameter = getMethodParameter();
Assert.state(parameter != null, "No MethodParameter");
StringBuilder sb = new StringBuilder("Validation failed for argument at index ")
.append(parameter.getParameterIndex()).append(" in method: ")
.append(parameter.getMethod().toGenericString())
.append(parameter.getExecutable().toGenericString())
.append(", with ").append(this.bindingResult.getErrorCount()).append(" error(s): ");
for (ObjectError error : this.bindingResult.getAllErrors()) {
sb.append("[").append(error).append("] ");

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.
@@ -18,7 +18,6 @@ package org.springframework.web.bind.support;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
@@ -87,7 +86,7 @@ public class WebRequestDataBinder extends WebDataBinder {
* if the binder is just used to convert a plain parameter value)
* @param objectName the name of the target object
*/
public WebRequestDataBinder(@Nullable Object target, String objectName) {
public WebRequestDataBinder(@Nullable Object target, @Nullable String objectName) {
super(target, objectName);
}
@@ -119,7 +118,9 @@ public class WebRequestDataBinder extends WebDataBinder {
}
else {
HttpServletRequest servletRequest = ((NativeWebRequest) request).getNativeRequest(HttpServletRequest.class);
bindParts(servletRequest, mpvs);
if (servletRequest != null) {
bindParts(servletRequest, mpvs);
}
}
}
doBind(mpvs);

View File

@@ -556,7 +556,7 @@ public class AsyncRestTemplate extends org.springframework.http.client.support.I
* Returns a request callback implementation that writes the given object to the
* request stream.
*/
protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T> requestBody) {
protected <T> AsyncRequestCallback httpEntityCallback(@Nullable HttpEntity<T> requestBody) {
return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(requestBody));
}
@@ -564,7 +564,7 @@ public class AsyncRestTemplate extends org.springframework.http.client.support.I
* Returns a request callback implementation that writes the given object to the
* request stream.
*/
protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T> request, Type responseType) {
protected <T> AsyncRequestCallback httpEntityCallback(@Nullable HttpEntity<T> request, Type responseType) {
return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(request, responseType));
}
@@ -596,7 +596,9 @@ public class AsyncRestTemplate extends org.springframework.http.client.support.I
private final ResponseExtractor<T> responseExtractor;
public ResponseExtractorFuture(HttpMethod method, URI url,
ListenableFuture<ClientHttpResponse> clientHttpResponseFuture, ResponseExtractor<T> responseExtractor) {
ListenableFuture<ClientHttpResponse> clientHttpResponseFuture,
@Nullable ResponseExtractor<T> responseExtractor) {
super(clientHttpResponseFuture);
this.method = method;
this.url = url;
@@ -618,12 +620,11 @@ public class AsyncRestTemplate extends org.springframework.http.client.support.I
throw new ExecutionException(ex);
}
finally {
if (response != null) {
response.close();
}
response.close();
}
}
@Nullable
protected T convertResponse(ClientHttpResponse response) throws IOException {
return (this.responseExtractor != null ? this.responseExtractor.extractData(response) : null);
}
@@ -648,34 +649,32 @@ public class AsyncRestTemplate extends org.springframework.http.client.support.I
@Override
public void doWithRequest(final org.springframework.http.client.AsyncClientHttpRequest request) throws IOException {
if (this.adaptee != null) {
this.adaptee.doWithRequest(new ClientHttpRequest() {
@Override
public ClientHttpResponse execute() throws IOException {
throw new UnsupportedOperationException("execute not supported");
}
@Override
public OutputStream getBody() throws IOException {
return request.getBody();
}
@Override
public HttpMethod getMethod() {
return request.getMethod();
}
@Override
public String getMethodValue() {
return request.getMethodValue();
}
@Override
public URI getURI() {
return request.getURI();
}
@Override
public HttpHeaders getHeaders() {
return request.getHeaders();
}
});
}
this.adaptee.doWithRequest(new ClientHttpRequest() {
@Override
public ClientHttpResponse execute() throws IOException {
throw new UnsupportedOperationException("execute not supported");
}
@Override
public OutputStream getBody() throws IOException {
return request.getBody();
}
@Override
public HttpMethod getMethod() {
return request.getMethod();
}
@Override
public String getMethodValue() {
return request.getMethodValue();
}
@Override
public URI getURI() {
return request.getURI();
}
@Override
public HttpHeaders getHeaders() {
return request.getHeaders();
}
});
}
}

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.
@@ -61,7 +61,7 @@ class MessageBodyClientHttpResponseWrapper implements ClientHttpResponse {
responseStatus == HttpStatus.NOT_MODIFIED) {
return false;
}
else if (this.getHeaders().getContentLength() == 0) {
else if (getHeaders().getContentLength() == 0) {
return false;
}
return true;
@@ -79,10 +79,7 @@ class MessageBodyClientHttpResponseWrapper implements ClientHttpResponse {
*/
public boolean hasEmptyMessageBody() throws IOException {
InputStream body = this.response.getBody();
if (body == null) {
return true;
}
else if (body.markSupported()) {
if (body.markSupported()) {
body.mark(1);
if (body.read() == -1) {
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.
@@ -154,6 +154,7 @@ public interface RestOperations {
* @return the value for the {@code Location} header
* @see HttpEntity
*/
@Nullable
URI postForLocation(String url, @Nullable Object request, Object... uriVariables) throws RestClientException;
/**
@@ -168,6 +169,7 @@ public interface RestOperations {
* @return the value for the {@code Location} header
* @see HttpEntity
*/
@Nullable
URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables) throws RestClientException;
/**
@@ -180,6 +182,7 @@ public interface RestOperations {
* @return the value for the {@code Location} header
* @see HttpEntity
*/
@Nullable
URI postForLocation(URI url, @Nullable Object request) throws RestClientException;
/**

View File

@@ -20,6 +20,7 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -339,7 +340,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}
@Override
@@ -348,14 +349,14 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}
@Override
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor));
}
@@ -363,17 +364,17 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
@Override
public HttpHeaders headForHeaders(String url, Object... uriVariables) throws RestClientException {
return execute(url, HttpMethod.HEAD, null, headersExtractor(), uriVariables);
return nonNull(execute(url, HttpMethod.HEAD, null, headersExtractor(), uriVariables));
}
@Override
public HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables) throws RestClientException {
return execute(url, HttpMethod.HEAD, null, headersExtractor(), uriVariables);
return nonNull(execute(url, HttpMethod.HEAD, null, headersExtractor(), uriVariables));
}
@Override
public HttpHeaders headForHeaders(URI url) throws RestClientException {
return execute(url, HttpMethod.HEAD, null, headersExtractor());
return nonNull(execute(url, HttpMethod.HEAD, null, headersExtractor()));
}
@@ -383,21 +384,21 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
public URI postForLocation(String url, @Nullable Object request, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
return headers.getLocation();
return (headers != null ? headers.getLocation() : null);
}
@Override
public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
return headers.getLocation();
return (headers != null ? headers.getLocation() : null);
}
@Override
public URI postForLocation(URI url, @Nullable Object request) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request);
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor());
return headers.getLocation();
return (headers != null ? headers.getLocation() : null);
}
@Override
@@ -434,7 +435,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}
@Override
@@ -443,14 +444,14 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}
@Override
public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
return nonNull(execute(url, HttpMethod.POST, requestCallback, responseExtractor));
}
@@ -532,21 +533,21 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
public Set<HttpMethod> optionsForAllow(String url, Object... uriVariables) throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
HttpHeaders headers = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables);
return headers.getAllow();
return (headers != null ? headers.getAllow() : Collections.emptySet());
}
@Override
public Set<HttpMethod> optionsForAllow(String url, Map<String, ?> uriVariables) throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
HttpHeaders headers = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables);
return headers.getAllow();
return (headers != null ? headers.getAllow() : Collections.emptySet());
}
@Override
public Set<HttpMethod> optionsForAllow(URI url) throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
HttpHeaders headers = execute(url, HttpMethod.OPTIONS, null, headersExtractor);
return headers.getAllow();
return (headers != null ? headers.getAllow() : Collections.emptySet());
}
@@ -558,7 +559,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, method, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
}
@Override
@@ -567,7 +568,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, method, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
}
@Override
@@ -576,7 +577,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, method, requestCallback, responseExtractor);
return nonNull(execute(url, method, requestCallback, responseExtractor));
}
@Override
@@ -586,7 +587,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
Type type = responseType.getType();
RequestCallback requestCallback = httpEntityCallback(requestEntity, type);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);
return execute(url, method, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
}
@Override
@@ -596,7 +597,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
Type type = responseType.getType();
RequestCallback requestCallback = httpEntityCallback(requestEntity, type);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);
return execute(url, method, requestCallback, responseExtractor, uriVariables);
return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
}
@Override
@@ -606,30 +607,30 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
Type type = responseType.getType();
RequestCallback requestCallback = httpEntityCallback(requestEntity, type);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);
return execute(url, method, requestCallback, responseExtractor);
return nonNull(execute(url, method, requestCallback, responseExtractor));
}
@Override
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType)
throws RestClientException {
Assert.notNull(requestEntity, "'requestEntity' must not be null");
Assert.notNull(requestEntity, "RequestEntity must not be null");
RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(requestEntity.getUrl(), requestEntity.getMethod(), requestCallback, responseExtractor);
return nonNull(execute(requestEntity.getUrl(), requestEntity.getMethod(), requestCallback, responseExtractor));
}
@Override
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType)
throws RestClientException {
Assert.notNull(requestEntity, "'requestEntity' must not be null");
Assert.notNull(requestEntity, "RequestEntity must not be null");
Type type = responseType.getType();
RequestCallback requestCallback = httpEntityCallback(requestEntity, type);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);
return execute(requestEntity.getUrl(), requestEntity.getMethod(), requestCallback, responseExtractor);
return nonNull(execute(requestEntity.getUrl(), requestEntity.getMethod(), requestCallback, responseExtractor));
}
@@ -652,7 +653,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
}
@Override
public <T> T execute(URI url, HttpMethod method, @Nullable RequestCallback requestCallback,
public <T> T execute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
return doExecute(url, method, requestCallback, responseExtractor);
@@ -669,7 +670,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
*/
@Nullable
protected <T> T doExecute(URI url, HttpMethod method, @Nullable RequestCallback requestCallback,
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "'url' must not be null");
@@ -745,7 +746,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
* Returns a request callback implementation that writes the given object to the
* request stream.
*/
protected <T> RequestCallback httpEntityCallback(Object requestBody) {
protected <T> RequestCallback httpEntityCallback(@Nullable Object requestBody) {
return new HttpEntityRequestCallback(requestBody);
}
@@ -753,7 +754,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
* Returns a request callback implementation that writes the given object to the
* request stream.
*/
protected <T> RequestCallback httpEntityCallback(Object requestBody, Type responseType) {
protected <T> RequestCallback httpEntityCallback(@Nullable Object requestBody, Type responseType) {
return new HttpEntityRequestCallback(requestBody, responseType);
}
@@ -771,6 +772,11 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
return this.headersExtractor;
}
private static <T> T nonNull(@Nullable T result) {
Assert.state(result != null, "No result");
return result;
}
/**
* Request callback implementation that prepares the request's accept headers.
@@ -779,7 +785,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
private final Type responseType;
private AcceptHeaderRequestCallback(Type responseType) {
private AcceptHeaderRequestCallback(@Nullable Type responseType) {
this.responseType = responseType;
}
@@ -836,11 +842,11 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
private final HttpEntity<?> requestEntity;
private HttpEntityRequestCallback(Object requestBody) {
private HttpEntityRequestCallback(@Nullable Object requestBody) {
this(requestBody, null);
}
private HttpEntityRequestCallback(Object requestBody, Type responseType) {
private HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {
super(responseType);
if (requestBody instanceof HttpEntity) {
this.requestEntity = (HttpEntity<?>) requestBody;
@@ -857,7 +863,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
@SuppressWarnings("unchecked")
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
super.doWithRequest(httpRequest);
if (!this.requestEntity.hasBody()) {
Object requestBody = this.requestEntity.getBody();
if (requestBody == null) {
HttpHeaders httpHeaders = httpRequest.getHeaders();
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
if (!requestHeaders.isEmpty()) {
@@ -868,7 +875,6 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
}
}
else {
Object requestBody = this.requestEntity.getBody();
Class<?> requestBodyClass = requestBody.getClass();
Type requestBodyType = (this.requestEntity instanceof RequestEntity ?
((RequestEntity<?>)this.requestEntity).getType() : requestBodyClass);
@@ -933,7 +939,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
private final HttpMessageConverterExtractor<T> delegate;
public ResponseEntityResponseExtractor(Type responseType) {
public ResponseEntityResponseExtractor(@Nullable Type responseType) {
if (responseType != null && Void.class != responseType) {
this.delegate = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
}

View File

@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
@@ -236,7 +235,7 @@ public class ContextLoader {
* @see #customizeContext
*/
@SuppressWarnings("unchecked")
public void setContextInitializers(ApplicationContextInitializer<?>... initializers) {
public void setContextInitializers(@Nullable ApplicationContextInitializer<?>... initializers) {
if (initializers != null) {
for (ApplicationContextInitializer<?> initializer : initializers) {
this.contextInitializers.add((ApplicationContextInitializer<ConfigurableApplicationContext>) initializer);

View File

@@ -99,7 +99,6 @@ public interface WebApplicationContext extends ApplicationContext {
/**
* Return the standard Servlet API ServletContext for this application.
* <p>Also available for a Portlet application, in addition to the PortletContext.
*/
@Nullable
ServletContext getServletContext();

View File

@@ -18,6 +18,7 @@ package org.springframework.web.context.request;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.util.Assert;
/**
* Abstract {@link Scope} implementation that reads from a particular scope
@@ -42,6 +43,7 @@ public abstract class AbstractRequestAttributesScope implements Scope {
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
Assert.state(scopedObject != null, "Scoped object resolved to null");
attributes.setAttribute(name, scopedObject, getScope());
// Retrieve object again, registering it for implicit session attribute updates.
// As a bonus, we also allow for potential decoration at the getAttribute level.

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.
@@ -193,7 +193,7 @@ public class FacesRequestAttributes implements RequestAttributes {
try {
// Both HttpSession and PortletSession have a getId() method.
Method getIdMethod = session.getClass().getMethod("getId");
return ReflectionUtils.invokeMethod(getIdMethod, session).toString();
return String.valueOf(ReflectionUtils.invokeMethod(getIdMethod, session));
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Session object [" + session + "] does not have a getId() method");

View File

@@ -58,7 +58,7 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
@Override
@SuppressWarnings("unchecked")
public <T> T getNativeRequest(Class<T> requiredType) {
public <T> T getNativeRequest(@Nullable Class<T> requiredType) {
if (requiredType != null) {
Object request = getExternalContext().getRequest();
if (requiredType.isInstance(request)) {
@@ -70,7 +70,7 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
@Override
@SuppressWarnings("unchecked")
public <T> T getNativeResponse(Class<T> requiredType) {
public <T> T getNativeResponse(@Nullable Class<T> requiredType) {
if (requiredType != null) {
Object response = getExternalContext().getResponse();
if (requiredType.isInstance(response)) {

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.
@@ -31,15 +31,16 @@ import org.springframework.lang.Nullable;
public interface NativeWebRequest extends WebRequest {
/**
* Return the underlying native request object, if available.
* Return the underlying native request object.
* @see javax.servlet.http.HttpServletRequest
*/
Object getNativeRequest();
/**
* Return the underlying native response object, if available.
* Return the underlying native response object, if any.
* @see javax.servlet.http.HttpServletResponse
*/
@Nullable
Object getNativeResponse();
/**
@@ -50,7 +51,7 @@ public interface NativeWebRequest extends WebRequest {
* @see javax.servlet.http.HttpServletRequest
*/
@Nullable
<T> T getNativeRequest(Class<T> requiredType);
<T> T getNativeRequest(@Nullable Class<T> requiredType);
/**
* Return the underlying native response object, if available.
@@ -60,6 +61,6 @@ public interface NativeWebRequest extends WebRequest {
* @see javax.servlet.http.HttpServletResponse
*/
@Nullable
<T> T getNativeResponse(Class<T> requiredType);
<T> T getNativeResponse(@Nullable Class<T> requiredType);
}

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.
@@ -132,7 +132,6 @@ public interface RequestAttributes {
* Return an id for the current underlying session.
* @return the session id as String (never {@code null})
*/
@Nullable
String getSessionId();
/**
@@ -140,7 +139,6 @@ public interface RequestAttributes {
* that is, an object to synchronize on for the underlying session.
* @return the session mutex to use (never {@code null})
*/
@Nullable
Object getSessionMutex();
}

Some files were not shown because too many files have changed in this diff Show More