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 98746dbe93d..eba7faf97b1 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 @@ -34,14 +34,14 @@ import org.springframework.util.StringUtils; /** * Represents an Internet Media Type, as defined in the HTTP specification. * - *

Consists of a {@linkplain #getType() type} and a {@linkplain #getSubtype() subtype}. - * Also has functionality to parse media types from a string using {@link #parseMediaType(String)}, - * or multiple comma-separated media types using {@link #parseMediaTypes(String)}. + *

Consists of a {@linkplain #getType() type} and a {@linkplain #getSubtype() subtype}. Also has functionality to + * parse media types from a string using {@link #parseMediaType(String)}, or multiple comma-separated media types using + * {@link #parseMediaTypes(String)}. * * @author Arjen Poutsma * @author Juergen Hoeller - * @since 3.0 * @see HTTP 1.1 + * @since 3.0 */ public class MediaType implements Comparable { @@ -53,17 +53,16 @@ public class MediaType implements Comparable { private static final String PARAM_CHARSET = "charset"; - private final String type; private final String subtype; private final Map parameters; - /** - * Create a new {@link MediaType} for the given primary type. - *

The {@linkplain #getSubtype() subtype} is set to *, parameters empty. + * Create a new {@link MediaType} for the given primary type.

The {@linkplain #getSubtype() subtype} is set to + * *, parameters empty. + * * @param type the primary type */ public MediaType(String type) { @@ -71,8 +70,8 @@ public class MediaType implements Comparable { } /** - * Create a new {@link MediaType} for the given primary type and subtype. - *

The parameters are empty. + * Create a new {@link MediaType} for the given primary type and subtype.

The parameters are empty. + * * @param type the primary type * @param subtype the subtype */ @@ -82,6 +81,7 @@ public class MediaType implements Comparable { /** * Create a new {@link MediaType} for the given type, subtype, and character set. + * * @param type the primary type * @param subtype the subtype * @param charSet the character set @@ -92,6 +92,7 @@ public class MediaType implements Comparable { /** * Create a new {@link MediaType} for the given type, subtype, and parameters. + * * @param type the primary type * @param subtype the subtype * @param parameters the parameters, mat be null @@ -110,30 +111,24 @@ public class MediaType implements Comparable { } } - - /** - * Return the primary type. - */ + /** Return the primary type. */ public String getType() { return this.type; } - /** - * Indicate whether the {@linkplain #getType() type} is the wildcard character * or not. - */ + /** Indicate whether the {@linkplain #getType() type} is the wildcard character * or not. */ public boolean isWildcardType() { return WILDCARD_TYPE.equals(type); } - /** - * Return the subtype. - */ + /** Return the subtype. */ public String getSubtype() { return this.subtype; } /** * Indicate whether the {@linkplain #getSubtype() subtype} is the wildcard character * or not. + * * @return whether the subtype is * */ public boolean isWildcardSubtype() { @@ -142,6 +137,7 @@ public class MediaType implements Comparable { /** * Return the character set, as indicated by a charset parameter, if any. + * * @return the character set; or null if not available */ public Charset getCharSet() { @@ -151,6 +147,7 @@ public class MediaType implements Comparable { /** * Return the quality value, as indicated by a q parameter, if any. Defaults to 1.0. + * * @return the quality factory */ public double getQualityValue() { @@ -160,6 +157,7 @@ public class MediaType implements Comparable { /** * Return a generic parameter value, given a parameter name. + * * @param name the parameter name * @return the parameter value; or null if not present */ @@ -167,11 +165,10 @@ public class MediaType implements Comparable { return this.parameters.get(name); } - /** - * Indicate whether this {@link MediaType} includes the given media type. - *

For instance, text/* includes text/plain, - * text/html, etc. + * Indicate whether this {@link MediaType} includes the given media type.

For instance, {@code text/*} includes + * {@code text/plain}, {@code text/html}, and {@code application/*+xml} includes {@code application/soap+xml}, etc. + * * @param other the reference media type with which to compare * @return true if this media type includes the given media type; false otherwise */ @@ -183,6 +180,18 @@ public class MediaType implements Comparable { if (this.subtype.equals(other.subtype) || isWildcardSubtype()) { return true; } + // application/*+xml includes application/soap+xml + int thisPlusIdx = this.subtype.indexOf('+'); + int otherPlusIdx = other.subtype.indexOf('+'); + if (thisPlusIdx != -1 && otherPlusIdx != -1) { + String thisSubtypeNoSuffix = this.subtype.substring(0, thisPlusIdx); + + String thisSubtypeSuffix = this.subtype.substring(thisPlusIdx + 1); + String otherSubtypeSuffix = other.subtype.substring(otherPlusIdx + 1); + if (thisSubtypeSuffix.equals(otherSubtypeSuffix) && WILDCARD_TYPE.equals(thisSubtypeNoSuffix)) { + return true; + } + } } return isWildcardType(); } @@ -192,9 +201,10 @@ public class MediaType implements Comparable { * audio/basic < audio/* < */* . That is, an explicit media type is sorted before an unspecific * media type. Quality parameters are also considered, so that

audio/* < audio/*;q=0.7; * audio/*;q=0.3
. + * * @param other the media type to compare to - * @return a negative integer, zero, or a positive integer as this media type is less than, equal to, - * or greater than the specified media type + * @return a negative integer, zero, or a positive integer as this media type is less than, equal to, or greater than + * the specified media type */ public int compareTo(MediaType other) { double qVal1 = this.getQualityValue(); @@ -263,7 +273,7 @@ public class MediaType implements Comparable { builder.append(this.type); builder.append('/'); builder.append(this.subtype); - for (Map.Entry entry :this. parameters.entrySet()) { + for (Map.Entry entry : this.parameters.entrySet()) { builder.append(';'); builder.append(entry.getKey()); builder.append('='); @@ -271,9 +281,9 @@ public class MediaType implements Comparable { } } - /** * Parse the given String into a single {@link MediaType}. + * * @param mediaType the string to parse * @return the media type * @throws IllegalArgumentException if the string cannot be parsed @@ -309,8 +319,9 @@ public class MediaType implements Comparable { } /** - * Parse the given, comma-seperated string into a list of {@link MediaType} objects. - *

This method can be used to parse an Accept or Content-Type header. + * Parse the given, comma-seperated string into a list of {@link MediaType} objects.

This method can be used to + * parse an Accept or Content-Type header. + * * @param mediaTypes the string to parse * @return the list of media types * @throws IllegalArgumentException if the string cannot be parsed @@ -328,8 +339,9 @@ public class MediaType implements Comparable { } /** - * Return a string representation of the given list of {@link MediaType} objects. - *

This method can be used to for an Accept or Content-Type header. + * Return a string representation of the given list of {@link MediaType} objects.

This method can be used to for an + * Accept or Content-Type header. + * * @param mediaTypes the string to parse * @return the list of media types * @throws IllegalArgumentException if the String cannot be parsed 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 355667eee6f..01566219677 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 @@ -16,28 +16,35 @@ package org.springframework.http; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.nio.charset.Charset; import static org.junit.Assert.*; import org.junit.Test; -/** - * @author Arjen Poutsma - */ +/** @author Arjen Poutsma */ public class MediaTypeTests { @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)); + MediaType textPlain = new MediaType("text", "plain"); + assertTrue("Equal types is not inclusive", textPlain.includes(textPlain)); + MediaType allText = new MediaType("text"); + assertTrue("All subtypes is not inclusive", allText.includes(textPlain)); + assertFalse("All subtypes is not inclusive", textPlain.includes(allText)); + assertTrue("All types is not inclusive", MediaType.ALL.includes(textPlain)); + assertFalse("All types is not inclusive", textPlain.includes(MediaType.ALL)); + + MediaType applicationSoapXml = new MediaType("application", "soap+xml"); + MediaType applicationWildcardXml = new MediaType("application", "*+xml"); + + assertTrue(applicationSoapXml.includes(applicationSoapXml)); + assertTrue(applicationWildcardXml.includes(applicationWildcardXml)); + + assertTrue(applicationWildcardXml.includes(applicationSoapXml)); + assertFalse(applicationSoapXml.includes(applicationWildcardXml)); } @Test