Skip to content

Commit e238c8a

Browse files
committed
Declare resolvedCharset as transient (restoring serializability)
Closes gh-26127
1 parent 9e99fd5 commit e238c8a

File tree

4 files changed

+54
-24
lines changed

4 files changed

+54
-24
lines changed

spring-core/src/main/java/org/springframework/util/MimeType.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.util;
1818

19+
import java.io.IOException;
20+
import java.io.ObjectInputStream;
1921
import java.io.Serializable;
2022
import java.nio.charset.Charset;
2123
import java.util.BitSet;
@@ -104,7 +106,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
104106
private final Map<String, String> parameters;
105107

106108
@Nullable
107-
private Charset resolvedCharset;
109+
private transient Charset resolvedCharset;
108110

109111
@Nullable
110112
private volatile String toStringValue;
@@ -184,9 +186,9 @@ public MimeType(String type, String subtype, @Nullable Map<String, String> param
184186
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
185187
if (!CollectionUtils.isEmpty(parameters)) {
186188
Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
187-
parameters.forEach((attribute, value) -> {
188-
checkParameters(attribute, value);
189-
map.put(attribute, value);
189+
parameters.forEach((parameter, value) -> {
190+
checkParameters(parameter, value);
191+
map.put(parameter, value);
190192
});
191193
this.parameters = Collections.unmodifiableMap(map);
192194
}
@@ -210,11 +212,11 @@ private void checkToken(String token) {
210212
}
211213
}
212214

213-
protected void checkParameters(String attribute, String value) {
214-
Assert.hasLength(attribute, "'attribute' must not be empty");
215+
protected void checkParameters(String parameter, String value) {
216+
Assert.hasLength(parameter, "'parameter' must not be empty");
215217
Assert.hasLength(value, "'value' must not be empty");
216-
checkToken(attribute);
217-
if (PARAM_CHARSET.equals(attribute)) {
218+
checkToken(parameter);
219+
if (PARAM_CHARSET.equals(parameter)) {
218220
if (this.resolvedCharset == null) {
219221
this.resolvedCharset = Charset.forName(unquote(value));
220222
}
@@ -569,6 +571,17 @@ public int compareTo(MimeType other) {
569571
return 0;
570572
}
571573

574+
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
575+
// Rely on default serialization, just initialize state after deserialization.
576+
ois.defaultReadObject();
577+
578+
// Initialize transient fields.
579+
String charsetName = getParameter(PARAM_CHARSET);
580+
if (charsetName != null) {
581+
this.resolvedCharset = Charset.forName(unquote(charsetName));
582+
}
583+
}
584+
572585

573586
/**
574587
* Parse the given String value into a {@code MimeType} object,

spring-core/src/test/java/org/springframework/util/MimeTypeTests.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -26,6 +26,7 @@
2626

2727
import org.springframework.core.convert.ConversionService;
2828
import org.springframework.core.convert.support.DefaultConversionService;
29+
import org.springframework.core.testfixture.io.SerializationTestUtils;
2930

3031
import static java.util.Collections.singletonMap;
3132
import static org.assertj.core.api.Assertions.assertThat;
@@ -267,13 +268,13 @@ void parseMimeTypeSingleQuotedParameterValue() {
267268
assertThat(mimeType.getParameter("attr")).isEqualTo("'v>alue'");
268269
}
269270

270-
@Test // SPR-16630
271+
@Test // SPR-16630
271272
void parseMimeTypeWithSpacesAroundEquals() {
272273
MimeType mimeType = MimeTypeUtils.parseMimeType("multipart/x-mixed-replace;boundary = --myboundary");
273274
assertThat(mimeType.getParameter("boundary")).isEqualTo("--myboundary");
274275
}
275276

276-
@Test // SPR-16630
277+
@Test // SPR-16630
277278
void parseMimeTypeWithSpacesAroundEqualsAndQuotedValue() {
278279
MimeType mimeType = MimeTypeUtils.parseMimeType("text/plain; foo = \" bar \" ");
279280
assertThat(mimeType.getParameter("foo")).isEqualTo("\" bar \"");
@@ -303,14 +304,14 @@ void parseMimeTypes() {
303304
assertThat(mimeTypes.size()).as("Invalid amount of mime types").isEqualTo(0);
304305
}
305306

306-
@Test // gh-23241
307+
@Test // gh-23241
307308
void parseMimeTypesWithTrailingComma() {
308309
List<MimeType> mimeTypes = MimeTypeUtils.parseMimeTypes("text/plain, text/html,");
309310
assertThat(mimeTypes).as("No mime types returned").isNotNull();
310311
assertThat(mimeTypes.size()).as("Incorrect number of mime types").isEqualTo(2);
311312
}
312313

313-
@Test // SPR-17459
314+
@Test // SPR-17459
314315
void parseMimeTypesWithQuotedParameters() {
315316
testWithQuotedParameters("foo/bar;param=\",\"");
316317
testWithQuotedParameters("foo/bar;param=\"s,a,\"");
@@ -323,8 +324,9 @@ void parseMimeTypesWithQuotedParameters() {
323324
private void testWithQuotedParameters(String... mimeTypes) {
324325
String s = String.join(",", mimeTypes);
325326
List<MimeType> actual = MimeTypeUtils.parseMimeTypes(s);
327+
326328
assertThat(actual.size()).isEqualTo(mimeTypes.length);
327-
for (int i=0; i < mimeTypes.length; i++) {
329+
for (int i = 0; i < mimeTypes.length; i++) {
328330
assertThat(actual.get(i).toString()).isEqualTo(mimeTypes[i]);
329331
}
330332
}
@@ -351,6 +353,7 @@ void compareTo() {
351353

352354
List<MimeType> result = new ArrayList<>(expected);
353355
Random rnd = new Random();
356+
354357
// shuffle & sort 10 times
355358
for (int i = 0; i < 10; i++) {
356359
Collections.shuffle(result, rnd);
@@ -380,11 +383,7 @@ void compareToCaseSensitivity() {
380383
assertThat(m2.compareTo(m1) != 0).as("Invalid comparison result").isTrue();
381384
}
382385

383-
/**
384-
* SPR-13157
385-
* @since 4.2
386-
*/
387-
@Test
386+
@Test // SPR-13157
388387
void equalsIsCaseInsensitiveForCharsets() {
389388
MimeType m1 = new MimeType("text", "plain", singletonMap("charset", "UTF-8"));
390389
MimeType m2 = new MimeType("text", "plain", singletonMap("charset", "utf-8"));
@@ -394,4 +393,12 @@ void equalsIsCaseInsensitiveForCharsets() {
394393
assertThat(m2.compareTo(m1)).isEqualTo(0);
395394
}
396395

396+
@Test // gh-26127
397+
void serialize() throws Exception {
398+
MimeType original = new MimeType("text", "plain", StandardCharsets.UTF_8);
399+
MimeType deserialized = (MimeType) SerializationTestUtils.serializeAndDeserialize(original);
400+
assertThat(deserialized).isEqualTo(original);
401+
assertThat(original).isEqualTo(deserialized);
402+
}
403+
397404
}

spring-web/src/main/java/org/springframework/http/MediaType.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,9 @@ public MediaType(String type, String subtype, @Nullable Map<String, String> para
480480

481481

482482
@Override
483-
protected void checkParameters(String attribute, String value) {
484-
super.checkParameters(attribute, value);
485-
if (PARAM_QUALITY_FACTOR.equals(attribute)) {
483+
protected void checkParameters(String parameter, String value) {
484+
super.checkParameters(parameter, value);
485+
if (PARAM_QUALITY_FACTOR.equals(parameter)) {
486486
value = unquote(value);
487487
double d = Double.parseDouble(value);
488488
Assert.isTrue(d >= 0D && d <= 1D,

spring-web/src/test/java/org/springframework/http/MediaTypeTests.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.http;
1818

19+
import java.nio.charset.StandardCharsets;
1920
import java.util.ArrayList;
2021
import java.util.Collections;
2122
import java.util.Comparator;
@@ -26,6 +27,7 @@
2627

2728
import org.springframework.core.convert.ConversionService;
2829
import org.springframework.core.convert.support.DefaultConversionService;
30+
import org.springframework.core.testfixture.io.SerializationTestUtils;
2931

3032
import static org.assertj.core.api.Assertions.assertThat;
3133
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -160,7 +162,7 @@ public void parseMediaTypes() throws Exception {
160162
assertThat(mediaTypes.size()).as("Invalid amount of media types").isEqualTo(0);
161163
}
162164

163-
@Test // gh-23241
165+
@Test // gh-23241
164166
public void parseMediaTypesWithTrailingComma() {
165167
List<MediaType> mediaTypes = MediaType.parseMediaTypes("text/plain, text/html, ");
166168
assertThat(mediaTypes).as("No media types returned").isNotNull();
@@ -460,4 +462,12 @@ public void isConcrete() {
460462
assertThat(new MediaType("text", "*").isConcrete()).as("text/* concrete").isFalse();
461463
}
462464

465+
@Test // gh-26127
466+
void serialize() throws Exception {
467+
MediaType original = new MediaType("text", "plain", StandardCharsets.UTF_8);
468+
MediaType deserialized = (MediaType) SerializationTestUtils.serializeAndDeserialize(original);
469+
assertThat(deserialized).isEqualTo(original);
470+
assertThat(original).isEqualTo(deserialized);
471+
}
472+
463473
}

0 commit comments

Comments
 (0)