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