1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.http;
15
16 import java.util.Enumeration;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.Map;
20 import java.util.MissingResourceException;
21 import java.util.ResourceBundle;
22
23 import org.eclipse.jetty.io.Buffer;
24 import org.eclipse.jetty.io.BufferCache;
25 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
26 import org.eclipse.jetty.util.StringUtil;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29
30
31
32
33
34
35 public class MimeTypes
36 {
37 private static final Logger LOG = Log.getLogger(MimeTypes.class);
38
39 public final static String
40 FORM_ENCODED="application/x-www-form-urlencoded",
41 MESSAGE_HTTP="message/http",
42 MULTIPART_BYTERANGES="multipart/byteranges",
43
44 TEXT_HTML="text/html",
45 TEXT_PLAIN="text/plain",
46 TEXT_XML="text/xml",
47 TEXT_JSON="text/json",
48
49 TEXT_HTML_8859_1="text/html;charset=ISO-8859-1",
50 TEXT_PLAIN_8859_1="text/plain;charset=ISO-8859-1",
51 TEXT_XML_8859_1="text/xml;charset=ISO-8859-1",
52
53 TEXT_HTML_UTF_8="text/html;charset=UTF-8",
54 TEXT_PLAIN_UTF_8="text/plain;charset=UTF-8",
55 TEXT_XML_UTF_8="text/xml;charset=UTF-8",
56 TEXT_JSON_UTF_8="text/json;charset=UTF-8";
57
58 private final static String
59 TEXT_HTML__8859_1="text/html; charset=ISO-8859-1",
60 TEXT_PLAIN__8859_1="text/plain; charset=ISO-8859-1",
61 TEXT_XML__8859_1="text/xml; charset=ISO-8859-1",
62 TEXT_HTML__UTF_8="text/html; charset=UTF-8",
63 TEXT_PLAIN__UTF_8="text/plain; charset=UTF-8",
64 TEXT_XML__UTF_8="text/xml; charset=UTF-8",
65 TEXT_JSON__UTF_8="text/json; charset=UTF-8";
66
67 private final static int
68 FORM_ENCODED_ORDINAL=1,
69 MESSAGE_HTTP_ORDINAL=2,
70 MULTIPART_BYTERANGES_ORDINAL=3,
71
72 TEXT_HTML_ORDINAL=4,
73 TEXT_PLAIN_ORDINAL=5,
74 TEXT_XML_ORDINAL=6,
75 TEXT_JSON_ORDINAL=7,
76
77 TEXT_HTML_8859_1_ORDINAL=8,
78 TEXT_PLAIN_8859_1_ORDINAL=9,
79 TEXT_XML_8859_1_ORDINAL=10,
80
81 TEXT_HTML_UTF_8_ORDINAL=11,
82 TEXT_PLAIN_UTF_8_ORDINAL=12,
83 TEXT_XML_UTF_8_ORDINAL=13,
84 TEXT_JSON_UTF_8_ORDINAL=14;
85
86 private static int __index=15;
87
88 public final static BufferCache CACHE = new BufferCache();
89
90 public final static CachedBuffer
91 FORM_ENCODED_BUFFER=CACHE.add(FORM_ENCODED,FORM_ENCODED_ORDINAL),
92 MESSAGE_HTTP_BUFFER=CACHE.add(MESSAGE_HTTP, MESSAGE_HTTP_ORDINAL),
93 MULTIPART_BYTERANGES_BUFFER=CACHE.add(MULTIPART_BYTERANGES,MULTIPART_BYTERANGES_ORDINAL),
94
95 TEXT_HTML_BUFFER=CACHE.add(TEXT_HTML,TEXT_HTML_ORDINAL),
96 TEXT_PLAIN_BUFFER=CACHE.add(TEXT_PLAIN,TEXT_PLAIN_ORDINAL),
97 TEXT_XML_BUFFER=CACHE.add(TEXT_XML,TEXT_XML_ORDINAL),
98 TEXT_JSON_BUFFER=CACHE.add(TEXT_JSON,TEXT_JSON_ORDINAL),
99
100 TEXT_HTML_8859_1_BUFFER=CACHE.add(TEXT_HTML_8859_1,TEXT_HTML_8859_1_ORDINAL),
101 TEXT_PLAIN_8859_1_BUFFER=CACHE.add(TEXT_PLAIN_8859_1,TEXT_PLAIN_8859_1_ORDINAL),
102 TEXT_XML_8859_1_BUFFER=CACHE.add(TEXT_XML_8859_1,TEXT_XML_8859_1_ORDINAL),
103
104 TEXT_HTML_UTF_8_BUFFER=CACHE.add(TEXT_HTML_UTF_8,TEXT_HTML_UTF_8_ORDINAL),
105 TEXT_PLAIN_UTF_8_BUFFER=CACHE.add(TEXT_PLAIN_UTF_8,TEXT_PLAIN_UTF_8_ORDINAL),
106 TEXT_XML_UTF_8_BUFFER=CACHE.add(TEXT_XML_UTF_8,TEXT_XML_UTF_8_ORDINAL),
107 TEXT_JSON_UTF_8_BUFFER=CACHE.add(TEXT_JSON_UTF_8,TEXT_JSON_UTF_8_ORDINAL),
108
109 TEXT_HTML__8859_1_BUFFER=CACHE.add(TEXT_HTML__8859_1,TEXT_HTML_8859_1_ORDINAL),
110 TEXT_PLAIN__8859_1_BUFFER=CACHE.add(TEXT_PLAIN__8859_1,TEXT_PLAIN_8859_1_ORDINAL),
111 TEXT_XML__8859_1_BUFFER=CACHE.add(TEXT_XML__8859_1,TEXT_XML_8859_1_ORDINAL),
112
113 TEXT_HTML__UTF_8_BUFFER=CACHE.add(TEXT_HTML__UTF_8,TEXT_HTML_UTF_8_ORDINAL),
114 TEXT_PLAIN__UTF_8_BUFFER=CACHE.add(TEXT_PLAIN__UTF_8,TEXT_PLAIN_UTF_8_ORDINAL),
115 TEXT_XML__UTF_8_BUFFER=CACHE.add(TEXT_XML__UTF_8,TEXT_XML_UTF_8_ORDINAL),
116 TEXT_JSON__UTF_8_BUFFER=CACHE.add(TEXT_JSON__UTF_8,TEXT_JSON_UTF_8_ORDINAL);
117
118
119
120
121 private final static Map __dftMimeMap = new HashMap();
122 private final static Map __encodings = new HashMap();
123 static
124 {
125 try
126 {
127 ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime");
128 Enumeration i = mime.getKeys();
129 while(i.hasMoreElements())
130 {
131 String ext = (String)i.nextElement();
132 String m = mime.getString(ext);
133 __dftMimeMap.put(StringUtil.asciiToLowerCase(ext),normalizeMimeType(m));
134 }
135 }
136 catch(MissingResourceException e)
137 {
138 LOG.warn(e.toString());
139 LOG.debug(e);
140 }
141
142 try
143 {
144 ResourceBundle encoding = ResourceBundle.getBundle("org/eclipse/jetty/http/encoding");
145 Enumeration i = encoding.getKeys();
146 while(i.hasMoreElements())
147 {
148 Buffer type = normalizeMimeType((String)i.nextElement());
149 __encodings.put(type,encoding.getString(type.toString()));
150 }
151 }
152 catch(MissingResourceException e)
153 {
154 LOG.warn(e.toString());
155 LOG.debug(e);
156 }
157
158
159 TEXT_HTML_BUFFER.setAssociate("ISO-8859-1",TEXT_HTML_8859_1_BUFFER);
160 TEXT_HTML_BUFFER.setAssociate("ISO_8859_1",TEXT_HTML_8859_1_BUFFER);
161 TEXT_HTML_BUFFER.setAssociate("iso-8859-1",TEXT_HTML_8859_1_BUFFER);
162 TEXT_PLAIN_BUFFER.setAssociate("ISO-8859-1",TEXT_PLAIN_8859_1_BUFFER);
163 TEXT_PLAIN_BUFFER.setAssociate("ISO_8859_1",TEXT_PLAIN_8859_1_BUFFER);
164 TEXT_PLAIN_BUFFER.setAssociate("iso-8859-1",TEXT_PLAIN_8859_1_BUFFER);
165 TEXT_XML_BUFFER.setAssociate("ISO-8859-1",TEXT_XML_8859_1_BUFFER);
166 TEXT_XML_BUFFER.setAssociate("ISO_8859_1",TEXT_XML_8859_1_BUFFER);
167 TEXT_XML_BUFFER.setAssociate("iso-8859-1",TEXT_XML_8859_1_BUFFER);
168
169 TEXT_HTML_BUFFER.setAssociate("UTF-8",TEXT_HTML_UTF_8_BUFFER);
170 TEXT_HTML_BUFFER.setAssociate("UTF8",TEXT_HTML_UTF_8_BUFFER);
171 TEXT_HTML_BUFFER.setAssociate("utf8",TEXT_HTML_UTF_8_BUFFER);
172 TEXT_HTML_BUFFER.setAssociate("utf-8",TEXT_HTML_UTF_8_BUFFER);
173 TEXT_PLAIN_BUFFER.setAssociate("UTF-8",TEXT_PLAIN_UTF_8_BUFFER);
174 TEXT_PLAIN_BUFFER.setAssociate("UTF8",TEXT_PLAIN_UTF_8_BUFFER);
175 TEXT_PLAIN_BUFFER.setAssociate("utf8",TEXT_PLAIN_UTF_8_BUFFER);
176 TEXT_PLAIN_BUFFER.setAssociate("utf-8",TEXT_PLAIN_UTF_8_BUFFER);
177 TEXT_XML_BUFFER.setAssociate("UTF-8",TEXT_XML_UTF_8_BUFFER);
178 TEXT_XML_BUFFER.setAssociate("UTF8",TEXT_XML_UTF_8_BUFFER);
179 TEXT_XML_BUFFER.setAssociate("utf8",TEXT_XML_UTF_8_BUFFER);
180 TEXT_XML_BUFFER.setAssociate("utf-8",TEXT_XML_UTF_8_BUFFER);
181 TEXT_JSON_BUFFER.setAssociate("UTF-8",TEXT_JSON_UTF_8_BUFFER);
182 TEXT_JSON_BUFFER.setAssociate("UTF8",TEXT_JSON_UTF_8_BUFFER);
183 TEXT_JSON_BUFFER.setAssociate("utf8",TEXT_JSON_UTF_8_BUFFER);
184 TEXT_JSON_BUFFER.setAssociate("utf-8",TEXT_JSON_UTF_8_BUFFER);
185 }
186
187
188
189 private Map _mimeMap;
190
191
192
193
194 public MimeTypes()
195 {
196 }
197
198
199 public synchronized Map getMimeMap()
200 {
201 return _mimeMap;
202 }
203
204
205
206
207
208 public void setMimeMap(Map mimeMap)
209 {
210 if (mimeMap==null)
211 {
212 _mimeMap=null;
213 return;
214 }
215
216 Map m=new HashMap();
217 Iterator i=mimeMap.entrySet().iterator();
218 while (i.hasNext())
219 {
220 Map.Entry entry = (Map.Entry)i.next();
221 m.put(entry.getKey(),normalizeMimeType(entry.getValue().toString()));
222 }
223 _mimeMap=m;
224 }
225
226
227
228
229
230
231
232 public Buffer getMimeByExtension(String filename)
233 {
234 Buffer type=null;
235
236 if (filename!=null)
237 {
238 int i=-1;
239 while(type==null)
240 {
241 i=filename.indexOf(".",i+1);
242
243 if (i<0 || i>=filename.length())
244 break;
245
246 String ext=StringUtil.asciiToLowerCase(filename.substring(i+1));
247 if (_mimeMap!=null)
248 type = (Buffer)_mimeMap.get(ext);
249 if (type==null)
250 type=(Buffer)__dftMimeMap.get(ext);
251 }
252 }
253
254 if (type==null)
255 {
256 if (_mimeMap!=null)
257 type=(Buffer)_mimeMap.get("*");
258 if (type==null)
259 type=(Buffer)__dftMimeMap.get("*");
260 }
261
262 return type;
263 }
264
265
266
267
268
269
270 public void addMimeMapping(String extension,String type)
271 {
272 if (_mimeMap==null)
273 _mimeMap=new HashMap();
274
275 _mimeMap.put(StringUtil.asciiToLowerCase(extension),normalizeMimeType(type));
276 }
277
278
279 private static synchronized Buffer normalizeMimeType(String type)
280 {
281 Buffer b =CACHE.get(type);
282 if (b==null)
283 b=CACHE.add(type,__index++);
284 return b;
285 }
286
287
288 public static String getCharsetFromContentType(Buffer value)
289 {
290 if (value instanceof CachedBuffer)
291 {
292 switch(((CachedBuffer)value).getOrdinal())
293 {
294 case TEXT_HTML_8859_1_ORDINAL:
295 case TEXT_PLAIN_8859_1_ORDINAL:
296 case TEXT_XML_8859_1_ORDINAL:
297 return StringUtil.__ISO_8859_1;
298
299 case TEXT_HTML_UTF_8_ORDINAL:
300 case TEXT_PLAIN_UTF_8_ORDINAL:
301 case TEXT_XML_UTF_8_ORDINAL:
302 case TEXT_JSON_UTF_8_ORDINAL:
303 return StringUtil.__UTF8;
304 }
305 }
306
307 int i=value.getIndex();
308 int end=value.putIndex();
309 int state=0;
310 int start=0;
311 boolean quote=false;
312 for (;i<end;i++)
313 {
314 byte b = value.peek(i);
315
316 if (quote && state!=10)
317 {
318 if ('"'==b)
319 quote=false;
320 continue;
321 }
322
323 switch(state)
324 {
325 case 0:
326 if ('"'==b)
327 {
328 quote=true;
329 break;
330 }
331 if (';'==b)
332 state=1;
333 break;
334
335 case 1: if ('c'==b) state=2; else if (' '!=b) state=0; break;
336 case 2: if ('h'==b) state=3; else state=0;break;
337 case 3: if ('a'==b) state=4; else state=0;break;
338 case 4: if ('r'==b) state=5; else state=0;break;
339 case 5: if ('s'==b) state=6; else state=0;break;
340 case 6: if ('e'==b) state=7; else state=0;break;
341 case 7: if ('t'==b) state=8; else state=0;break;
342
343 case 8: if ('='==b) state=9; else if (' '!=b) state=0; break;
344
345 case 9:
346 if (' '==b)
347 break;
348 if ('"'==b)
349 {
350 quote=true;
351 start=i+1;
352 state=10;
353 break;
354 }
355 start=i;
356 state=10;
357 break;
358
359 case 10:
360 if (!quote && (';'==b || ' '==b )||
361 (quote && '"'==b ))
362 return CACHE.lookup(value.peek(start,i-start)).toString();
363 }
364 }
365
366 if (state==10)
367 return CACHE.lookup(value.peek(start,i-start)).toString();
368
369 return (String)__encodings.get(value);
370 }
371 }