1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.util;
18
19 import java.nio.charset.UnsupportedCharsetException;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.Iterator;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.springframework.util.MimeType.SpecificityComparator;
30
31
32
33
34
35
36
37
38 public abstract class MimeTypeUtils {
39
40
41
42
43 public static final MimeType ALL;
44
45
46
47
48 public static final String ALL_VALUE = "*/*";
49
50
51
52
53 public final static MimeType APPLICATION_ATOM_XML;
54
55
56
57
58 public final static String APPLICATION_ATOM_XML_VALUE = "application/atom+xml";
59
60
61
62
63 public final static MimeType APPLICATION_FORM_URLENCODED;
64
65
66
67
68 public final static String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded";
69
70
71
72
73 public final static MimeType APPLICATION_JSON;
74
75
76
77
78 public final static String APPLICATION_JSON_VALUE = "application/json";
79
80
81
82
83 public final static MimeType APPLICATION_OCTET_STREAM;
84
85
86
87
88 public final static String APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream";
89
90
91
92
93 public final static MimeType APPLICATION_XHTML_XML;
94
95
96
97
98 public final static String APPLICATION_XHTML_XML_VALUE = "application/xhtml+xml";
99
100
101
102
103 public final static MimeType APPLICATION_XML;
104
105
106
107
108 public final static String APPLICATION_XML_VALUE = "application/xml";
109
110
111
112
113 public final static MimeType IMAGE_GIF;
114
115
116
117
118 public final static String IMAGE_GIF_VALUE = "image/gif";
119
120
121
122
123 public final static MimeType IMAGE_JPEG;
124
125
126
127
128 public final static String IMAGE_JPEG_VALUE = "image/jpeg";
129
130
131
132
133 public final static MimeType IMAGE_PNG;
134
135
136
137
138 public final static String IMAGE_PNG_VALUE = "image/png";
139
140
141
142
143 public final static MimeType MULTIPART_FORM_DATA;
144
145
146
147
148 public final static String MULTIPART_FORM_DATA_VALUE = "multipart/form-data";
149
150
151
152
153 public final static MimeType TEXT_HTML;
154
155
156
157
158 public final static String TEXT_HTML_VALUE = "text/html";
159
160
161
162
163 public final static MimeType TEXT_PLAIN;
164
165
166
167
168 public final static String TEXT_PLAIN_VALUE = "text/plain";
169
170
171
172
173 public final static MimeType TEXT_XML;
174
175
176
177
178 public final static String TEXT_XML_VALUE = "text/xml";
179
180
181 static {
182 ALL = MimeType.valueOf(ALL_VALUE);
183 APPLICATION_ATOM_XML = MimeType.valueOf(APPLICATION_ATOM_XML_VALUE);
184 APPLICATION_FORM_URLENCODED = MimeType.valueOf(APPLICATION_FORM_URLENCODED_VALUE);
185 APPLICATION_JSON = MimeType.valueOf(APPLICATION_JSON_VALUE);
186 APPLICATION_OCTET_STREAM = MimeType.valueOf(APPLICATION_OCTET_STREAM_VALUE);
187 APPLICATION_XHTML_XML = MimeType.valueOf(APPLICATION_XHTML_XML_VALUE);
188 APPLICATION_XML = MimeType.valueOf(APPLICATION_XML_VALUE);
189 IMAGE_GIF = MimeType.valueOf(IMAGE_GIF_VALUE);
190 IMAGE_JPEG = MimeType.valueOf(IMAGE_JPEG_VALUE);
191 IMAGE_PNG = MimeType.valueOf(IMAGE_PNG_VALUE);
192 MULTIPART_FORM_DATA = MimeType.valueOf(MULTIPART_FORM_DATA_VALUE);
193 TEXT_HTML = MimeType.valueOf(TEXT_HTML_VALUE);
194 TEXT_PLAIN = MimeType.valueOf(TEXT_PLAIN_VALUE);
195 TEXT_XML = MimeType.valueOf(TEXT_XML_VALUE);
196 }
197
198
199
200
201
202
203
204
205 public static MimeType parseMimeType(String mimeType) {
206 if (!StringUtils.hasLength(mimeType)) {
207 throw new InvalidMimeTypeException(mimeType, "'mimeType' must not be empty");
208 }
209 String[] parts = StringUtils.tokenizeToStringArray(mimeType, ";");
210
211 String fullType = parts[0].trim();
212
213 if (MimeType.WILDCARD_TYPE.equals(fullType)) {
214 fullType = "*/*";
215 }
216 int subIndex = fullType.indexOf('/');
217 if (subIndex == -1) {
218 throw new InvalidMimeTypeException(mimeType, "does not contain '/'");
219 }
220 if (subIndex == fullType.length() - 1) {
221 throw new InvalidMimeTypeException(mimeType, "does not contain subtype after '/'");
222 }
223 String type = fullType.substring(0, subIndex);
224 String subtype = fullType.substring(subIndex + 1, fullType.length());
225 if (MimeType.WILDCARD_TYPE.equals(type) && !MimeType.WILDCARD_TYPE.equals(subtype)) {
226 throw new InvalidMimeTypeException(mimeType, "wildcard type is legal only in '*/*' (all mime types)");
227 }
228
229 Map<String, String> parameters = null;
230 if (parts.length > 1) {
231 parameters = new LinkedHashMap<String, String>(parts.length - 1);
232 for (int i = 1; i < parts.length; i++) {
233 String parameter = parts[i];
234 int eqIndex = parameter.indexOf('=');
235 if (eqIndex != -1) {
236 String attribute = parameter.substring(0, eqIndex);
237 String value = parameter.substring(eqIndex + 1, parameter.length());
238 parameters.put(attribute, value);
239 }
240 }
241 }
242
243 try {
244 return new MimeType(type, subtype, parameters);
245 }
246 catch (UnsupportedCharsetException ex) {
247 throw new InvalidMimeTypeException(mimeType, "unsupported charset '" + ex.getCharsetName() + "'");
248 }
249 catch (IllegalArgumentException ex) {
250 throw new InvalidMimeTypeException(mimeType, ex.getMessage());
251 }
252 }
253
254
255
256
257
258
259
260 public static List<MimeType> parseMimeTypes(String mimeTypes) {
261 if (!StringUtils.hasLength(mimeTypes)) {
262 return Collections.emptyList();
263 }
264 String[] tokens = mimeTypes.split(",\\s*");
265 List<MimeType> result = new ArrayList<MimeType>(tokens.length);
266 for (String token : tokens) {
267 result.add(parseMimeType(token));
268 }
269 return result;
270 }
271
272
273
274
275
276
277
278 public static String toString(Collection<? extends MimeType> mimeTypes) {
279 StringBuilder builder = new StringBuilder();
280 for (Iterator<? extends MimeType> iterator = mimeTypes.iterator(); iterator.hasNext();) {
281 MimeType mimeType = iterator.next();
282 mimeType.appendTo(builder);
283 if (iterator.hasNext()) {
284 builder.append(", ");
285 }
286 }
287 return builder.toString();
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 public static void sortBySpecificity(List<MimeType> mimeTypes) {
316 Assert.notNull(mimeTypes, "'mimeTypes' must not be null");
317 if (mimeTypes.size() > 1) {
318 Collections.sort(mimeTypes, SPECIFICITY_COMPARATOR);
319 }
320 }
321
322
323
324
325
326 public static final Comparator<MimeType> SPECIFICITY_COMPARATOR = new SpecificityComparator<MimeType>();
327
328 }