Skip to content

Commit 67d2b25

Browse files
committed
Revert "WIP"
This reverts commit c09b0f57631905a7b9cca32be5516853e4263ac0.
1 parent 1486102 commit 67d2b25

File tree

5 files changed

+40
-111
lines changed

5 files changed

+40
-111
lines changed

spring-test/src/main/java/org/springframework/test/web/client/match/ContentRequestMatchers.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,12 @@ public RequestMatcher formDataContains(Map<String, String> expected) {
174174
return formData(multiValueMap, false);
175175
}
176176

177-
@SuppressWarnings("unchecked")
178177
private RequestMatcher formData(MultiValueMap<String, String> expectedMap, boolean containsExactly) {
179178
return request -> {
180179
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
181180
MockHttpInputMessage message = new MockHttpInputMessage(mockRequest.getBodyAsBytes());
182181
message.getHeaders().putAll(mockRequest.getHeaders());
183-
MultiValueMap<String, String> actualMap = (MultiValueMap<String, String>) new FormHttpMessageConverter().read(null, message);
182+
MultiValueMap<String, String> actualMap = new FormHttpMessageConverter().read(null, message);
184183
if (containsExactly) {
185184
assertEquals("Form data", expectedMap, actualMap);
186185
}

spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,6 @@ public HttpHeaders getHeaders() {
899899
}
900900
}
901901

902-
@SuppressWarnings("unchecked")
903902
private MultiValueMap<String, String> parseFormData(MediaType mediaType) {
904903
HttpInputMessage message = new HttpInputMessage() {
905904
@Override
@@ -915,7 +914,7 @@ public HttpHeaders getHeaders() {
915914
};
916915

917916
try {
918-
return (MultiValueMap<String, String>) new FormHttpMessageConverter().read(null, message);
917+
return new FormHttpMessageConverter().read(null, message);
919918
}
920919
catch (IOException ex) {
921920
throw new IllegalStateException("Failed to parse form data in request body", ex);

spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java

+34-86
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
* @see org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
153153
* @see org.springframework.util.MultiValueMap
154154
*/
155-
public class FormHttpMessageConverter implements HttpMessageConverter<Map<String, ?>> {
155+
public class FormHttpMessageConverter implements HttpMessageConverter<MultiValueMap<String, ?>> {
156156

157157
/** The default charset used by the converter. */
158158
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
@@ -295,7 +295,7 @@ public void setMultipartCharset(Charset charset) {
295295

296296
@Override
297297
public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
298-
if (!Map.class.isAssignableFrom(clazz)) {
298+
if (!MultiValueMap.class.isAssignableFrom(clazz)) {
299299
return false;
300300
}
301301
if (mediaType == null) {
@@ -330,7 +330,7 @@ public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
330330
}
331331

332332
@Override
333-
public Map<String, ?> read(@Nullable Class<? extends Map<String, ?>> clazz,
333+
public MultiValueMap<String, String> read(@Nullable Class<? extends MultiValueMap<String, ?>> clazz,
334334
HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
335335

336336
MediaType contentType = inputMessage.getHeaders().getContentType();
@@ -339,76 +339,41 @@ public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
339339
String body = StreamUtils.copyToString(inputMessage.getBody(), charset);
340340

341341
String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
342-
Map<String, String> svResult = null;
343-
MultiValueMap<String, String> mvResult = null;
344-
if (clazz == null || MultiValueMap.class.isAssignableFrom(clazz)) {
345-
mvResult = new LinkedMultiValueMap<>(pairs.length);
346-
}
347-
else {
348-
svResult = CollectionUtils.newLinkedHashMap(pairs.length);
349-
}
342+
MultiValueMap<String, String> result = new LinkedMultiValueMap<>(pairs.length);
350343
for (String pair : pairs) {
351344
int idx = pair.indexOf('=');
352345
if (idx == -1) {
353-
String name = URLDecoder.decode(pair, charset);
354-
if (mvResult != null) {
355-
mvResult.add(name, null);
356-
}
357-
else if (svResult != null) {
358-
svResult.put(name, null);
359-
}
346+
result.add(URLDecoder.decode(pair, charset), null);
360347
}
361348
else {
362349
String name = URLDecoder.decode(pair.substring(0, idx), charset);
363350
String value = URLDecoder.decode(pair.substring(idx + 1), charset);
364-
if (mvResult != null) {
365-
mvResult.add(name, value);
366-
}
367-
else if (svResult != null) {
368-
svResult.put(name, value);
369-
}
351+
result.add(name, value);
370352
}
371353
}
372-
if (mvResult != null) {
373-
return mvResult;
374-
}
375-
else if (svResult != null) {
376-
return svResult;
377-
}
378-
else {
379-
throw new IllegalStateException();
380-
}
354+
return result;
381355
}
382356

383357
@Override
384358
@SuppressWarnings("unchecked")
385-
public void write(Map<String, ?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
359+
public void write(MultiValueMap<String, ?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
386360
throws IOException, HttpMessageNotWritableException {
387361

388362
if (isMultipart(map, contentType)) {
389-
writeMultipart((Map<String, Object>) map, contentType, outputMessage);
363+
writeMultipart((MultiValueMap<String, Object>) map, contentType, outputMessage);
390364
}
391365
else {
392-
writeForm((Map<String, Object>) map, contentType, outputMessage);
366+
writeForm((MultiValueMap<String, Object>) map, contentType, outputMessage);
393367
}
394368
}
395369

396370

397-
private boolean isMultipart(Map<String, ?> map, @Nullable MediaType contentType) {
371+
private boolean isMultipart(MultiValueMap<String, ?> map, @Nullable MediaType contentType) {
398372
if (contentType != null) {
399373
return contentType.getType().equalsIgnoreCase("multipart");
400374
}
401-
if (map instanceof MultiValueMap<?, ?> mvMap) {
402-
for (List<?> values : mvMap.values()) {
403-
for (Object value : values) {
404-
if (value != null && !(value instanceof String)) {
405-
return true;
406-
}
407-
}
408-
}
409-
}
410-
else {
411-
for (Object value : map.values()) {
375+
for (List<?> values : map.values()) {
376+
for (Object value : values) {
412377
if (value != null && !(value instanceof String)) {
413378
return true;
414379
}
@@ -417,7 +382,7 @@ private boolean isMultipart(Map<String, ?> map, @Nullable MediaType contentType)
417382
return false;
418383
}
419384

420-
private void writeForm(Map<String, Object> formData, @Nullable MediaType mediaType,
385+
private void writeForm(MultiValueMap<String, Object> formData, @Nullable MediaType mediaType,
421386
HttpOutputMessage outputMessage) throws IOException {
422387

423388
mediaType = getFormContentType(mediaType);
@@ -465,37 +430,30 @@ protected MediaType getFormContentType(@Nullable MediaType contentType) {
465430
return contentType;
466431
}
467432

468-
protected String serializeForm(Map<String, Object> formData, Charset charset) {
433+
protected String serializeForm(MultiValueMap<String, Object> formData, Charset charset) {
469434
StringBuilder builder = new StringBuilder();
470-
formData.forEach((name, value) -> {
435+
formData.forEach((name, values) -> {
471436
if (name == null) {
472-
Assert.isTrue(value == null || value instanceof List<?> values && values.isEmpty(),
473-
() -> "Null name in form data: " + formData);
437+
Assert.isTrue(CollectionUtils.isEmpty(values), () -> "Null name in form data: " + formData);
474438
return;
475439
}
476-
if (value instanceof List<?> values) {
477-
values.forEach(v -> serializeFormValue(name, value, charset, builder));
478-
}
479-
else {
480-
serializeFormValue(name, value, charset, builder);
481-
}
440+
values.forEach(value -> {
441+
if (builder.length() != 0) {
442+
builder.append('&');
443+
}
444+
builder.append(URLEncoder.encode(name, charset));
445+
if (value != null) {
446+
builder.append('=');
447+
builder.append(URLEncoder.encode(String.valueOf(value), charset));
448+
}
449+
});
482450
});
483-
return builder.toString();
484-
}
485451

486-
private static void serializeFormValue(String name, @Nullable Object value, Charset charset, StringBuilder builder) {
487-
if (!builder.isEmpty()) {
488-
builder.append('&');
489-
}
490-
builder.append(URLEncoder.encode(name, charset));
491-
if (value != null) {
492-
builder.append('=');
493-
builder.append(URLEncoder.encode(String.valueOf(value), charset));
494-
}
452+
return builder.toString();
495453
}
496454

497455
private void writeMultipart(
498-
Map<String, Object> parts, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
456+
MultiValueMap<String, Object> parts, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
499457
throws IOException {
500458

501459
// If the supplied content type is null, fall back to multipart/form-data.
@@ -542,23 +500,13 @@ private boolean isFilenameCharsetSet() {
542500
return (this.multipartCharset != null);
543501
}
544502

545-
private void writeParts(OutputStream os, Map<String, Object> parts, byte[] boundary) throws IOException {
546-
for (Map.Entry<String, Object> entry : parts.entrySet()) {
503+
private void writeParts(OutputStream os, MultiValueMap<String, Object> parts, byte[] boundary) throws IOException {
504+
for (Map.Entry<String, List<Object>> entry : parts.entrySet()) {
547505
String name = entry.getKey();
548-
Object value = entry.getValue();
549-
if (value instanceof List<?> values) {
550-
for (Object part : values) {
551-
if (part != null) {
552-
writeBoundary(os, boundary);
553-
writePart(name, getHttpEntity(part), os);
554-
writeNewLine(os);
555-
}
556-
}
557-
}
558-
else {
559-
if (value != null) {
506+
for (Object part : entry.getValue()) {
507+
if (part != null) {
560508
writeBoundary(os, boundary);
561-
writePart(name, getHttpEntity(value), os);
509+
writePart(name, getHttpEntity(part), os);
562510
writeNewLine(os);
563511
}
564512
}

spring-web/src/main/java/org/springframework/web/filter/FormContentFilter.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -94,7 +94,6 @@ protected void doFilterInternal(
9494
}
9595
}
9696

97-
@SuppressWarnings("unchecked")
9897
@Nullable
9998
private MultiValueMap<String, String> parseIfNecessary(HttpServletRequest request) throws IOException {
10099
if (!shouldParse(request)) {
@@ -107,7 +106,7 @@ public InputStream getBody() throws IOException {
107106
return request.getInputStream();
108107
}
109108
};
110-
return (MultiValueMap<String, String>) this.formConverter.read(null, inputMessage);
109+
return this.formConverter.read(null, inputMessage);
111110
}
112111

113112
private boolean shouldParse(HttpServletRequest request) {

spring-web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java

+2-18
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,13 @@ void addSupportedMediaTypes() {
117117
assertCanWrite(MULTIPART_RELATED);
118118
}
119119

120-
@SuppressWarnings("unchecked")
121120
@Test
122-
void readMultiValueForm() throws Exception {
121+
void readForm() throws Exception {
123122
String body = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3";
124123
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.ISO_8859_1));
125124
inputMessage.getHeaders().setContentType(
126125
new MediaType("application", "x-www-form-urlencoded", StandardCharsets.ISO_8859_1));
127-
MultiValueMap<String, String> result = (MultiValueMap<String, String>) this.converter.read(null, inputMessage);
126+
MultiValueMap<String, String> result = this.converter.read(null, inputMessage);
128127

129128
assertThat(result).as("Invalid result").hasSize(3);
130129
assertThat(result.getFirst("name 1")).as("Invalid result").isEqualTo("value 1");
@@ -133,21 +132,6 @@ void readMultiValueForm() throws Exception {
133132
assertThat(result.getFirst("name 3")).as("Invalid result").isNull();
134133
}
135134

136-
@SuppressWarnings("unchecked")
137-
@Test
138-
void readSingleValueForm() throws Exception {
139-
String body = "name+1=value+1&name+2=value+2&name+3";
140-
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.ISO_8859_1));
141-
inputMessage.getHeaders().setContentType(
142-
new MediaType("application", "x-www-form-urlencoded", StandardCharsets.ISO_8859_1));
143-
Map<String, String> result = (Map<String, String>) this.converter.read((Class<? extends Map<String, ?>>) Map.class, inputMessage);
144-
145-
assertThat(result).as("Invalid result").hasSize(3);
146-
assertThat(result.get("name 1")).as("Invalid result").isEqualTo("value 1");
147-
assertThat(result.get("name 2")).as("Invalid result").isEqualTo("value 2");
148-
assertThat(result.get("name 3")).as("Invalid result").isNull();
149-
}
150-
151135
@Test
152136
void writeForm() throws IOException {
153137
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();

0 commit comments

Comments
 (0)