From 01d8d642007e74e8c9aebcd6ea2934df2b06b1b2 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Sat, 6 Oct 2012 10:20:14 -0400 Subject: [PATCH] Recognize wildcards in media types with a suffix The "includes" and "isCompatibleWith" methods of MediaType take into account media types with suffices (e.g. application/soap+xml) including wildcards with suffices (e.g. application/*+xml). However before this change, the isWildcardSubtype() method returned true only for subtype "*". Now a media type such as application/*+xml is also recognized as having a wildcard subtype. Issue: SPR-9841 --- ...questResponseBodyMethodProcessorTests.java | 22 +++++++++++++++++++ .../org/springframework/http/MediaType.java | 5 +++-- .../springframework/http/MediaTypeTests.java | 6 +++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java index 8449f51e5e..bca0175866 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java @@ -264,6 +264,28 @@ public class RequestResponseBodyMethodProcessorTests { fail("Expected exception"); } + // SPR-9841 + + @Test + public void handleReturnValueMediaTypeSuffix() throws Exception { + String body = "Foo"; + MediaType accepted = MediaType.APPLICATION_XHTML_XML; + List supported = Collections.singletonList(MediaType.valueOf("application/*+xml")); + + servletRequest.addHeader("Accept", accepted); + + expect(messageConverter.canWrite(String.class, null)).andReturn(true); + expect(messageConverter.getSupportedMediaTypes()).andReturn(supported); + expect(messageConverter.canWrite(String.class, accepted)).andReturn(true); + messageConverter.write(eq(body), eq(accepted), isA(HttpOutputMessage.class)); + replay(messageConverter); + + processor.handleReturnValue(body, returnTypeStringProduces, mavContainer, webRequest); + + assertTrue(mavContainer.isRequestHandled()); + verify(messageConverter); + } + // SPR-9160 @Test 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 4cc037b8c6..3164daedb0 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 @@ -413,11 +413,12 @@ public class MediaType implements Comparable { } /** - * Indicates whether the {@linkplain #getSubtype() subtype} is the wildcard character * or not. + * Indicates whether the {@linkplain #getSubtype() subtype} is the wildcard character * + * or the wildcard character followed by a sufiix (e.g. *+xml), or not. * @return whether the subtype is * */ public boolean isWildcardSubtype() { - return WILDCARD_TYPE.equals(subtype); + return WILDCARD_TYPE.equals(subtype) || subtype.startsWith("*+"); } /** 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 d54768ef6f..cbaaae7aa2 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 @@ -313,6 +313,7 @@ public class MediaTypeTests { MediaType audio07 = new MediaType("audio", "*", 0.7); MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1")); MediaType textHtml = new MediaType("text", "html"); + MediaType allXml = new MediaType("application", "*+xml"); MediaType all = MediaType.ALL; Comparator comp = MediaType.SPECIFICITY_COMPARATOR; @@ -328,9 +329,11 @@ public class MediaTypeTests { assertTrue("Invalid comparison result", comp.compare(audioBasic, audio) < 0); assertTrue("Invalid comparison result", comp.compare(audioBasic, all) < 0); assertTrue("Invalid comparison result", comp.compare(audio, all) < 0); + assertTrue("Invalid comparison result", comp.compare(MediaType.APPLICATION_XHTML_XML, allXml) < 0); // unspecific to specific assertTrue("Invalid comparison result", comp.compare(audio, audioBasic) > 0); + assertTrue("Invalid comparison result", comp.compare(allXml, MediaType.APPLICATION_XHTML_XML) > 0); assertTrue("Invalid comparison result", comp.compare(all, audioBasic) > 0); assertTrue("Invalid comparison result", comp.compare(all, audio) > 0); @@ -414,6 +417,7 @@ public class MediaTypeTests { MediaType audio07 = new MediaType("audio", "*", 0.7); MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1")); MediaType textHtml = new MediaType("text", "html"); + MediaType allXml = new MediaType("application", "*+xml"); MediaType all = MediaType.ALL; Comparator comp = MediaType.QUALITY_VALUE_COMPARATOR; @@ -429,11 +433,13 @@ public class MediaTypeTests { assertTrue("Invalid comparison result", comp.compare(audioBasic, audio) < 0); assertTrue("Invalid comparison result", comp.compare(audioBasic, all) < 0); assertTrue("Invalid comparison result", comp.compare(audio, all) < 0); + assertTrue("Invalid comparison result", comp.compare(MediaType.APPLICATION_XHTML_XML, allXml) < 0); // unspecific to specific assertTrue("Invalid comparison result", comp.compare(audio, audioBasic) > 0); assertTrue("Invalid comparison result", comp.compare(all, audioBasic) > 0); assertTrue("Invalid comparison result", comp.compare(all, audio) > 0); + assertTrue("Invalid comparison result", comp.compare(allXml, MediaType.APPLICATION_XHTML_XML) > 0); // qualifiers assertTrue("Invalid comparison result", comp.compare(audio, audio07) < 0);