From cfe7ff1c819b3b6d624ca524b489faab099ba2dd Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 2 Feb 2018 13:44:07 +0100 Subject: [PATCH] MimeType.compareTo uses case-insensitive Charset (analogous to equals) Issue: SPR-16458 --- .../org/springframework/util/MimeType.java | 64 ++++++++++++------- .../springframework/util/MimeTypeTests.java | 12 ++-- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/MimeType.java b/spring-core/src/main/java/org/springframework/util/MimeType.java index 76220df744..2e3bc960f7 100644 --- a/spring-core/src/main/java/org/springframework/util/MimeType.java +++ b/spring-core/src/main/java/org/springframework/util/MimeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -319,7 +319,7 @@ public class MimeType implements Comparable, Serializable { return true; } if (this.isWildcardSubtype()) { - // wildcard with suffix, e.g. application/*+xml + // Wildcard with suffix, e.g. application/*+xml int thisPlusIdx = getSubtype().lastIndexOf('+'); if (thisPlusIdx == -1) { return true; @@ -361,22 +361,18 @@ public class MimeType implements Comparable, Serializable { if (getSubtype().equals(other.getSubtype())) { return true; } - // wildcard with suffix? e.g. application/*+xml + // Wildcard with suffix? e.g. application/*+xml if (this.isWildcardSubtype() || other.isWildcardSubtype()) { - int thisPlusIdx = getSubtype().lastIndexOf('+'); int otherPlusIdx = other.getSubtype().lastIndexOf('+'); - if (thisPlusIdx == -1 && otherPlusIdx == -1) { return true; } else if (thisPlusIdx != -1 && otherPlusIdx != -1) { String thisSubtypeNoSuffix = getSubtype().substring(0, thisPlusIdx); String otherSubtypeNoSuffix = other.getSubtype().substring(0, otherPlusIdx); - String thisSubtypeSuffix = getSubtype().substring(thisPlusIdx + 1); String otherSubtypeSuffix = other.getSubtype().substring(otherPlusIdx + 1); - if (thisSubtypeSuffix.equals(otherSubtypeSuffix) && (WILDCARD_TYPE.equals(thisSubtypeNoSuffix) || WILDCARD_TYPE.equals(otherSubtypeNoSuffix))) { return true; @@ -417,7 +413,6 @@ public class MimeType implements Comparable, Serializable { if (!other.parameters.containsKey(key)) { return false; } - if (PARAM_CHARSET.equals(key)) { if (!ObjectUtils.nullSafeEquals(getCharset(), other.getCharset())) { return false; @@ -481,12 +476,14 @@ public class MimeType implements Comparable, Serializable { if (comp != 0) { return comp; } + TreeSet thisAttributes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); thisAttributes.addAll(getParameters().keySet()); TreeSet otherAttributes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); otherAttributes.addAll(other.getParameters().keySet()); Iterator thisAttributesIterator = thisAttributes.iterator(); Iterator otherAttributesIterator = otherAttributes.iterator(); + while (thisAttributesIterator.hasNext()) { String thisAttribute = thisAttributesIterator.next(); String otherAttribute = otherAttributesIterator.next(); @@ -494,16 +491,35 @@ public class MimeType implements Comparable, Serializable { if (comp != 0) { return comp; } - String thisValue = getParameters().get(thisAttribute); - String otherValue = other.getParameters().get(otherAttribute); - if (otherValue == null) { - otherValue = ""; + if (PARAM_CHARSET.equals(thisAttribute)) { + Charset thisCharset = getCharset(); + Charset otherCharset = other.getCharset(); + if (thisCharset != otherCharset) { + if (thisCharset == null) { + return -1; + } + if (otherCharset == null) { + return 1; + } + comp = thisCharset.compareTo(otherCharset); + if (comp != 0) { + return comp; + } + } } - comp = thisValue.compareTo(otherValue); - if (comp != 0) { - return comp; + else { + String thisValue = getParameters().get(thisAttribute); + String otherValue = other.getParameters().get(otherAttribute); + if (otherValue == null) { + otherValue = ""; + } + comp = thisValue.compareTo(otherValue); + if (comp != 0) { + return comp; + } } } + return 0; } @@ -529,26 +545,26 @@ public class MimeType implements Comparable, Serializable { @Override public int compare(T mimeType1, T mimeType2) { - if (mimeType1.isWildcardType() && !mimeType2.isWildcardType()) { // */* < audio/* + if (mimeType1.isWildcardType() && !mimeType2.isWildcardType()) { // */* < audio/* return 1; } - else if (mimeType2.isWildcardType() && !mimeType1.isWildcardType()) { // audio/* > */* + else if (mimeType2.isWildcardType() && !mimeType1.isWildcardType()) { // audio/* > */* return -1; } - else if (!mimeType1.getType().equals(mimeType2.getType())) { // audio/basic == text/html + else if (!mimeType1.getType().equals(mimeType2.getType())) { // audio/basic == text/html return 0; } - else { // mediaType1.getType().equals(mediaType2.getType()) - if (mimeType1.isWildcardSubtype() && !mimeType2.isWildcardSubtype()) { // audio/* < audio/basic + else { // mediaType1.getType().equals(mediaType2.getType()) + if (mimeType1.isWildcardSubtype() && !mimeType2.isWildcardSubtype()) { // audio/* < audio/basic return 1; } - else if (mimeType2.isWildcardSubtype() && !mimeType1.isWildcardSubtype()) { // audio/basic > audio/* + else if (mimeType2.isWildcardSubtype() && !mimeType1.isWildcardSubtype()) { // audio/basic > audio/* return -1; } - else if (!mimeType1.getSubtype().equals(mimeType2.getSubtype())) { // audio/basic == audio/wave + else if (!mimeType1.getSubtype().equals(mimeType2.getSubtype())) { // audio/basic == audio/wave return 0; } - else { // mediaType2.getSubtype().equals(mediaType2.getSubtype()) + else { // mediaType2.getSubtype().equals(mediaType2.getSubtype()) return compareParameters(mimeType1, mimeType2); } } @@ -557,7 +573,7 @@ public class MimeType implements Comparable, Serializable { protected int compareParameters(T mimeType1, T mimeType2) { int paramsSize1 = mimeType1.getParameters().size(); int paramsSize2 = mimeType2.getParameters().size(); - return (paramsSize2 < paramsSize1 ? -1 : (paramsSize2 == paramsSize1 ? 0 : 1)); // audio/basic;level=1 < audio/basic + return Integer.compare(paramsSize2, paramsSize1); // audio/basic;level=1 < audio/basic } } diff --git a/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java b/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java index f24e93c33a..03ab787bed 100644 --- a/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java +++ b/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -27,12 +27,8 @@ import org.junit.Test; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; -import static java.util.Collections.singletonMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static java.util.Collections.*; +import static org.junit.Assert.*; /** * Unit tests for {@link MimeType}. @@ -335,6 +331,8 @@ public class MimeTypeTests { MimeType m2 = new MimeType("text", "plain", singletonMap("charset", "utf-8")); assertEquals(m1, m2); assertEquals(m2, m1); + assertEquals(0, m1.compareTo(m2)); + assertEquals(0, m2.compareTo(m1)); } }