Declare resolvedCharset as transient (restoring serializability)
Closes gh-26127
This commit is contained in:
parent
e6324bd578
commit
4fb5d59c64
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
@ -104,7 +106,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||||
private final Map<String, String> parameters;
|
private final Map<String, String> parameters;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Charset resolvedCharset;
|
private transient Charset resolvedCharset;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private volatile String toStringValue;
|
private volatile String toStringValue;
|
||||||
|
|
@ -184,9 +186,9 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||||
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
|
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
|
||||||
if (!CollectionUtils.isEmpty(parameters)) {
|
if (!CollectionUtils.isEmpty(parameters)) {
|
||||||
Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
|
Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
|
||||||
parameters.forEach((attribute, value) -> {
|
parameters.forEach((parameter, value) -> {
|
||||||
checkParameters(attribute, value);
|
checkParameters(parameter, value);
|
||||||
map.put(attribute, value);
|
map.put(parameter, value);
|
||||||
});
|
});
|
||||||
this.parameters = Collections.unmodifiableMap(map);
|
this.parameters = Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
@ -224,11 +226,11 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkParameters(String attribute, String value) {
|
protected void checkParameters(String parameter, String value) {
|
||||||
Assert.hasLength(attribute, "'attribute' must not be empty");
|
Assert.hasLength(parameter, "'parameter' must not be empty");
|
||||||
Assert.hasLength(value, "'value' must not be empty");
|
Assert.hasLength(value, "'value' must not be empty");
|
||||||
checkToken(attribute);
|
checkToken(parameter);
|
||||||
if (PARAM_CHARSET.equals(attribute)) {
|
if (PARAM_CHARSET.equals(parameter)) {
|
||||||
if (this.resolvedCharset == null) {
|
if (this.resolvedCharset == null) {
|
||||||
this.resolvedCharset = Charset.forName(unquote(value));
|
this.resolvedCharset = Charset.forName(unquote(value));
|
||||||
}
|
}
|
||||||
|
|
@ -591,6 +593,17 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||||
return 0;
|
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,
|
* Parse the given String value into a {@code MimeType} object,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
|
import org.springframework.core.testfixture.io.SerializationTestUtils;
|
||||||
|
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -267,13 +268,13 @@ class MimeTypeTests {
|
||||||
assertThat(mimeType.getParameter("attr")).isEqualTo("'v>alue'");
|
assertThat(mimeType.getParameter("attr")).isEqualTo("'v>alue'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-16630
|
@Test // SPR-16630
|
||||||
void parseMimeTypeWithSpacesAroundEquals() {
|
void parseMimeTypeWithSpacesAroundEquals() {
|
||||||
MimeType mimeType = MimeTypeUtils.parseMimeType("multipart/x-mixed-replace;boundary = --myboundary");
|
MimeType mimeType = MimeTypeUtils.parseMimeType("multipart/x-mixed-replace;boundary = --myboundary");
|
||||||
assertThat(mimeType.getParameter("boundary")).isEqualTo("--myboundary");
|
assertThat(mimeType.getParameter("boundary")).isEqualTo("--myboundary");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-16630
|
@Test // SPR-16630
|
||||||
void parseMimeTypeWithSpacesAroundEqualsAndQuotedValue() {
|
void parseMimeTypeWithSpacesAroundEqualsAndQuotedValue() {
|
||||||
MimeType mimeType = MimeTypeUtils.parseMimeType("text/plain; foo = \" bar \" ");
|
MimeType mimeType = MimeTypeUtils.parseMimeType("text/plain; foo = \" bar \" ");
|
||||||
assertThat(mimeType.getParameter("foo")).isEqualTo("\" bar \"");
|
assertThat(mimeType.getParameter("foo")).isEqualTo("\" bar \"");
|
||||||
|
|
@ -303,14 +304,14 @@ class MimeTypeTests {
|
||||||
assertThat(mimeTypes.size()).as("Invalid amount of mime types").isEqualTo(0);
|
assertThat(mimeTypes.size()).as("Invalid amount of mime types").isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-23241
|
@Test // gh-23241
|
||||||
void parseMimeTypesWithTrailingComma() {
|
void parseMimeTypesWithTrailingComma() {
|
||||||
List<MimeType> mimeTypes = MimeTypeUtils.parseMimeTypes("text/plain, text/html,");
|
List<MimeType> mimeTypes = MimeTypeUtils.parseMimeTypes("text/plain, text/html,");
|
||||||
assertThat(mimeTypes).as("No mime types returned").isNotNull();
|
assertThat(mimeTypes).as("No mime types returned").isNotNull();
|
||||||
assertThat(mimeTypes.size()).as("Incorrect number of mime types").isEqualTo(2);
|
assertThat(mimeTypes.size()).as("Incorrect number of mime types").isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-17459
|
@Test // SPR-17459
|
||||||
void parseMimeTypesWithQuotedParameters() {
|
void parseMimeTypesWithQuotedParameters() {
|
||||||
testWithQuotedParameters("foo/bar;param=\",\"");
|
testWithQuotedParameters("foo/bar;param=\",\"");
|
||||||
testWithQuotedParameters("foo/bar;param=\"s,a,\"");
|
testWithQuotedParameters("foo/bar;param=\"s,a,\"");
|
||||||
|
|
@ -332,7 +333,7 @@ class MimeTypeTests {
|
||||||
assertThat(type.getSubtypeSuffix()).isEqualTo("json");
|
assertThat(type.getSubtypeSuffix()).isEqualTo("json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-25350
|
@Test // gh-25350
|
||||||
void wildcardSubtypeCompatibleWithSuffix() {
|
void wildcardSubtypeCompatibleWithSuffix() {
|
||||||
MimeType applicationStar = new MimeType("application", "*");
|
MimeType applicationStar = new MimeType("application", "*");
|
||||||
MimeType applicationVndJson = new MimeType("application", "vnd.something+json");
|
MimeType applicationVndJson = new MimeType("application", "vnd.something+json");
|
||||||
|
|
@ -413,4 +414,12 @@ class MimeTypeTests {
|
||||||
assertThat(m2.compareTo(m1)).isEqualTo(0);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -514,9 +514,9 @@ public class MediaType extends MimeType implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkParameters(String attribute, String value) {
|
protected void checkParameters(String parameter, String value) {
|
||||||
super.checkParameters(attribute, value);
|
super.checkParameters(parameter, value);
|
||||||
if (PARAM_QUALITY_FACTOR.equals(attribute)) {
|
if (PARAM_QUALITY_FACTOR.equals(parameter)) {
|
||||||
value = unquote(value);
|
value = unquote(value);
|
||||||
double d = Double.parseDouble(value);
|
double d = Double.parseDouble(value);
|
||||||
Assert.isTrue(d >= 0D && d <= 1D,
|
Assert.isTrue(d >= 0D && d <= 1D,
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.http;
|
package org.springframework.http;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
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.ConversionService;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
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.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
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);
|
assertThat(mediaTypes.size()).as("Invalid amount of media types").isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-23241
|
@Test // gh-23241
|
||||||
public void parseMediaTypesWithTrailingComma() {
|
public void parseMediaTypesWithTrailingComma() {
|
||||||
List<MediaType> mediaTypes = MediaType.parseMediaTypes("text/plain, text/html, ");
|
List<MediaType> mediaTypes = MediaType.parseMediaTypes("text/plain, text/html, ");
|
||||||
assertThat(mediaTypes).as("No media types returned").isNotNull();
|
assertThat(mediaTypes).as("No media types returned").isNotNull();
|
||||||
|
|
@ -460,4 +462,12 @@ public class MediaTypeTests {
|
||||||
assertThat(new MediaType("text", "*").isConcrete()).as("text/* concrete").isFalse();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue