Declare resolvedCharset as transient (restoring serializability)

Closes gh-26127
This commit is contained in:
Juergen Hoeller 2020-11-20 18:40:10 +01:00
parent e6324bd578
commit 4fb5d59c64
4 changed files with 50 additions and 18 deletions

View File

@ -16,6 +16,8 @@
package org.springframework.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.BitSet;
@ -104,7 +106,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
private final Map<String, String> parameters;
@Nullable
private Charset resolvedCharset;
private transient Charset resolvedCharset;
@Nullable
private volatile String toStringValue;
@ -184,9 +186,9 @@ public class MimeType implements Comparable<MimeType>, Serializable {
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
if (!CollectionUtils.isEmpty(parameters)) {
Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
parameters.forEach((attribute, value) -> {
checkParameters(attribute, value);
map.put(attribute, value);
parameters.forEach((parameter, value) -> {
checkParameters(parameter, value);
map.put(parameter, value);
});
this.parameters = Collections.unmodifiableMap(map);
}
@ -224,11 +226,11 @@ public class MimeType implements Comparable<MimeType>, Serializable {
}
}
protected void checkParameters(String attribute, String value) {
Assert.hasLength(attribute, "'attribute' must not be empty");
protected void checkParameters(String parameter, String value) {
Assert.hasLength(parameter, "'parameter' must not be empty");
Assert.hasLength(value, "'value' must not be empty");
checkToken(attribute);
if (PARAM_CHARSET.equals(attribute)) {
checkToken(parameter);
if (PARAM_CHARSET.equals(parameter)) {
if (this.resolvedCharset == null) {
this.resolvedCharset = Charset.forName(unquote(value));
}
@ -591,6 +593,17 @@ public class MimeType implements Comparable<MimeType>, Serializable {
return 0;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
String charsetName = getParameter(PARAM_CHARSET);
if (charsetName != null) {
this.resolvedCharset = Charset.forName(unquote(charsetName));
}
}
/**
* Parse the given String value into a {@code MimeType} object,

View File

@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.testfixture.io.SerializationTestUtils;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
@ -267,13 +268,13 @@ class MimeTypeTests {
assertThat(mimeType.getParameter("attr")).isEqualTo("'v>alue'");
}
@Test // SPR-16630
@Test // SPR-16630
void parseMimeTypeWithSpacesAroundEquals() {
MimeType mimeType = MimeTypeUtils.parseMimeType("multipart/x-mixed-replace;boundary = --myboundary");
assertThat(mimeType.getParameter("boundary")).isEqualTo("--myboundary");
}
@Test // SPR-16630
@Test // SPR-16630
void parseMimeTypeWithSpacesAroundEqualsAndQuotedValue() {
MimeType mimeType = MimeTypeUtils.parseMimeType("text/plain; foo = \" bar \" ");
assertThat(mimeType.getParameter("foo")).isEqualTo("\" bar \"");
@ -303,14 +304,14 @@ class MimeTypeTests {
assertThat(mimeTypes.size()).as("Invalid amount of mime types").isEqualTo(0);
}
@Test // gh-23241
@Test // gh-23241
void parseMimeTypesWithTrailingComma() {
List<MimeType> mimeTypes = MimeTypeUtils.parseMimeTypes("text/plain, text/html,");
assertThat(mimeTypes).as("No mime types returned").isNotNull();
assertThat(mimeTypes.size()).as("Incorrect number of mime types").isEqualTo(2);
}
@Test // SPR-17459
@Test // SPR-17459
void parseMimeTypesWithQuotedParameters() {
testWithQuotedParameters("foo/bar;param=\",\"");
testWithQuotedParameters("foo/bar;param=\"s,a,\"");
@ -332,7 +333,7 @@ class MimeTypeTests {
assertThat(type.getSubtypeSuffix()).isEqualTo("json");
}
@Test // gh-25350
@Test // gh-25350
void wildcardSubtypeCompatibleWithSuffix() {
MimeType applicationStar = new MimeType("application", "*");
MimeType applicationVndJson = new MimeType("application", "vnd.something+json");
@ -413,4 +414,12 @@ class MimeTypeTests {
assertThat(m2.compareTo(m1)).isEqualTo(0);
}
@Test // gh-26127
void serialize() throws Exception {
MimeType original = new MimeType("text", "plain", StandardCharsets.UTF_8);
MimeType deserialized = SerializationTestUtils.serializeAndDeserialize(original);
assertThat(deserialized).isEqualTo(original);
assertThat(original).isEqualTo(deserialized);
}
}

View File

@ -514,9 +514,9 @@ public class MediaType extends MimeType implements Serializable {
@Override
protected void checkParameters(String attribute, String value) {
super.checkParameters(attribute, value);
if (PARAM_QUALITY_FACTOR.equals(attribute)) {
protected void checkParameters(String parameter, String value) {
super.checkParameters(parameter, value);
if (PARAM_QUALITY_FACTOR.equals(parameter)) {
value = unquote(value);
double d = Double.parseDouble(value);
Assert.isTrue(d >= 0D && d <= 1D,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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 java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -26,6 +27,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.testfixture.io.SerializationTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -160,7 +162,7 @@ public class MediaTypeTests {
assertThat(mediaTypes.size()).as("Invalid amount of media types").isEqualTo(0);
}
@Test // gh-23241
@Test // gh-23241
public void parseMediaTypesWithTrailingComma() {
List<MediaType> mediaTypes = MediaType.parseMediaTypes("text/plain, text/html, ");
assertThat(mediaTypes).as("No media types returned").isNotNull();
@ -460,4 +462,12 @@ public class MediaTypeTests {
assertThat(new MediaType("text", "*").isConcrete()).as("text/* concrete").isFalse();
}
@Test // gh-26127
void serialize() throws Exception {
MediaType original = new MediaType("text", "plain", StandardCharsets.UTF_8);
MediaType deserialized = SerializationTestUtils.serializeAndDeserialize(original);
assertThat(deserialized).isEqualTo(original);
assertThat(original).isEqualTo(deserialized);
}
}