From a6b7cbc790e30bbcfe84dff098ac38832f8f7c25 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Mon, 23 Feb 2009 22:02:10 +0000 Subject: [PATCH] Fixed issue in parsing of invalid MediaTypes from java.net.HttpUrlConnection (*; q=.2) git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@672 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../org/springframework/util/MediaType.java | 39 +++-- .../springframework/util/MediaTypeTest.java | 149 ++++++++++-------- 2 files changed, 101 insertions(+), 87 deletions(-) diff --git a/org.springframework.core/src/main/java/org/springframework/util/MediaType.java b/org.springframework.core/src/main/java/org/springframework/util/MediaType.java index dabd4615b3f..a3eef19387c 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/MediaType.java +++ b/org.springframework.core/src/main/java/org/springframework/util/MediaType.java @@ -106,7 +106,7 @@ public final class MediaType implements Comparable { Assert.hasText(subtype, "'subtype' must not be empty"); this.type = type.toLowerCase(Locale.ENGLISH); this.subtype = subtype.toLowerCase(Locale.ENGLISH); - if (parameters != null) { + if (!CollectionUtils.isEmpty(parameters)) { this.parameters = CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(parameters.size()); this.parameters.putAll(parameters); } @@ -124,28 +124,33 @@ public final class MediaType implements Comparable { */ public static MediaType parseMediaType(String mediaType) { Assert.hasLength(mediaType, "'mediaType' must not be empty"); - mediaType = mediaType.trim(); - int subTypeIdx = mediaType.indexOf('/'); - if (subTypeIdx == -1) { - throw new IllegalArgumentException("mediaType " + mediaType + " contains no /"); - } - String type = mediaType.substring(0, subTypeIdx); - String subtype; + String[] parts = StringUtils.tokenizeToStringArray(mediaType, ";"); + Map parameters; - int paramIdx = mediaType.indexOf(';', subTypeIdx + 1); - if (paramIdx == -1) { - subtype = mediaType.substring(subTypeIdx + 1).trim(); + if (parts.length <= 1) { parameters = null; } else { - subtype = mediaType.substring(subTypeIdx + 1, paramIdx).trim(); - String[] tokens = StringUtils.tokenizeToStringArray(mediaType.substring(paramIdx), "; "); - parameters = new LinkedHashMap(tokens.length); - for (String token : tokens) { - int eqPos = token.indexOf('='); - parameters.put(token.substring(0, eqPos), token.substring(eqPos + 1)); + parameters = new LinkedHashMap(parts.length - 1); + } + for (int i = 1; i < parts.length; i++) { + String part = parts[i]; + int idx = part.indexOf('='); + if (idx != -1) { + String name = part.substring(0, idx); + String value = part.substring(idx + 1, part.length()); + parameters.put(name, value); } } + String fullType = parts[0].trim(); + + // java.net.HttpURLConnection returns a *; q=.2 Accept header + if (WILDCARD_TYPE.equals(fullType)) { + fullType = "*/*"; + } + int idx = fullType.indexOf('/'); + String type = fullType.substring(0, idx); + String subtype = fullType.substring(idx + 1, fullType.length()); return new MediaType(type, subtype, parameters); } diff --git a/org.springframework.core/src/test/java/org/springframework/util/MediaTypeTest.java b/org.springframework.core/src/test/java/org/springframework/util/MediaTypeTest.java index b00f947c2f2..3e920b839eb 100644 --- a/org.springframework.core/src/test/java/org/springframework/util/MediaTypeTest.java +++ b/org.springframework.core/src/test/java/org/springframework/util/MediaTypeTest.java @@ -28,85 +28,94 @@ import org.junit.Test; */ public class MediaTypeTest { - @Test - public void includes() throws Exception { - MediaType type1 = new MediaType("text", "plain"); - MediaType type2 = new MediaType("text", "plain"); - assertTrue("Equal types is not inclusive", type1.includes(type2)); - type1 = new MediaType("text"); - assertTrue("All subtypes is not inclusive", type1.includes(type2)); - type1 = MediaType.ALL; - assertTrue("All types is not inclusive", type1.includes(type2)); - } + @Test + public void includes() throws Exception { + MediaType type1 = new MediaType("text", "plain"); + MediaType type2 = new MediaType("text", "plain"); + assertTrue("Equal types is not inclusive", type1.includes(type2)); + type1 = new MediaType("text"); + assertTrue("All subtypes is not inclusive", type1.includes(type2)); + type1 = MediaType.ALL; + assertTrue("All types is not inclusive", type1.includes(type2)); + } - @Test - public void testToString() throws Exception { - MediaType mediaType = new MediaType("text", "plain", Collections.singletonMap("q", "0.7")); - String result = mediaType.toString(); - assertEquals("Invalid toString() returned", "text/plain;q=0.7", result); - } + @Test + public void testToString() throws Exception { + MediaType mediaType = new MediaType("text", "plain", Collections.singletonMap("q", "0.7")); + String result = mediaType.toString(); + assertEquals("Invalid toString() returned", "text/plain;q=0.7", result); + } - @Test - public void parseMediaType() throws Exception { - String s = "audio/*; q=0.2"; - MediaType mediaType = MediaType.parseMediaType(s); - assertEquals("Invalid type", "audio", mediaType.getType()); - assertEquals("Invalid subtype", "*", mediaType.getSubtype()); - assertEquals("Invalid quality factor", 0.2D, mediaType.getQualityValue(), 0D); - } + @Test + public void parseMediaType() throws Exception { + String s = "audio/*; q=0.2"; + MediaType mediaType = MediaType.parseMediaType(s); + assertEquals("Invalid type", "audio", mediaType.getType()); + assertEquals("Invalid subtype", "*", mediaType.getSubtype()); + assertEquals("Invalid quality factor", 0.2D, mediaType.getQualityValue(), 0D); + } - @Test - public void parseMediaTypes() throws Exception { - String s = "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"; - List mediaTypes = MediaType.parseMediaTypes(s); - assertNotNull("No media types returned", mediaTypes); - assertEquals("Invalid amount of media types", 4, mediaTypes.size()); - } + @Test + public void parseURLConnectionMediaType() throws Exception { + String s = "*; q=.2"; + MediaType mediaType = MediaType.parseMediaType(s); + assertEquals("Invalid type", "*", mediaType.getType()); + assertEquals("Invalid subtype", "*", mediaType.getSubtype()); + assertEquals("Invalid quality factor", 0.2D, mediaType.getQualityValue(), 0D); + } - @Test - public void compareTo() throws Exception { - MediaType audioBasic = new MediaType("audio", "basic"); - MediaType audio = new MediaType("audio"); - MediaType audio03 = new MediaType("audio", "*", Collections.singletonMap("q", "0.3")); - MediaType audio07 = new MediaType("audio", "*", Collections.singletonMap("q", "0.7")); - MediaType all = MediaType.ALL; + @Test + public void parseMediaTypes() throws Exception { + String s = "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"; + List mediaTypes = MediaType.parseMediaTypes(s); + assertNotNull("No media types returned", mediaTypes); + assertEquals("Invalid amount of media types", 4, mediaTypes.size()); + } - // equal - assertEquals("Invalid comparison result", 0, audioBasic.compareTo(audioBasic)); - assertEquals("Invalid comparison result", 0, audio.compareTo(audio)); - assertEquals("Invalid comparison result", 0, audio07.compareTo(audio07)); + @Test + public void compareTo() throws Exception { + MediaType audioBasic = new MediaType("audio", "basic"); + MediaType audio = new MediaType("audio"); + MediaType audio03 = new MediaType("audio", "*", Collections.singletonMap("q", "0.3")); + MediaType audio07 = new MediaType("audio", "*", Collections.singletonMap("q", "0.7")); + MediaType all = MediaType.ALL; - // specific to unspecific - assertTrue("Invalid comparison result", audioBasic.compareTo(audio) < 0); - assertTrue("Invalid comparison result", audioBasic.compareTo(all) < 0); - assertTrue("Invalid comparison result", audio.compareTo(all) < 0); + // equal + assertEquals("Invalid comparison result", 0, audioBasic.compareTo(audioBasic)); + assertEquals("Invalid comparison result", 0, audio.compareTo(audio)); + assertEquals("Invalid comparison result", 0, audio07.compareTo(audio07)); - // unspecific to specific - assertTrue("Invalid comparison result", audio.compareTo(audioBasic) > 0); - assertTrue("Invalid comparison result", all.compareTo(audioBasic) > 0); - assertTrue("Invalid comparison result", all.compareTo(audio) > 0); + // specific to unspecific + assertTrue("Invalid comparison result", audioBasic.compareTo(audio) < 0); + assertTrue("Invalid comparison result", audioBasic.compareTo(all) < 0); + assertTrue("Invalid comparison result", audio.compareTo(all) < 0); - // qualifiers - assertTrue("Invalid comparison result", audio.compareTo(audio07) < 0); - assertTrue("Invalid comparison result", audio07.compareTo(audio03) < 0); - assertTrue("Invalid comparison result", audio03.compareTo(all) > 0); + // unspecific to specific + assertTrue("Invalid comparison result", audio.compareTo(audioBasic) > 0); + assertTrue("Invalid comparison result", all.compareTo(audioBasic) > 0); + assertTrue("Invalid comparison result", all.compareTo(audio) > 0); - // sort - List expected = new ArrayList(); - expected.add(audioBasic); - expected.add(audio); - expected.add(all); - expected.add(audio07); - expected.add(audio03); + // qualifiers + assertTrue("Invalid comparison result", audio.compareTo(audio07) < 0); + assertTrue("Invalid comparison result", audio07.compareTo(audio03) < 0); + assertTrue("Invalid comparison result", audio03.compareTo(all) > 0); - List result = new ArrayList(expected); - for (int i = 0; i < 10; i++) { - Collections.shuffle(result); - Collections.sort(result); + // sort + List expected = new ArrayList(); + expected.add(audioBasic); + expected.add(audio); + expected.add(all); + expected.add(audio07); + expected.add(audio03); - for (int j = 0; j < result.size(); j++) { - assertEquals("Invalid media type at " + j, expected.get(j), result.get(j)); - } - } - } + List result = new ArrayList(expected); + for (int i = 0; i < 10; i++) { + Collections.shuffle(result); + Collections.sort(result); + + for (int j = 0; j < result.size(); j++) { + assertEquals("Invalid media type at " + j, expected.get(j), result.get(j)); + } + } + } } \ No newline at end of file