From 9e370208d0a46301c0d26c60d257c20c563e3edc Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 11 May 2012 14:39:31 -0400 Subject: [PATCH] Fix content negotiation issue with sort by q-value Before this fix the q-value of media types in the Accept header were ignored when using the new RequestMappingHandlerAdapter in combination with @ResponseBody and HttpMessageConverters. Issue: SPR-9160 Backport-Issue: SPR-9168 Backport-Commit: 982cb2f258a5be1173115044d379f54702dc8c5b --- .../resources/changelog.txt | 2 + ...stractMessageConverterMethodProcessor.java | 17 +++-- .../view/ContentNegotiatingViewResolver.java | 28 ++++---- ...questResponseBodyMethodProcessorTests.java | 44 +++++++++---- .../ContentNegotiatingViewResolverTests.java | 65 +++++++++++++++---- .../org/springframework/http/MediaType.java | 62 +++++++++++++++--- .../springframework/http/MediaTypeTests.java | 10 +-- 7 files changed, 167 insertions(+), 61 deletions(-) diff --git a/build-spring-framework/resources/changelog.txt b/build-spring-framework/resources/changelog.txt index 952663a5764..9a91eca8b13 100644 --- a/build-spring-framework/resources/changelog.txt +++ b/build-spring-framework/resources/changelog.txt @@ -18,6 +18,8 @@ Changes in version 3.1.2 (2012-06-??) * fix issue with parsing invalid Content-Type or Accept headers * add Jackson 2 HttpMessageConverter and View types * translate IOException from Jackson to HttpMessageNotReadableException +* fix content negotiation issue when sorting selected media types by quality value + Changes in version 3.1.1 (2012-02-16) ------------------------------------- diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java index a47074fcadf..d1aa721bbf1 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -117,7 +116,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe } List mediaTypes = new ArrayList(compatibleMediaTypes); - MediaType.sortBySpecificity(mediaTypes); + MediaType.sortBySpecificityAndQuality(mediaTypes); MediaType selectedMediaType = null; for (MediaType mediaType : mediaTypes) { @@ -131,6 +130,8 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe } } + selectedMediaType = selectedMediaType.removeQualityValue(); + if (selectedMediaType != null) { for (HttpMessageConverter messageConverter : messageConverters) { if (messageConverter.canWrite(returnValueClass, selectedMediaType)) { @@ -188,14 +189,12 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe } /** - * Returns the more specific media type using the q-value of the first media type for both. + * Return the more specific of the acceptable and the producible media types + * with the q-value of the former. */ - private MediaType getMostSpecificMediaType(MediaType type1, MediaType type2) { - double quality = type1.getQualityValue(); - Map params = Collections.singletonMap("q", String.valueOf(quality)); - MediaType t1 = new MediaType(type1, params); - MediaType t2 = new MediaType(type2, params); - return MediaType.SPECIFICITY_COMPARATOR.compare(t1, t2) <= 0 ? type1 : type2; + private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) { + produceType = produceType.copyQualityValue(acceptType); + return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) < 0 ? acceptType : produceType; } } \ No newline at end of file diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java index e304511d269..588489d4716 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -101,6 +101,7 @@ import org.springframework.web.util.WebUtils; * * @author Arjen Poutsma * @author Juergen Hoeller + * @author Rossen Stoyanchev * @since 3.0 * @see ViewResolver * @see InternalResourceViewResolver @@ -117,6 +118,9 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport private static final UrlPathHelper urlPathHelper = new UrlPathHelper(); + static { + urlPathHelper.setUrlDecode(false); + } private int order = Ordered.HIGHEST_PRECEDENCE; @@ -270,7 +274,7 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport String name = viewResolvers.get(i).getClass().getName() + i; getApplicationContext().getAutowireCapableBeanFactory().initializeBean(viewResolvers.get(i), name); } - + } if (this.viewResolvers.isEmpty()) { logger.warn("Did not find any ViewResolvers to delegate to; please configure them using the " + @@ -351,13 +355,13 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport } } } - List mediaTypes = new ArrayList(compatibleMediaTypes); - MediaType.sortByQualityValue(mediaTypes); + List selectedMediaTypes = new ArrayList(compatibleMediaTypes); + MediaType.sortBySpecificityAndQuality(selectedMediaTypes); if (logger.isDebugEnabled()) { - logger.debug("Requested media types are " + mediaTypes + " based on Accept header types " + + logger.debug("Requested media types are " + selectedMediaTypes + " based on Accept header types " + "and producible media types " + producibleMediaTypes + ")"); } - return mediaTypes; + return selectedMediaTypes; } catch (IllegalArgumentException ex) { if (logger.isDebugEnabled()) { @@ -392,14 +396,12 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport } /** - * Returns the more specific media type using the q-value of the first media type for both. + * Return the more specific of the acceptable and the producible media types + * with the q-value of the former. */ - private MediaType getMostSpecificMediaType(MediaType type1, MediaType type2) { - double quality = type1.getQualityValue(); - Map params = Collections.singletonMap("q", String.valueOf(quality)); - MediaType t1 = new MediaType(type1, params); - MediaType t2 = new MediaType(type2, params); - return MediaType.SPECIFICITY_COMPARATOR.compare(t1, t2) <= 0 ? type1 : type2; + private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) { + produceType = produceType.copyQualityValue(acceptType); + return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) < 0 ? acceptType : produceType; } /** 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 a98820751d2..8449f51e5ef 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 @@ -48,25 +48,25 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.HttpMediaTypeNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.ServletWebRequest; -import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor; /** * Test fixture with {@link RequestResponseBodyMethodProcessor} and mock {@link HttpMessageConverter}. - * + * * @author Arjen Poutsma * @author Rossen Stoyanchev */ @@ -100,7 +100,7 @@ public class RequestResponseBodyMethodProcessorTests { processor = new RequestResponseBodyMethodProcessor(Collections.>singletonList(messageConverter)); reset(messageConverter); - + Method handle = getClass().getMethod("handle1", String.class, Integer.TYPE); paramRequestBodyString = new MethodParameter(handle, 0); paramInt = new MethodParameter(handle, 1); @@ -110,7 +110,7 @@ public class RequestResponseBodyMethodProcessorTests { paramValidBean = new MethodParameter(getClass().getMethod("handle4", SimpleBean.class), 0); mavContainer = new ModelAndViewContainer(); - + servletRequest = new MockHttpServletRequest(); servletResponse = new MockHttpServletResponse(); webRequest = new ServletWebRequest(servletRequest, servletResponse); @@ -175,10 +175,10 @@ public class RequestResponseBodyMethodProcessorTests { processor = new RequestResponseBodyMethodProcessor(Collections.>singletonList(beanConverter)); processor.resolveArgument(paramValidBean, mavContainer, webRequest, new ValidatingBinderFactory()); - + verify(beanConverter); } - + @Test(expected = HttpMediaTypeNotSupportedException.class) public void resolveArgumentNotReadable() throws Exception { MediaType contentType = MediaType.TEXT_PLAIN; @@ -248,7 +248,7 @@ public class RequestResponseBodyMethodProcessorTests { fail("Expected exception"); } - + @Test(expected = HttpMediaTypeNotAcceptableException.class) public void handleReturnValueNotAcceptableProduces() throws Exception { MediaType accepted = MediaType.TEXT_PLAIN; @@ -264,19 +264,35 @@ public class RequestResponseBodyMethodProcessorTests { fail("Expected exception"); } + // SPR-9160 + @Test - public void handleStringReturnValue() throws Exception { + public void handleReturnValueSortByQuality() throws Exception { + this.servletRequest.addHeader("Accept", "text/plain; q=0.5, application/json"); + + List> converters = new ArrayList>(); + converters.add(new MappingJackson2HttpMessageConverter()); + converters.add(new StringHttpMessageConverter()); + RequestResponseBodyMethodProcessor handler = new RequestResponseBodyMethodProcessor(converters); + + handler.writeWithMessageConverters("Foo", returnTypeStringProduces, webRequest); + + assertEquals("application/json;charset=UTF-8", servletResponse.getHeader("Content-Type")); + } + + @Test + public void handleReturnValueString() throws Exception { List>converters = new ArrayList>(); converters.add(new ByteArrayHttpMessageConverter()); converters.add(new StringHttpMessageConverter()); - + processor = new RequestResponseBodyMethodProcessor(converters); processor.handleReturnValue("Foo", returnTypeString, mavContainer, webRequest); - + assertEquals("text/plain;charset=ISO-8859-1", servletResponse.getHeader("Content-Type")); assertEquals("Foo", servletResponse.getContentAsString()); } - + @ResponseBody public String handle1(@RequestBody String s, int i) { return s; @@ -293,7 +309,7 @@ public class RequestResponseBodyMethodProcessorTests { public void handle4(@Valid @RequestBody SimpleBean b) { } - + private final class ValidatingBinderFactory implements WebDataBinderFactory { public WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) throws Exception { LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); @@ -318,5 +334,5 @@ public class RequestResponseBodyMethodProcessorTests { return name; } } - + } \ No newline at end of file diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java index 5c3240d8fa8..5d20f59e79c 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -16,6 +16,16 @@ package org.springframework.web.servlet.view; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -28,7 +38,6 @@ import java.util.Set; import org.junit.After; import org.junit.Before; import org.junit.Test; - import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -40,9 +49,6 @@ import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; -import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; - /** * @author Arjen Poutsma */ @@ -100,7 +106,7 @@ public class ContentNegotiatingViewResolverTests { } // SPR-8678 - + @Test public void getMediaTypeFilenameWithContextPath() { request.setContextPath("/project-1.0.0.M3"); @@ -110,6 +116,15 @@ public class ContentNegotiatingViewResolverTests { assertTrue("Context path should be excluded", viewResolver.getMediaTypes(request).isEmpty()); } + // SPR-9390 + + @Test + public void getMediaTypeFilenameWithEncodedURI() { + request.setRequestURI("/quo%20vadis%3f.html"); + List result = viewResolver.getMediaTypes(request); + assertEquals("Invalid content type", Collections.singletonList(new MediaType("text", "html")), result); + } + @Test public void getMediaTypeParameter() { viewResolver.setFavorParameter(true); @@ -139,7 +154,6 @@ public class ContentNegotiatingViewResolverTests { request.setAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, producibleTypes); request.addHeader("Accept", "text/html,application/xml;q=0.9,application/xhtml+xml,*/*;q=0.8"); List result = viewResolver.getMediaTypes(request); - assertEquals("Invalid amount of media types", 1, result.size()); assertEquals("Invalid content type", new MediaType("application", "xhtml+xml"), result.get(0)); } @@ -294,6 +308,35 @@ public class ContentNegotiatingViewResolverTests { verify(viewResolverMock1, viewResolverMock2, viewMock1, viewMock2); } + // SPR-9160 + + @Test + public void resolveViewNameAcceptHeaderSortByQuality() throws Exception { + request.addHeader("Accept", "text/plain;q=0.5, application/json"); + + ViewResolver htmlViewResolver = createMock(ViewResolver.class); + ViewResolver jsonViewResolver = createMock(ViewResolver.class); + viewResolver.setViewResolvers(Arrays.asList(htmlViewResolver, jsonViewResolver)); + + View htmlView = createMock("text_html", View.class); + View jsonViewMock = createMock("application_json", View.class); + + String viewName = "view"; + Locale locale = Locale.ENGLISH; + + expect(htmlViewResolver.resolveViewName(viewName, locale)).andReturn(htmlView); + expect(jsonViewResolver.resolveViewName(viewName, locale)).andReturn(jsonViewMock); + expect(htmlView.getContentType()).andReturn("text/html").anyTimes(); + expect(jsonViewMock.getContentType()).andReturn("application/json").anyTimes(); + replay(htmlViewResolver, jsonViewResolver, htmlView, jsonViewMock); + + viewResolver.setFavorPathExtension(false); + View result = viewResolver.resolveViewName(viewName, locale); + assertSame("Invalid view", jsonViewMock, result); + + verify(htmlViewResolver, jsonViewResolver, htmlView, jsonViewMock); + } + @Test public void resolveViewNameAcceptHeaderDefaultView() throws Exception { request.addHeader("Accept", "application/json"); @@ -426,7 +469,7 @@ public class ContentNegotiatingViewResolverTests { StaticWebApplicationContext webAppContext = new StaticWebApplicationContext(); webAppContext.setServletContext(new MockServletContext()); webAppContext.refresh(); - + UrlBasedViewResolver urlViewResolver = new InternalResourceViewResolver(); urlViewResolver.setApplicationContext(webAppContext); ViewResolver xmlViewResolver = createMock(ViewResolver.class); @@ -435,7 +478,7 @@ public class ContentNegotiatingViewResolverTests { View xmlView = createMock("application_xml", View.class); View jsonView = createMock("application_json", View.class); viewResolver.setDefaultViews(Arrays.asList(jsonView)); - + String viewName = "redirect:anotherTest"; Locale locale = Locale.ENGLISH; @@ -449,7 +492,7 @@ public class ContentNegotiatingViewResolverTests { verify(xmlViewResolver, xmlView, jsonView); } - + @Test public void resolveViewNoMatch() throws Exception { request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9"); @@ -505,7 +548,7 @@ public class ContentNegotiatingViewResolverTests { StaticWebApplicationContext webAppContext = new StaticWebApplicationContext(); webAppContext.setServletContext(new MockServletContext()); webAppContext.refresh(); - + InternalResourceViewResolver nestedResolver = new InternalResourceViewResolver(); nestedResolver.setApplicationContext(webAppContext); nestedResolver.setViewClass(InternalResourceView.class); 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 6d0f75fe4f5..14110404890 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 @@ -33,6 +33,7 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedCaseInsensitiveMap; import org.springframework.util.StringUtils; +import org.springframework.util.comparator.CompoundComparator; /** * Represents an Internet Media Type, as defined in the HTTP specification. @@ -43,6 +44,7 @@ import org.springframework.util.StringUtils; * * @author Arjen Poutsma * @author Juergen Hoeller + * @author Rossen Stoyanchev * @since 3.0 * @see HTTP 1.1, section 3.7 */ @@ -102,7 +104,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code application/xhtml+xml}. * */ public final static MediaType APPLICATION_XHTML_XML; - + /** * A String equivalent of {@link MediaType#APPLICATION_XHTML_XML}. */ @@ -112,7 +114,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code application/xml}. */ public final static MediaType APPLICATION_XML; - + /** * A String equivalent of {@link MediaType#APPLICATION_XML}. */ @@ -122,7 +124,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code image/gif}. */ public final static MediaType IMAGE_GIF; - + /** * A String equivalent of {@link MediaType#IMAGE_GIF}. */ @@ -132,7 +134,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code image/jpeg}. */ public final static MediaType IMAGE_JPEG; - + /** * A String equivalent of {@link MediaType#IMAGE_JPEG}. */ @@ -142,7 +144,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code image/png}. */ public final static MediaType IMAGE_PNG; - + /** * A String equivalent of {@link MediaType#IMAGE_PNG}. */ @@ -152,7 +154,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code multipart/form-data}. * */ public final static MediaType MULTIPART_FORM_DATA; - + /** * A String equivalent of {@link MediaType#MULTIPART_FORM_DATA}. */ @@ -162,7 +164,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code text/html}. * */ public final static MediaType TEXT_HTML; - + /** * A String equivalent of {@link MediaType#TEXT_HTML}. */ @@ -172,7 +174,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code text/plain}. * */ public final static MediaType TEXT_PLAIN; - + /** * A String equivalent of {@link MediaType#TEXT_PLAIN}. */ @@ -182,7 +184,7 @@ public class MediaType implements Comparable { * Public constant media type for {@code text/xml}. * */ public final static MediaType TEXT_XML; - + /** * A String equivalent of {@link MediaType#TEXT_XML}. */ @@ -529,6 +531,32 @@ public class MediaType implements Comparable { return false; } + /** + * Return a replica of this instance with the quality value of the given MediaType. + * @return the same instance if the given MediaType doesn't have a quality value, or a new one otherwise + */ + public MediaType copyQualityValue(MediaType mediaType) { + if (!mediaType.parameters.containsKey(PARAM_QUALITY_FACTOR)) { + return this; + } + Map params = new LinkedHashMap(this.parameters); + params.put(PARAM_QUALITY_FACTOR, mediaType.parameters.get(PARAM_QUALITY_FACTOR)); + return new MediaType(this, params); + } + + /** + * Return a replica of this instance with its quality value removed. + * @return the same instance if the media type doesn't contain a quality value, or a new one otherwise + */ + public MediaType removeQualityValue() { + if (!this.parameters.containsKey(PARAM_QUALITY_FACTOR)) { + return this; + } + Map params = new LinkedHashMap(this.parameters); + params.remove(PARAM_QUALITY_FACTOR); + return new MediaType(this, params); + } + /** * Compares this {@code MediaType} to another alphabetically. * @param other media type to compare to @@ -772,6 +800,22 @@ public class MediaType implements Comparable { } } + /** + * Sorts the given list of {@code MediaType} objects by specificity as the + * primary criteria and quality value the secondary. + * @see MediaType#sortBySpecificity(List) + * @see MediaType#sortByQualityValue(List) + */ + public static void sortBySpecificityAndQuality(List mediaTypes) { + Assert.notNull(mediaTypes, "'mediaTypes' must not be null"); + if (mediaTypes.size() > 1) { + Comparator[] comparators = new Comparator[2]; + comparators[0] = MediaType.SPECIFICITY_COMPARATOR; + comparators[1] = MediaType.QUALITY_VALUE_COMPARATOR; + Collections.sort(mediaTypes, new CompoundComparator(comparators)); + } + } + /** * Comparator used by {@link #sortBySpecificity(List)}. 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 5ed742a0eb2..2e290d0a814 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -60,7 +60,7 @@ public class MediaTypeTests { assertTrue(applicationWildcardXml.includes(applicationSoapXml)); assertFalse(applicationSoapXml.includes(applicationWildcardXml)); } - + @Test public void isCompatible() throws Exception { MediaType textPlain = MediaType.TEXT_PLAIN; @@ -102,7 +102,7 @@ public class MediaTypeTests { public void slashInSubtype() { new MediaType("text", "/"); } - + @Test public void getDefaultQualityValue() { MediaType mediaType = new MediaType("text", "plain"); @@ -477,7 +477,7 @@ public class MediaTypeTests { } } } - + @Test public void sortByQualityUnrelated() { MediaType audioBasic = new MediaType("audio", "basic"); @@ -504,7 +504,7 @@ public class MediaTypeTests { MediaType mediaType = MediaType.parseMediaType("application/xml"); assertEquals(mediaType, conversionService.convert("application/xml", MediaType.class)); } - + @Test public void isConcrete() { assertTrue("text/plain not concrete", MediaType.TEXT_PLAIN.isConcrete());