11/*
2- * Copyright 2002-2016 the original author or authors.
2+ * Copyright 2002-2017 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.
1616
1717package org .springframework .http ;
1818
19+ import java .io .BufferedReader ;
1920import java .io .IOException ;
2021import java .io .InputStream ;
21- import javax .activation .FileTypeMap ;
22- import javax .activation .MimetypesFileTypeMap ;
22+ import java .io .InputStreamReader ;
23+ import java .nio .charset .StandardCharsets ;
24+ import java .util .Collections ;
25+ import java .util .List ;
26+ import java .util .Locale ;
27+ import java .util .Optional ;
2328
24- import org .springframework .core .io .ClassPathResource ;
2529import org .springframework .core .io .Resource ;
30+ import org .springframework .util .LinkedMultiValueMap ;
31+ import org .springframework .util .MultiValueMap ;
2632import org .springframework .util .StringUtils ;
2733
2834/**
2935 * A factory delegate for resolving {@link MediaType} objects
3036 * from {@link Resource} handles or filenames.
3137 *
32- * <p>This implementation is based on the Java Activation Framework,
33- * sharing the MIME type definitions with Spring's JavaMail support.
34- * However, JAF is an implementation detail and not leaking out.
35- *
3638 * @author Juergen Hoeller
39+ * @author Arjen Poutsma
3740 * @since 5.0
3841 */
3942public class MediaTypeFactory {
4043
41- private static final FileTypeMap fileTypeMap ;
44+ private static final String MIME_TYPES_FILE_NAME = "/org/springframework/http/mime.types" ;
45+
46+ private static final MultiValueMap <String , MediaType > fileExtensionToMediaTypes ;
4247
4348 static {
44- fileTypeMap = loadFileTypeMapFromContextSupportModule ();
49+ fileExtensionToMediaTypes = parseMimeTypes ();
4550 }
4651
52+ /**
53+ * Parse the {@code mime.types} file found in the resources. Format is:
54+ * <code>
55+ * # comments begin with a '#'<br>
56+ * # the format is <mime type> <space separated file extensions><br>
57+ * # for example:<br>
58+ * text/plain txt text<br>
59+ * # this would map file.txt and file.text to<br>
60+ * # the mime type "text/plain"<br>
61+ * </code>
62+ * @return a multi-value map, mapping media types to file extensions.
63+ */
64+ private static MultiValueMap <String , MediaType > parseMimeTypes () {
65+ InputStream is = null ;
66+ try {
67+ is = MediaTypeFactory .class .getResourceAsStream (MIME_TYPES_FILE_NAME );
68+ BufferedReader reader =
69+ new BufferedReader (new InputStreamReader (is , StandardCharsets .US_ASCII ));
4770
48- private static FileTypeMap loadFileTypeMapFromContextSupportModule () {
49- // See if we can find the extended mime.types from the context-support module...
50- Resource mappingLocation = new ClassPathResource ("org/springframework/mail/javamail/mime.types" );
51- if (mappingLocation .exists ()) {
52- InputStream inputStream = null ;
53- try {
54- inputStream = mappingLocation .getInputStream ();
55- return new MimetypesFileTypeMap (inputStream );
56- }
57- catch (IOException ex ) {
58- // ignore
71+ MultiValueMap <String , MediaType > result = new LinkedMultiValueMap <>();
72+ String line ;
73+ while ((line = reader .readLine ()) != null ) {
74+ if (line .isEmpty () || line .charAt (0 ) == '#' ) {
75+ continue ;
76+ }
77+ String [] tokens = StringUtils .tokenizeToStringArray (line , " \t \n \r \f " );
78+ MediaType mediaType = MediaType .parseMediaType (tokens [0 ]);
79+
80+ for (int i = 1 ; i < tokens .length ; i ++) {
81+ String fileExtension = tokens [i ].toLowerCase (Locale .ENGLISH );
82+ result .add (fileExtension , mediaType );
83+ }
5984 }
60- finally {
61- if (inputStream != null ) {
62- try {
63- inputStream .close ();
64- }
65- catch (IOException ex ) {
66- // ignore
67- }
85+ return result ;
86+ }
87+ catch (IOException ex ) {
88+ throw new IllegalStateException ("Could not load '" + MIME_TYPES_FILE_NAME + "'" , ex );
89+ }
90+ finally {
91+ if (is != null ) {
92+ try {
93+ is .close ();
94+ }
95+ catch (IOException ignore ) {
6896 }
6997 }
7098 }
71- return FileTypeMap .getDefaultFileTypeMap ();
7299 }
73100
74-
75101 /**
76102 * Determine a media type for the given resource, if possible.
77103 * @param resource the resource to introspect
@@ -88,8 +114,20 @@ public static MediaType getMediaType(Resource resource) {
88114 * @return the corresponding media type, or {@code null} if none found
89115 */
90116 public static MediaType getMediaType (String filename ) {
91- String mediaType = fileTypeMap .getContentType (filename );
92- return (StringUtils .hasText (mediaType ) ? MediaType .parseMediaType (mediaType ) : null );
117+ List <MediaType > mediaTypes = getMediaTypes (filename );
118+ return (!mediaTypes .isEmpty () ? mediaTypes .get (0 ) : null );
119+ }
120+
121+ /**
122+ * Determine the media types for the given file name, if possible.
123+ * @param filename the file name plus extension
124+ * @return the corresponding media types, or an empty list if none found
125+ */
126+ public static List <MediaType > getMediaTypes (String filename ) {
127+ return Optional .ofNullable (StringUtils .getFilenameExtension (filename ))
128+ .map (s -> s .toLowerCase (Locale .ENGLISH ))
129+ .map (fileExtensionToMediaTypes ::get )
130+ .orElse (Collections .emptyList ());
93131 }
94132
95133}
0 commit comments