diff --git a/spring-web/src/main/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolver.java b/spring-web/src/main/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolver.java index 3fee1520815..7acd788dd5f 100644 --- a/spring-web/src/main/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolver.java +++ b/spring-web/src/main/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -31,24 +31,28 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** - * An implementation of {@link MediaTypeFileExtensionResolver} that maintains a lookup - * from extension to MediaType. + * An implementation of {@code MediaTypeFileExtensionResolver} that maintains + * lookups between file extensions and MediaTypes in both directions. + * + *

Initially created with a map of file extensions and media types. + * Subsequently sub-classes can use {@link #addMapping} to add more mappings. * * @author Rossen Stoyanchev * @since 3.2 */ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExtensionResolver { - private final ConcurrentMap mediaTypes = new ConcurrentHashMap(64); + private final ConcurrentMap mediaTypes = + new ConcurrentHashMap(64); - private final MultiValueMap fileExtensions = new LinkedMultiValueMap(); + private final MultiValueMap fileExtensions = + new LinkedMultiValueMap(); private final List allFileExtensions = new LinkedList(); /** - * Create an instance with the given mappings between extensions and media types. - * @throws IllegalArgumentException if a media type string cannot be parsed + * Create an instance with the given map of file extensions and media types. */ public MappingMediaTypeFileExtensionResolver(Map mediaTypes) { if (mediaTypes != null) { @@ -61,10 +65,22 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten } + protected List getAllMediaTypes() { + return new ArrayList(this.mediaTypes.values()); + } + /** - * Find the file extensions mapped to the given MediaType. - * @return 0 or more extensions, never {@code null} + * Map an extension to a MediaType. Ignore if extension already mapped. */ + protected void addMapping(String extension, MediaType mediaType) { + MediaType previous = this.mediaTypes.putIfAbsent(extension, mediaType); + if (previous == null) { + this.fileExtensions.add(mediaType, extension); + this.allFileExtensions.add(extension); + } + } + + @Override public List resolveFileExtensions(MediaType mediaType) { List fileExtensions = this.fileExtensions.get(mediaType); @@ -76,27 +92,12 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten return Collections.unmodifiableList(this.allFileExtensions); } - protected List getAllMediaTypes() { - return new ArrayList(this.mediaTypes.values()); - } - /** - * Return the MediaType mapped to the given extension. - * @return a MediaType for the key or {@code null} + * Use this method for a reverse lookup from extension to MediaType. + * @return a MediaType for the key, or {@code null} if none found */ protected MediaType lookupMediaType(String extension) { - return this.mediaTypes.get(extension); - } - - /** - * Map a MediaType to an extension or ignore if the extensions is already mapped. - */ - protected void addMapping(String extension, MediaType mediaType) { - MediaType previous = this.mediaTypes.putIfAbsent(extension, mediaType); - if (previous == null) { - this.fileExtensions.add(mediaType, extension); - this.allFileExtensions.add(extension); - } + return this.mediaTypes.get(extension.toLowerCase(Locale.ENGLISH)); } } diff --git a/spring-web/src/test/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolverTests.java b/spring-web/src/test/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolverTests.java index 4ea37728431..3bf9087e718 100644 --- a/spring-web/src/test/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -29,6 +29,7 @@ import static org.junit.Assert.*; * Test fixture for {@link MappingMediaTypeFileExtensionResolver}. * * @author Rossen Stoyanchev + * @author Melissa Hartsock */ public class MappingMediaTypeFileExtensionResolverTests { @@ -51,4 +52,17 @@ public class MappingMediaTypeFileExtensionResolverTests { assertTrue(extensions.isEmpty()); } + /** + * Unit test for SPR-13747 - ensures that reverse lookup of media type from media + * type key is case-insensitive. + */ + @Test + public void lookupMediaTypeCaseInsensitive() { + Map mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON); + MappingMediaTypeFileExtensionResolver resolver = new MappingMediaTypeFileExtensionResolver(mapping); + MediaType mediaType = resolver.lookupMediaType("JSON"); + + assertEquals(mediaType, MediaType.APPLICATION_JSON); + } + }