Skip to content

Commit 6f11d4f

Browse files
committed
Backported fix for lower-case media type lookups
Issue: SPR-13747
1 parent f53d01b commit 6f11d4f

File tree

2 files changed

+43
-28
lines changed

2 files changed

+43
-28
lines changed

spring-web/src/main/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolver.java

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,24 +31,28 @@
3131
import org.springframework.util.MultiValueMap;
3232

3333
/**
34-
* An implementation of {@link MediaTypeFileExtensionResolver} that maintains a lookup
35-
* from extension to MediaType.
34+
* An implementation of {@code MediaTypeFileExtensionResolver} that maintains
35+
* lookups between file extensions and MediaTypes in both directions.
36+
*
37+
* <p>Initially created with a map of file extensions and media types.
38+
* Subsequently sub-classes can use {@link #addMapping} to add more mappings.
3639
*
3740
* @author Rossen Stoyanchev
3841
* @since 3.2
3942
*/
4043
public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExtensionResolver {
4144

42-
private final ConcurrentMap<String, MediaType> mediaTypes = new ConcurrentHashMap<String, MediaType>(64);
45+
private final ConcurrentMap<String, MediaType> mediaTypes =
46+
new ConcurrentHashMap<String, MediaType>(64);
4347

44-
private final MultiValueMap<MediaType, String> fileExtensions = new LinkedMultiValueMap<MediaType, String>();
48+
private final MultiValueMap<MediaType, String> fileExtensions =
49+
new LinkedMultiValueMap<MediaType, String>();
4550

4651
private final List<String> allFileExtensions = new LinkedList<String>();
4752

4853

4954
/**
50-
* Create an instance with the given mappings between extensions and media types.
51-
* @throws IllegalArgumentException if a media type string cannot be parsed
55+
* Create an instance with the given map of file extensions and media types.
5256
*/
5357
public MappingMediaTypeFileExtensionResolver(Map<String, MediaType> mediaTypes) {
5458
if (mediaTypes != null) {
@@ -61,10 +65,22 @@ public MappingMediaTypeFileExtensionResolver(Map<String, MediaType> mediaTypes)
6165
}
6266

6367

68+
protected List<MediaType> getAllMediaTypes() {
69+
return new ArrayList<MediaType>(this.mediaTypes.values());
70+
}
71+
6472
/**
65-
* Find the file extensions mapped to the given MediaType.
66-
* @return 0 or more extensions, never {@code null}
73+
* Map an extension to a MediaType. Ignore if extension already mapped.
6774
*/
75+
protected void addMapping(String extension, MediaType mediaType) {
76+
MediaType previous = this.mediaTypes.putIfAbsent(extension, mediaType);
77+
if (previous == null) {
78+
this.fileExtensions.add(mediaType, extension);
79+
this.allFileExtensions.add(extension);
80+
}
81+
}
82+
83+
6884
@Override
6985
public List<String> resolveFileExtensions(MediaType mediaType) {
7086
List<String> fileExtensions = this.fileExtensions.get(mediaType);
@@ -76,27 +92,12 @@ public List<String> getAllFileExtensions() {
7692
return Collections.unmodifiableList(this.allFileExtensions);
7793
}
7894

79-
protected List<MediaType> getAllMediaTypes() {
80-
return new ArrayList<MediaType>(this.mediaTypes.values());
81-
}
82-
8395
/**
84-
* Return the MediaType mapped to the given extension.
85-
* @return a MediaType for the key or {@code null}
96+
* Use this method for a reverse lookup from extension to MediaType.
97+
* @return a MediaType for the key, or {@code null} if none found
8698
*/
8799
protected MediaType lookupMediaType(String extension) {
88-
return this.mediaTypes.get(extension);
89-
}
90-
91-
/**
92-
* Map a MediaType to an extension or ignore if the extensions is already mapped.
93-
*/
94-
protected void addMapping(String extension, MediaType mediaType) {
95-
MediaType previous = this.mediaTypes.putIfAbsent(extension, mediaType);
96-
if (previous == null) {
97-
this.fileExtensions.add(mediaType, extension);
98-
this.allFileExtensions.add(extension);
99-
}
100+
return this.mediaTypes.get(extension.toLowerCase(Locale.ENGLISH));
100101
}
101102

102103
}

spring-web/src/test/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolverTests.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
2929
* Test fixture for {@link MappingMediaTypeFileExtensionResolver}.
3030
*
3131
* @author Rossen Stoyanchev
32+
* @author Melissa Hartsock
3233
*/
3334
public class MappingMediaTypeFileExtensionResolverTests {
3435

@@ -51,4 +52,17 @@ public void resolveExtensionsNoMatch() {
5152
assertTrue(extensions.isEmpty());
5253
}
5354

55+
/**
56+
* Unit test for SPR-13747 - ensures that reverse lookup of media type from media
57+
* type key is case-insensitive.
58+
*/
59+
@Test
60+
public void lookupMediaTypeCaseInsensitive() {
61+
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
62+
MappingMediaTypeFileExtensionResolver resolver = new MappingMediaTypeFileExtensionResolver(mapping);
63+
MediaType mediaType = resolver.lookupMediaType("JSON");
64+
65+
assertEquals(mediaType, MediaType.APPLICATION_JSON);
66+
}
67+
5468
}

0 commit comments

Comments
 (0)