diff --git a/spring-web/src/main/java/org/springframework/http/InvalidMediaTypeException.java b/spring-web/src/main/java/org/springframework/http/InvalidMediaTypeException.java new file mode 100644 index 0000000000..358c9c8226 --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/InvalidMediaTypeException.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2013 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.http; + +/** + * Exception thrown from {@link MediaType#parseMediaType(String)} in case of + * encountering an invalid media type specification String. + * + * @author Juergen Hoeller + * @since 3.2.2 + */ +@SuppressWarnings("serial") +public class InvalidMediaTypeException extends IllegalArgumentException { + + private String mediaType; + + + /** + * Create a new InvalidMediaTypeException for the given media type. + * @param mediaType the offending media type + * @param msg a detail message indicating the invalid part + */ + public InvalidMediaTypeException(String mediaType, String msg) { + super("Invalid media type \"" + mediaType + "\": " + msg); + this.mediaType = mediaType; + + } + + + /** + * Return the offending media type. + */ + public String getMediaType() { + return this.mediaType; + } + +} diff --git a/spring-web/src/main/java/org/springframework/http/MediaType.java b/spring-web/src/main/java/org/springframework/http/MediaType.java index 99e1b2d124..9f527c7c8c 100644 --- a/spring-web/src/main/java/org/springframework/http/MediaType.java +++ b/spring-web/src/main/java/org/springframework/http/MediaType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -17,6 +17,7 @@ package org.springframework.http; import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; @@ -321,8 +322,8 @@ public class MediaType implements Comparable { * @throws IllegalArgumentException if any of the parameters contain illegal characters */ public MediaType(String type, String subtype, Map parameters) { - Assert.hasLength(type, "'type' must not be empty"); - Assert.hasLength(subtype, "'subtype' must not be empty"); + Assert.hasLength(type, "type must not be empty"); + Assert.hasLength(subtype, "subtype must not be empty"); checkToken(type); checkToken(subtype); this.type = type.toLowerCase(Locale.ENGLISH); @@ -347,11 +348,11 @@ public class MediaType implements Comparable { * @throws IllegalArgumentException in case of illegal characters * @see HTTP 1.1, section 2.2 */ - private void checkToken(String s) { - for (int i=0; i < s.length(); i++ ) { - char ch = s.charAt(i); + private void checkToken(String token) { + for (int i=0; i < token.length(); i++ ) { + char ch = token.charAt(i); if (!TOKEN.get(ch)) { - throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + s + "\""); + throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + token + "\""); } } } @@ -681,7 +682,7 @@ public class MediaType implements Comparable { * Parse the given String into a single {@code MediaType}. * @param mediaType the string to parse * @return the media type - * @throws IllegalArgumentException if the string cannot be parsed + * @throws InvalidMediaTypeException if the string cannot be parsed */ public static MediaType parseMediaType(String mediaType) { Assert.hasLength(mediaType, "'mediaType' must not be empty"); @@ -694,15 +695,15 @@ public class MediaType implements Comparable { } int subIndex = fullType.indexOf('/'); if (subIndex == -1) { - throw new IllegalArgumentException("\"" + mediaType + "\" does not contain '/'"); + throw new InvalidMediaTypeException(mediaType, "does not contain '/'"); } if (subIndex == fullType.length() - 1) { - throw new IllegalArgumentException("\"" + mediaType + "\" does not contain subtype after '/'"); + throw new InvalidMediaTypeException(mediaType, "does not contain subtype after '/'"); } String type = fullType.substring(0, subIndex); String subtype = fullType.substring(subIndex + 1, fullType.length()); if (WILDCARD_TYPE.equals(type) && !WILDCARD_TYPE.equals(subtype)) { - throw new IllegalArgumentException("A wildcard type is legal only in '*/*' (all media types)."); + throw new InvalidMediaTypeException(mediaType, "wildcard type is legal only in '*/*' (all media types)"); } Map parameters = null; @@ -719,7 +720,15 @@ public class MediaType implements Comparable { } } - return new MediaType(type, subtype, parameters); + try { + return new MediaType(type, subtype, parameters); + } + catch (UnsupportedCharsetException ex) { + throw new InvalidMediaTypeException(mediaType, "unsupported charset '" + ex.getCharsetName() + "'"); + } + catch (IllegalArgumentException ex) { + throw new InvalidMediaTypeException(mediaType, ex.getMessage()); + } } diff --git a/spring-web/src/test/java/org/springframework/http/MediaTypeTests.java b/spring-web/src/test/java/org/springframework/http/MediaTypeTests.java index 906c8dec58..d5657d199e 100644 --- a/spring-web/src/test/java/org/springframework/http/MediaTypeTests.java +++ b/spring-web/src/test/java/org/springframework/http/MediaTypeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -97,12 +97,12 @@ public class MediaTypeTests { assertEquals("Invalid toString() returned", "text/plain;q=0.7", result); } - @Test(expected= IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void slashInType() { new MediaType("text/plain"); } - @Test(expected= IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void slashInSubtype() { new MediaType("text", "/"); } @@ -122,57 +122,57 @@ public class MediaTypeTests { assertEquals("Invalid quality factor", 0.2D, mediaType.getQualityValue(), 0D); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeNoSubtype() { MediaType.parseMediaType("audio"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeNoSubtypeSlash() { MediaType.parseMediaType("audio/"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeTypeRange() { MediaType.parseMediaType("*/json"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalType() { MediaType.parseMediaType("audio(/basic"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalSubtype() { MediaType.parseMediaType("audio/basic)"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeEmptyParameterAttribute() { MediaType.parseMediaType("audio/*;=value"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeEmptyParameterValue() { MediaType.parseMediaType("audio/*;attr="); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalParameterAttribute() { MediaType.parseMediaType("audio/*;attr<=value"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalParameterValue() { MediaType.parseMediaType("audio/*;attr=v>alue"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalQualityFactor() { MediaType.parseMediaType("audio/basic;q=1.1"); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalCharset() { MediaType.parseMediaType("text/html; charset=foo-bar"); } @@ -193,7 +193,7 @@ public class MediaTypeTests { assertEquals("'v>alue'", mediaType.getParameter("attr")); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = InvalidMediaTypeException.class) public void parseMediaTypeIllegalQuotedParameterValue() { MediaType.parseMediaType("audio/*;attr=\""); }