Skip to content

Commit 89e504c

Browse files
committed
Uses Charset instead of String in MimeType.equals()
Prior to this commit, Spring's MimeType checked for equality between two MIME types based on the equality of their properties maps; however, the properties maps contain string representations of the "charset" values. Thus, "UTF-8" is never equal to "utf-8" which breaks the contract for character set names which must be compared in a case-insensitive manner. This commit addresses this issue by ensuring that "charset" properties in MimeType instances are compared as Java Charset instances, thereby ignoring case when checking for equality between charset names. Issue: SPR-13157
1 parent f2f58f1 commit 89e504c

File tree

3 files changed

+61
-14
lines changed

3 files changed

+61
-14
lines changed

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

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.Locale;
2727
import java.util.Map;
28+
import java.util.Map.Entry;
2829
import java.util.TreeSet;
2930

3031
/**
@@ -430,7 +431,37 @@ public boolean equals(Object other) {
430431
MimeType otherType = (MimeType) other;
431432
return (this.type.equalsIgnoreCase(otherType.type) &&
432433
this.subtype.equalsIgnoreCase(otherType.subtype) &&
433-
this.parameters.equals(otherType.parameters));
434+
parametersAreEqual(otherType));
435+
}
436+
437+
/**
438+
* Determine if the parameters in this {@code MimeType} and the supplied
439+
* {@code MimeType} are equal, performing case-insensitive comparisons
440+
* for {@link Charset}s.
441+
* @since 4.2
442+
*/
443+
private boolean parametersAreEqual(MimeType that) {
444+
if (this.parameters.size() != that.parameters.size()) {
445+
return false;
446+
}
447+
448+
for (Entry<String, String> entry : this.parameters.entrySet()) {
449+
String key = entry.getKey();
450+
if (!that.parameters.containsKey(key)) {
451+
return false;
452+
}
453+
454+
if (PARAM_CHARSET.equals(key)) {
455+
if (!ObjectUtils.nullSafeEquals(this.getCharSet(), that.getCharSet())) {
456+
return false;
457+
}
458+
}
459+
else if (!ObjectUtils.nullSafeEquals(this.parameters.get(key), that.parameters.get(key))) {
460+
return false;
461+
}
462+
}
463+
464+
return true;
434465
}
435466

436467
@Override

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 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.
@@ -27,15 +27,18 @@
2727
import org.springframework.core.convert.ConversionService;
2828
import org.springframework.core.convert.support.DefaultConversionService;
2929

30+
import static java.util.Collections.singletonMap;
3031
import static org.junit.Assert.*;
3132

3233
/**
34+
* Unit tests for {@link MimeType}.
35+
*
3336
* @author Arjen Poutsma
3437
* @author Juergen Hoeller
38+
* @author Sam Brannen
3539
*/
3640
public class MimeTypeTests {
3741

38-
3942
@Test(expected = IllegalArgumentException.class)
4043
public void slashInSubtype() {
4144
new MimeType("text", "/");
@@ -85,7 +88,7 @@ public void parseQuotedCharset() {
8588
}
8689

8790
@Test
88-
public void testWithConversionService() {
91+
public void withConversionService() {
8992
ConversionService conversionService = new DefaultConversionService();
9093
assertTrue(conversionService.canConvert(String.class, MimeType.class));
9194
MimeType mimeType = MimeType.valueOf("application/xml");
@@ -211,16 +214,18 @@ public void parseMimeTypeIllegalCharset() {
211214
MimeTypeUtils.parseMimeType("text/html; charset=foo-bar");
212215
}
213216

214-
// SPR-8917
215-
217+
/**
218+
* SPR-8917
219+
*/
216220
@Test
217221
public void parseMimeTypeQuotedParameterValue() {
218222
MimeType mimeType = MimeTypeUtils.parseMimeType("audio/*;attr=\"v>alue\"");
219223
assertEquals("\"v>alue\"", mimeType.getParameter("attr"));
220224
}
221225

222-
// SPR-8917
223-
226+
/**
227+
* SPR-8917
228+
*/
224229
@Test
225230
public void parseMimeTypeSingleQuotedParameterValue() {
226231
MimeType mimeType = MimeTypeUtils.parseMimeType("audio/*;attr='v>alue'");
@@ -249,7 +254,7 @@ public void compareTo() {
249254
MimeType audioBasic = new MimeType("audio", "basic");
250255
MimeType audio = new MimeType("audio");
251256
MimeType audioWave = new MimeType("audio", "wave");
252-
MimeType audioBasicLevel = new MimeType("audio", "basic", Collections.singletonMap("level", "1"));
257+
MimeType audioBasicLevel = new MimeType("audio", "basic", singletonMap("level", "1"));
253258

254259
// equal
255260
assertEquals("Invalid comparison result", 0, audioBasic.compareTo(audioBasic));
@@ -284,16 +289,27 @@ public void compareToCaseSensitivity() {
284289
assertEquals("Invalid comparison result", 0, m1.compareTo(m2));
285290
assertEquals("Invalid comparison result", 0, m2.compareTo(m1));
286291

287-
m1 = new MimeType("audio", "basic", Collections.singletonMap("foo", "bar"));
288-
m2 = new MimeType("audio", "basic", Collections.singletonMap("Foo", "bar"));
292+
m1 = new MimeType("audio", "basic", singletonMap("foo", "bar"));
293+
m2 = new MimeType("audio", "basic", singletonMap("Foo", "bar"));
289294
assertEquals("Invalid comparison result", 0, m1.compareTo(m2));
290295
assertEquals("Invalid comparison result", 0, m2.compareTo(m1));
291296

292-
m1 = new MimeType("audio", "basic", Collections.singletonMap("foo", "bar"));
293-
m2 = new MimeType("audio", "basic", Collections.singletonMap("foo", "Bar"));
297+
m1 = new MimeType("audio", "basic", singletonMap("foo", "bar"));
298+
m2 = new MimeType("audio", "basic", singletonMap("foo", "Bar"));
294299
assertTrue("Invalid comparison result", m1.compareTo(m2) != 0);
295300
assertTrue("Invalid comparison result", m2.compareTo(m1) != 0);
296301
}
297302

303+
/**
304+
* SPR-13157
305+
* @since 4.2
306+
*/
307+
@Test
308+
public void equalsIsCaseInsensitiveForCharsets() {
309+
MimeType m1 = new MimeType("text", "plain", singletonMap("charset", "UTF-8"));
310+
MimeType m2 = new MimeType("text", "plain", singletonMap("charset", "utf-8"));
311+
assertEquals(m1, m2);
312+
assertEquals(m2, m1);
313+
}
298314

299315
}

spring-web/src/test/java/org/springframework/web/client/AbstractJettyServerTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class AbstractJettyServerTestCase {
5656

5757
protected static final String baseUrl = "http://localhost:" + port;
5858

59-
protected static final MediaType textContentType = new MediaType("text", "plain", Collections.singletonMap("charset", "utf-8"));
59+
protected static final MediaType textContentType = new MediaType("text", "plain", Collections.singletonMap("charset", "UTF-8"));
6060

6161
protected static final MediaType jsonContentType = new MediaType("application", "json", Collections.singletonMap("charset", "utf-8"));
6262

0 commit comments

Comments
 (0)