Nullability fine-tuning and related polishing

Issue: SPR-17250
This commit is contained in:
Juergen Hoeller 2018-10-14 23:29:46 +02:00
parent 5f2d47a17e
commit 58b3af9475
7 changed files with 77 additions and 59 deletions

View File

@ -31,7 +31,7 @@ import org.springframework.util.MultiValueMap;
* {@code HttpHeaders} object that can only be read, not written to.
*
* @author Brian Clozel
* @since 5.1
* @since 5.1.1
*/
class ReadOnlyHttpHeaders extends HttpHeaders {
@ -59,10 +59,7 @@ class ReadOnlyHttpHeaders extends HttpHeaders {
@Override
public List<String> get(Object key) {
List<String> values = this.headers.get(key);
if (values != null) {
return Collections.unmodifiableList(values);
}
return values;
return (values != null ? Collections.unmodifiableList(values) : null);
}
@Override

View File

@ -36,16 +36,18 @@ import org.springframework.util.MultiValueMap;
* {@code MultiValueMap} implementation for wrapping Jetty HTTP headers.
*
* @author Brian Clozel
* @since 5.1
* @since 5.1.1
*/
class JettyHeadersAdapter implements MultiValueMap<String, String> {
private final HttpFields headers;
JettyHeadersAdapter(HttpFields headers) {
this.headers = headers;
}
@Override
public String getFirst(String key) {
return this.headers.get(key);
@ -95,24 +97,18 @@ class JettyHeadersAdapter implements MultiValueMap<String, String> {
@Override
public boolean isEmpty() {
return this.headers.size() == 0;
return (this.headers.size() == 0);
}
@Override
public boolean containsKey(Object key) {
if (key instanceof String) {
return this.headers.containsKey((String) key);
}
return false;
return (key instanceof String && this.headers.containsKey((String) key));
}
@Override
public boolean containsValue(Object value) {
if (value instanceof String) {
return this.headers.stream()
.anyMatch(field -> field.contains((String) value));
}
return false;
return (value instanceof String &&
this.headers.stream().anyMatch(field -> field.contains((String) value)));
}
@Nullable
@ -144,8 +140,8 @@ class JettyHeadersAdapter implements MultiValueMap<String, String> {
}
@Override
public void putAll(Map<? extends String, ? extends List<String>> m) {
m.forEach(this::put);
public void putAll(Map<? extends String, ? extends List<String>> map) {
map.forEach(this::put);
}
@Override
@ -179,6 +175,7 @@ class JettyHeadersAdapter implements MultiValueMap<String, String> {
};
}
private class EntryIterator implements Iterator<Entry<String, List<String>>> {
private Enumeration<String> names = headers.getFieldNames();
@ -194,6 +191,7 @@ class JettyHeadersAdapter implements MultiValueMap<String, String> {
}
}
private class HeaderEntry implements Entry<String, List<String>> {
private final String key;
@ -204,7 +202,7 @@ class JettyHeadersAdapter implements MultiValueMap<String, String> {
@Override
public String getKey() {
return this.key.toString();
return this.key;
}
@Override
@ -219,4 +217,5 @@ class JettyHeadersAdapter implements MultiValueMap<String, String> {
return previousValues;
}
}
}

View File

@ -34,12 +34,14 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
/**
* {@link ServletHttpHandlerAdapter} extension that uses Jetty APIs for writing
* to the response with {@link ByteBuffer}.
*
* @author Violeta Georgieva
* @author Brian Clozel
* @since 5.0
* @see org.springframework.web.server.adapter.AbstractReactiveWebInitializer
*/
@ -53,6 +55,8 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
@Override
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context)
throws IOException, URISyntaxException {
Assert.notNull(getServletPath(), "Servlet path is not initialized");
return new JettyServerHttpRequest(request, context, getServletPath(), getDataBufferFactory(), getBufferSize());
}
@ -64,6 +68,7 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
response, context, getDataBufferFactory(), getBufferSize(), request);
}
private static final class JettyServerHttpRequest extends ServletServerHttpRequest {
JettyServerHttpRequest(HttpServletRequest request, AsyncContext asyncContext,

View File

@ -34,16 +34,18 @@ import org.springframework.util.MultiValueMap;
* {@code MultiValueMap} implementation for wrapping Netty HTTP headers.
*
* @author Brian Clozel
* @since 5.1
* @since 5.1.1
*/
class NettyHeadersAdapter implements MultiValueMap<String, String> {
private final HttpHeaders headers;
NettyHeadersAdapter(HttpHeaders headers) {
this.headers = headers;
}
@Override
@Nullable
public String getFirst(String key) {
@ -99,14 +101,14 @@ class NettyHeadersAdapter implements MultiValueMap<String, String> {
@Override
public boolean containsKey(Object key) {
return (key instanceof String) && this.headers.contains((String) key);
return (key instanceof String && this.headers.contains((String) key));
}
@Override
public boolean containsValue(Object value) {
return (value instanceof String) &&
return (value instanceof String &&
this.headers.entries().stream()
.anyMatch(entry -> value != null && value.equals(entry.getValue()));
.anyMatch(entry -> value.equals(entry.getValue())));
}
@Override
@ -138,8 +140,8 @@ class NettyHeadersAdapter implements MultiValueMap<String, String> {
}
@Override
public void putAll(Map<? extends String, ? extends List<String>> m) {
m.forEach(this.headers::add);
public void putAll(Map<? extends String, ? extends List<String>> map) {
map.forEach(this.headers::add);
}
@Override
@ -173,6 +175,7 @@ class NettyHeadersAdapter implements MultiValueMap<String, String> {
};
}
private class EntryIterator implements Iterator<Entry<String, List<String>>> {
private Iterator<String> names = headers.names().iterator();
@ -188,6 +191,7 @@ class NettyHeadersAdapter implements MultiValueMap<String, String> {
}
}
private class HeaderEntry implements Entry<String, List<String>> {
private final String key;

View File

@ -38,23 +38,25 @@ import org.springframework.util.MultiValueMap;
* {@code MultiValueMap} implementation for wrapping Tomcat HTTP headers.
*
* @author Brian Clozel
* @since 5.1
* @since 5.1.1
*/
class TomcatHeadersAdapter implements MultiValueMap<String, String> {
private final MimeHeaders headers;
TomcatHeadersAdapter(MimeHeaders headers) {
this.headers = headers;
}
@Override
public String getFirst(String key) {
return this.headers.getHeader(key);
}
@Override
public void add(String key, String value) {
public void add(String key, @Nullable String value) {
this.headers.addValue(key).setString(value);
}
@ -69,7 +71,7 @@ class TomcatHeadersAdapter implements MultiValueMap<String, String> {
}
@Override
public void set(String key, String value) {
public void set(String key, @Nullable String value) {
this.headers.setValue(key).setString(value);
}
@ -98,13 +100,13 @@ class TomcatHeadersAdapter implements MultiValueMap<String, String> {
@Override
public boolean isEmpty() {
return this.headers.size() == 0;
return (this.headers.size() == 0);
}
@Override
public boolean containsKey(Object key) {
if (key instanceof String) {
return this.headers.findHeader((String) key, 0) != -1;
return (this.headers.findHeader((String) key, 0) != -1);
}
return false;
}
@ -152,8 +154,8 @@ class TomcatHeadersAdapter implements MultiValueMap<String, String> {
}
@Override
public void putAll(Map<? extends String, ? extends List<String>> m) {
m.forEach(this::put);
public void putAll(Map<? extends String, ? extends List<String>> map) {
map.forEach(this::put);
}
@Override
@ -191,6 +193,7 @@ class TomcatHeadersAdapter implements MultiValueMap<String, String> {
};
}
private class EntryIterator implements Iterator<Entry<String, List<String>>> {
private Enumeration<String> names = headers.names();
@ -206,11 +209,12 @@ class TomcatHeadersAdapter implements MultiValueMap<String, String> {
}
}
private final class HeaderEntry implements Entry<String, List<String>> {
private final String key;
private HeaderEntry(String key) {
HeaderEntry(String key) {
this.key = key;
}
@ -234,4 +238,5 @@ class TomcatHeadersAdapter implements MultiValueMap<String, String> {
return previous;
}
}
}

View File

@ -48,7 +48,6 @@ import org.springframework.util.ReflectionUtils;
*
* @author Violeta Georgieva
* @author Brian Clozel
* @author Brian Clozel
* @since 5.0
* @see org.springframework.web.server.adapter.AbstractReactiveWebInitializer
*/
@ -64,7 +63,7 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext asyncContext)
throws IOException, URISyntaxException {
Assert.notNull(getServletPath(), "servletPath is not initialized.");
Assert.notNull(getServletPath(), "Servlet path is not initialized");
return new TomcatServerHttpRequest(
request, asyncContext, getServletPath(), getDataBufferFactory(), getBufferSize());
}
@ -77,16 +76,20 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
response, asyncContext, getDataBufferFactory(), getBufferSize(), request);
}
private static final class TomcatServerHttpRequest extends ServletServerHttpRequest {
private static final Field COYOTE_REQUEST_FIELD = ReflectionUtils.findField(RequestFacade.class, "request");
private static final Field COYOTE_REQUEST_FIELD;
private final int bufferSize;
private final DataBufferFactory factory;
static {
ReflectionUtils.makeAccessible(COYOTE_REQUEST_FIELD);
Field field = ReflectionUtils.findField(RequestFacade.class, "request");
Assert.state(field != null, "Incompatible Tomcat implementation");
ReflectionUtils.makeAccessible(field);
COYOTE_REQUEST_FIELD = field;
}
TomcatServerHttpRequest(HttpServletRequest request, AsyncContext context,
@ -99,8 +102,10 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
}
private static HttpHeaders createTomcatHttpHeaders(HttpServletRequest request) {
Request tomcatRequest = ((org.apache.catalina.connector.Request) ReflectionUtils
.getField(COYOTE_REQUEST_FIELD, request)).getCoyoteRequest();
org.apache.catalina.connector.Request connectorRequest = (org.apache.catalina.connector.Request)
ReflectionUtils.getField(COYOTE_REQUEST_FIELD, request);
Assert.state(connectorRequest != null, "No Tomcat connector request");
Request tomcatRequest = connectorRequest.getCoyoteRequest();
TomcatHeadersAdapter headers = new TomcatHeadersAdapter(tomcatRequest.getMimeHeaders());
return new HttpHeaders(headers);
}
@ -112,11 +117,9 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
DataBuffer dataBuffer = this.factory.allocateBuffer(capacity);
try {
ByteBuffer byteBuffer = dataBuffer.asByteBuffer(0, capacity);
ServletRequest request = getNativeRequest();
int read = ((CoyoteInputStream) request.getInputStream()).read(byteBuffer);
logBytesRead(read);
if (read > 0) {
dataBuffer.writePosition(read);
release = false;
@ -140,10 +143,13 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
private static final class TomcatServerHttpResponse extends ServletServerHttpResponse {
private static final Field COYOTE_RESPONSE_FIELD = ReflectionUtils.findField(ResponseFacade.class, "response");
private static final Field COYOTE_RESPONSE_FIELD;
static {
ReflectionUtils.makeAccessible(COYOTE_RESPONSE_FIELD);
Field field = ReflectionUtils.findField(ResponseFacade.class, "response");
Assert.state(field != null, "Incompatible Tomcat implementation");
ReflectionUtils.makeAccessible(field);
COYOTE_RESPONSE_FIELD = field;
}
TomcatServerHttpResponse(HttpServletResponse response, AsyncContext context,
@ -153,8 +159,10 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
}
private static HttpHeaders createTomcatHttpHeaders(HttpServletResponse response) {
Response tomcatResponse = ((org.apache.catalina.connector.Response) ReflectionUtils
.getField(COYOTE_RESPONSE_FIELD, response)).getCoyoteResponse();
org.apache.catalina.connector.Response connectorResponse = (org.apache.catalina.connector.Response)
ReflectionUtils.getField(COYOTE_RESPONSE_FIELD, response);
Assert.state(connectorResponse != null, "No Tomcat connector response");
Response tomcatResponse = connectorResponse.getCoyoteResponse();
TomcatHeadersAdapter headers = new TomcatHeadersAdapter(tomcatResponse.getMimeHeaders());
return new HttpHeaders(headers);
}

View File

@ -36,16 +36,18 @@ import org.springframework.util.MultiValueMap;
* {@code MultiValueMap} implementation for wrapping Undertow HTTP headers.
*
* @author Brian Clozel
* @since 5.1
* @since 5.1.1
*/
class UndertowHeadersAdapter implements MultiValueMap<String, String> {
private final HeaderMap headers;
UndertowHeadersAdapter(HeaderMap headers) {
this.headers = headers;
}
@Override
public String getFirst(String key) {
return this.headers.getFirst(key);
@ -92,25 +94,20 @@ class UndertowHeadersAdapter implements MultiValueMap<String, String> {
@Override
public boolean isEmpty() {
return this.headers.size() == 0;
return (this.headers.size() == 0);
}
@Override
public boolean containsKey(Object key) {
if (key instanceof String) {
return this.headers.contains((String) key);
}
return false;
return (key instanceof String && this.headers.contains((String) key));
}
@Override
public boolean containsValue(Object value) {
if (value instanceof String) {
return this.headers.getHeaderNames().stream()
.map(this.headers::get)
.anyMatch(values -> values.contains(value));
}
return false;
return (value instanceof String &&
this.headers.getHeaderNames().stream()
.map(this.headers::get)
.anyMatch(values -> values.contains(value)));
}
@Override
@ -140,8 +137,8 @@ class UndertowHeadersAdapter implements MultiValueMap<String, String> {
}
@Override
public void putAll(Map<? extends String, ? extends List<String>> m) {
m.forEach((key, values) ->
public void putAll(Map<? extends String, ? extends List<String>> map) {
map.forEach((key, values) ->
this.headers.putAll(HttpString.tryFromString(key), values));
}
@ -179,6 +176,7 @@ class UndertowHeadersAdapter implements MultiValueMap<String, String> {
};
}
private class EntryIterator implements Iterator<Entry<String, List<String>>> {
private Iterator<HttpString> names = headers.getHeaderNames().iterator();
@ -194,6 +192,7 @@ class UndertowHeadersAdapter implements MultiValueMap<String, String> {
}
}
private class HeaderEntry implements Entry<String, List<String>> {
private final HttpString key;
@ -219,4 +218,5 @@ class UndertowHeadersAdapter implements MultiValueMap<String, String> {
return previousValues;
}
}
}