diff --git a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java
index 119d0a29f2..f436b3f565 100644
--- a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java
+++ b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java
@@ -233,9 +233,9 @@ public final class ContentDisposition {
result = 31 * result + ObjectUtils.nullSafeHashCode(this.filename);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.charset);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.size);
- result = 31 * result + (this.creationDate != null ? this.creationDate.hashCode() : 0);
- result = 31 * result + (this.modificationDate != null ? this.modificationDate.hashCode() : 0);
- result = 31 * result + (this.readDate != null ? this.readDate.hashCode() : 0);
+ result = 31 * result + ObjectUtils.nullSafeHashCode(this.creationDate);
+ result = 31 * result + ObjectUtils.nullSafeHashCode(this.modificationDate);
+ result = 31 * result + ObjectUtils.nullSafeHashCode(this.readDate);
return result;
}
@@ -360,7 +360,7 @@ public final class ContentDisposition {
if (idx1 != -1 && idx2 != -1) {
charset = Charset.forName(value.substring(0, idx1).trim());
Assert.isTrue(UTF_8.equals(charset) || ISO_8859_1.equals(charset),
- "Charset should be UTF-8 or ISO-8859-1");
+ "Charset must be UTF-8 or ISO-8859-1");
filename = decodeFilename(value.substring(idx2 + 1), charset);
}
else {
@@ -532,10 +532,11 @@ public final class ContentDisposition {
* @see RFC 5987
*/
private static String encodeFilename(String input, Charset charset) {
- Assert.notNull(input, "'input' is required");
- Assert.notNull(charset, "'charset' is required");
+ Assert.notNull(input, "'input' must not be null");
+ Assert.notNull(charset, "'charset' must not be null");
Assert.isTrue(!StandardCharsets.US_ASCII.equals(charset), "ASCII does not require encoding");
Assert.isTrue(UTF_8.equals(charset) || ISO_8859_1.equals(charset), "Only UTF-8 and ISO-8859-1 are supported");
+
byte[] source = input.getBytes(charset);
int len = source.length;
StringBuilder sb = new StringBuilder(len << 1);
diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/JettyHttpHandlerAdapter.java b/spring-web/src/main/java/org/springframework/http/server/reactive/JettyHttpHandlerAdapter.java
index 89a3150683..041f8fd383 100644
--- a/spring-web/src/main/java/org/springframework/http/server/reactive/JettyHttpHandlerAdapter.java
+++ b/spring-web/src/main/java/org/springframework/http/server/reactive/JettyHttpHandlerAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,12 +65,12 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context)
throws IOException, URISyntaxException {
- // TODO: need to compile against Jetty 10 to use HttpFields (class->interface)
if (jetty10Present) {
+ // No HttpFields optimization on Jetty 10 due to binary incompatibility
return super.createRequest(request, context);
}
- Assert.notNull(getServletPath(), "Servlet path is not initialized");
+ Assert.state(getServletPath() != null, "Servlet path is not initialized");
return new JettyServerHttpRequest(
request, context, getServletPath(), getDataBufferFactory(), getBufferSize());
}
@@ -79,15 +79,14 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
protected ServletServerHttpResponse createResponse(HttpServletResponse response,
AsyncContext context, ServletServerHttpRequest request) throws IOException {
- // TODO: need to compile against Jetty 10 to use HttpFields (class->interface)
if (jetty10Present) {
+ // No HttpFields optimization on Jetty 10 due to binary incompatibility
return new BaseJettyServerHttpResponse(
response, context, getDataBufferFactory(), getBufferSize(), request);
}
- else {
- return new JettyServerHttpResponse(
- response, context, getDataBufferFactory(), getBufferSize(), request);
- }
+
+ return new JettyServerHttpResponse(
+ response, context, getDataBufferFactory(), getBufferSize(), request);
}
@@ -120,8 +119,6 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
"] to org.eclipse.jetty.server.Request");
}
}
-
-
}
diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ServletHttpHandlerAdapter.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ServletHttpHandlerAdapter.java
index c38837c7ed..0cedc4dd1b 100644
--- a/spring-web/src/main/java/org/springframework/http/server/reactive/ServletHttpHandlerAdapter.java
+++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ServletHttpHandlerAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -170,7 +170,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
AsyncListener requestListener;
String logPrefix;
try {
- httpRequest = createRequest(((HttpServletRequest) request), asyncContext);
+ httpRequest = createRequest((HttpServletRequest) request, asyncContext);
requestListener = httpRequest.getAsyncListener();
logPrefix = httpRequest.getLogPrefix();
}
@@ -183,8 +183,10 @@ public class ServletHttpHandlerAdapter implements Servlet {
return;
}
- ServerHttpResponse httpResponse = createResponse(((HttpServletResponse) response), asyncContext, httpRequest);
- AsyncListener responseListener = ((ServletServerHttpResponse) httpResponse).getAsyncListener();
+ ServletServerHttpResponse wrappedResponse =
+ createResponse((HttpServletResponse) response, asyncContext, httpRequest);
+ ServerHttpResponse httpResponse = wrappedResponse;
+ AsyncListener responseListener = wrappedResponse.getAsyncListener();
if (httpRequest.getMethod() == HttpMethod.HEAD) {
httpResponse = new HttpHeadResponseDecorator(httpResponse);
}
@@ -201,7 +203,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context)
throws IOException, URISyntaxException {
- Assert.notNull(this.servletPath, "Servlet path is not initialized");
+ Assert.state(this.servletPath != null, "Servlet path is not initialized");
return new ServletServerHttpRequest(
request, context, this.servletPath, getDataBufferFactory(), getBufferSize());
}
@@ -264,9 +266,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
private final String logPrefix;
-
- public HttpHandlerAsyncListener(
- AsyncListener requestAsyncListener, AsyncListener responseAsyncListener,
+ public HttpHandlerAsyncListener(AsyncListener requestAsyncListener, AsyncListener responseAsyncListener,
Runnable handlerDisposeTask, AtomicBoolean completionFlag, String logPrefix) {
this.requestAsyncListener = requestAsyncListener;
@@ -276,7 +276,6 @@ public class ServletHttpHandlerAdapter implements Servlet {
this.logPrefix = logPrefix;
}
-
@Override
public void onTimeout(AsyncEvent event) {
// Should never happen since we call asyncContext.setTimeout(-1)
@@ -362,9 +361,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
@Nullable
private volatile Subscription subscription;
- public HandlerResultSubscriber(
- AsyncContext asyncContext, AtomicBoolean completionFlag, String logPrefix) {
-
+ public HandlerResultSubscriber(AsyncContext asyncContext, AtomicBoolean completionFlag, String logPrefix) {
this.asyncContext = asyncContext;
this.completionFlag = completionFlag;
this.logPrefix = logPrefix;
diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/TomcatHttpHandlerAdapter.java b/spring-web/src/main/java/org/springframework/http/server/reactive/TomcatHttpHandlerAdapter.java
index b8c78fdbf4..ed67bc57ac 100644
--- a/spring-web/src/main/java/org/springframework/http/server/reactive/TomcatHttpHandlerAdapter.java
+++ b/spring-web/src/main/java/org/springframework/http/server/reactive/TomcatHttpHandlerAdapter.java
@@ -58,7 +58,6 @@ import org.springframework.util.ReflectionUtils;
*/
public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
-
public TomcatHttpHandlerAdapter(HttpHandler httpHandler) {
super(httpHandler);
}
@@ -68,7 +67,7 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext asyncContext)
throws IOException, URISyntaxException {
- Assert.notNull(getServletPath(), "Servlet path is not initialized");
+ Assert.state(getServletPath() != null, "Servlet path is not initialized");
return new TomcatServerHttpRequest(
request, asyncContext, getServletPath(), getDataBufferFactory(), getBufferSize());
}
diff --git a/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java b/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java
index 690eda7f55..af8cf0aee7 100644
--- a/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java
+++ b/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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,20 +25,22 @@ import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.springframework.http.ContentDisposition.parse;
/**
- * Unit tests for {@link ContentDisposition}
+ * Unit tests for {@link ContentDisposition}.
+ *
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
*/
class ContentDispositionTests {
- private static DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
+ private static final DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
- @Test
@SuppressWarnings("deprecation")
- void parse() {
+ @Test
+ void parseFilenameQuoted() {
assertThat(parse("form-data; name=\"foo\"; filename=\"foo.txt\"; size=123"))
.isEqualTo(ContentDisposition.formData()
.name("foo")
@@ -72,7 +74,7 @@ class ContentDispositionTests {
.build());
}
- @Test // gh-24112
+ @Test // gh-24112
void parseEncodedFilenameWithPaddedCharset() {
assertThat(parse("attachment; filename*= UTF-8''some-file.zip"))
.isEqualTo(ContentDisposition.attachment()
@@ -80,13 +82,13 @@ class ContentDispositionTests {
.build());
}
- @Test // gh-26463
+ @Test // gh-26463
void parseBase64EncodedFilename() {
String input = "attachment; filename=\"=?UTF-8?B?5pel5pys6KqeLmNzdg==?=\"";
assertThat(parse(input).getFilename()).isEqualTo("日本語.csv");
}
- @Test // gh-26463
+ @Test // gh-26463
void parseBase64EncodedShiftJISFilename() {
String input = "attachment; filename=\"=?SHIFT_JIS?B?k/qWe4zqLmNzdg==?=\"";
assertThat(parse(input).getFilename()).isEqualTo("日本語.csv");
@@ -116,7 +118,7 @@ class ContentDispositionTests {
.isThrownBy(() -> parse("form-data; name=\"name\"; filename*=UTF-8''%A.txt"));
}
- @Test // gh-23077
+ @Test // gh-23077
@SuppressWarnings("deprecation")
void parseWithEscapedQuote() {
BiConsumer tester = (description, filename) ->
@@ -137,8 +139,8 @@ class ContentDispositionTests {
"The Twilight Zone \\\\\\\\");
}
- @Test
@SuppressWarnings("deprecation")
+ @Test
void parseWithExtraSemicolons() {
assertThat(parse("form-data; name=\"foo\";; ; filename=\"foo.txt\"; size=123"))
.isEqualTo(ContentDisposition.formData()
@@ -148,8 +150,8 @@ class ContentDispositionTests {
.build());
}
- @Test
@SuppressWarnings("deprecation")
+ @Test
void parseDates() {
ZonedDateTime creationTime = ZonedDateTime.parse("Mon, 12 Feb 2007 10:15:30 -0500", formatter);
ZonedDateTime modificationTime = ZonedDateTime.parse("Tue, 13 Feb 2007 10:15:30 -0500", formatter);
@@ -167,8 +169,8 @@ class ContentDispositionTests {
.build());
}
- @Test
@SuppressWarnings("deprecation")
+ @Test
void parseIgnoresInvalidDates() {
ZonedDateTime readTime = ZonedDateTime.parse("Wed, 14 Feb 2007 10:15:30 -0500", formatter);
@@ -197,13 +199,8 @@ class ContentDispositionTests {
assertThatIllegalArgumentException().isThrownBy(() -> parse("foo;bar"));
}
- private static ContentDisposition parse(String input) {
- return ContentDisposition.parse(input);
- }
-
-
- @Test
@SuppressWarnings("deprecation")
+ @Test
void format() {
assertThat(
ContentDisposition.formData()
@@ -235,14 +232,11 @@ class ContentDispositionTests {
.isEqualTo("form-data; name=\"name\"; filename=\"test.txt\"");
}
- @Test // gh-24220
+ @Test // gh-24220
void formatWithFilenameWithQuotes() {
-
BiConsumer tester = (input, output) -> {
-
assertThat(ContentDisposition.formData().filename(input).build().toString())
.isEqualTo("form-data; filename=\"" + output + "\"");
-
assertThat(ContentDisposition.formData().filename(input, StandardCharsets.US_ASCII).build().toString())
.isEqualTo("form-data; filename=\"" + output + "\"");
};