diff --git a/org.springframework.web/src/main/java/org/springframework/http/MediaType.java b/org.springframework.web/src/main/java/org/springframework/http/MediaType.java index 39db262e9fc..77d7661254b 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/MediaType.java +++ b/org.springframework.web/src/main/java/org/springframework/http/MediaType.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.TreeSet; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -311,9 +312,38 @@ public class MediaType implements Comparable { * @see #sortBySpecificity(List) */ public int compareTo(MediaType other) { - String s1 = this.toString(); - String s2 = other.toString(); - return s1.compareToIgnoreCase(s2); + int comp = this.type.compareToIgnoreCase(other.type); + if (comp != 0) { + return comp; + } + comp = this.subtype.compareToIgnoreCase(other.subtype); + if (comp != 0) { + return comp; + } + comp = this.parameters.size() - other.parameters.size(); + if (comp != 0) { + return comp; + } + Iterator thisAttributes = new TreeSet(this.parameters.keySet()).iterator(); + Iterator otherAttributes = new TreeSet(other.parameters.keySet()).iterator(); + while (thisAttributes.hasNext()) { + String thisAttribute = thisAttributes.next(); + String otherAttribute = otherAttributes.next(); + comp = thisAttribute.compareToIgnoreCase(otherAttribute); + if (comp != 0) { + return comp; + } + String thisValue = this.parameters.get(thisAttribute); + String otherValue = other.parameters.get(otherAttribute); + if (otherValue == null) { + otherValue = ""; + } + comp = thisValue.compareTo(otherValue); + if (comp != 0) { + return comp; + } + } + return 0; } @Override @@ -348,7 +378,11 @@ public class MediaType implements Comparable { builder.append(this.type); builder.append('/'); builder.append(this.subtype); - for (Map.Entry entry : this.parameters.entrySet()) { + appendTo(this.parameters, builder); + } + + private static void appendTo(Map map, StringBuilder builder) { + for (Map.Entry entry : map.entrySet()) { builder.append(';'); builder.append(entry.getKey()); builder.append('='); diff --git a/org.springframework.web/src/test/java/org/springframework/http/MediaTypeTests.java b/org.springframework.web/src/test/java/org/springframework/http/MediaTypeTests.java index 0a042fbb204..7a18d90baca 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/MediaTypeTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/MediaTypeTests.java @@ -177,6 +177,7 @@ public class MediaTypeTests { MediaType audio = new MediaType("audio"); MediaType audioWave = new MediaType("audio", "wave"); MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1")); + MediaType audioBasic07 = new MediaType("audio", "basic", 0.7); // equal assertEquals("Invalid comparison result", 0, audioBasic.compareTo(audioBasic)); @@ -189,6 +190,7 @@ public class MediaTypeTests { expected.add(audio); expected.add(audioBasic); expected.add(audioBasicLevel); + expected.add(audioBasic07); expected.add(audioWave); List result = new ArrayList(expected); @@ -199,10 +201,37 @@ public class MediaTypeTests { Collections.sort(result); for (int j = 0; j < result.size(); j++) { - assertSame("Invalid media type at " + j, expected.get(j), result.get(j)); + assertSame("Invalid media type at " + j + ", run " + i, expected.get(j), result.get(j)); } } + } + @Test + public void compareToConsistentWithEquals() { + MediaType m1 = MediaType.parseMediaType("text/html; q=0.7; charset=iso-8859-1"); + MediaType m2 = MediaType.parseMediaType("text/html; charset=iso-8859-1; q=0.7"); + + assertEquals("Media types not equal", m1, m2); + assertEquals("compareTo() not consistent with equals", 0, m1.compareTo(m2)); + assertEquals("compareTo() not consistent with equals", 0, m2.compareTo(m1)); + } + + @Test + public void compareToCaseSensitivity() { + MediaType m1 = new MediaType("audio", "basic"); + MediaType m2 = new MediaType("Audio", "Basic"); + assertEquals("Invalid comparison result", 0, m1.compareTo(m2)); + assertEquals("Invalid comparison result", 0, m2.compareTo(m1)); + + m1 = new MediaType("audio", "basic", Collections.singletonMap("foo", "bar")); + m2 = new MediaType("audio", "basic", Collections.singletonMap("Foo", "bar")); + assertEquals("Invalid comparison result", 0, m1.compareTo(m2)); + assertEquals("Invalid comparison result", 0, m2.compareTo(m1)); + + m1 = new MediaType("audio", "basic", Collections.singletonMap("foo", "bar")); + m2 = new MediaType("audio", "basic", Collections.singletonMap("foo", "Bar")); + assertTrue("Invalid comparison result", m1.compareTo(m2) != 0); + assertTrue("Invalid comparison result", m2.compareTo(m1) != 0); } @Test