comparison src/org/eclipse/jetty/http/MimeTypes.java @ 1023:27f3dc761452

MimeTypes uses StringCache
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 01 Nov 2016 03:44:46 -0600
parents 6be43ef1eb96
children 2b769da7f67d
comparison
equal deleted inserted replaced
1022:3718afd99988 1023:27f3dc761452
24 import java.util.Map; 24 import java.util.Map;
25 import java.util.MissingResourceException; 25 import java.util.MissingResourceException;
26 import java.util.ResourceBundle; 26 import java.util.ResourceBundle;
27 27
28 import org.eclipse.jetty.io.Buffer; 28 import org.eclipse.jetty.io.Buffer;
29 import org.eclipse.jetty.io.BufferCache; 29 import org.eclipse.jetty.io.StringCache;
30 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
31 import org.eclipse.jetty.util.StringUtil; 30 import org.eclipse.jetty.util.StringUtil;
32 import org.slf4j.Logger; 31 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory; 32 import org.slf4j.LoggerFactory;
34 33
35 34
36 /* ------------------------------------------------------------ */ 35 public final class MimeTypes
37 /**
38 *
39 */
40 public class MimeTypes
41 { 36 {
42 private static final Logger LOG = LoggerFactory.getLogger(MimeTypes.class); 37 private static final Logger LOG = LoggerFactory.getLogger(MimeTypes.class);
43 38
44 public final static String 39 public final static String
45 FORM_ENCODED="application/x-www-form-urlencoded", 40 FORM_ENCODED="application/x-www-form-urlencoded",
68 TEXT_PLAIN__UTF_8="text/plain; charset=UTF-8", 63 TEXT_PLAIN__UTF_8="text/plain; charset=UTF-8",
69 TEXT_XML__UTF_8="text/xml; charset=UTF-8", 64 TEXT_XML__UTF_8="text/xml; charset=UTF-8",
70 TEXT_JSON__UTF_8="text/json; charset=UTF-8"; 65 TEXT_JSON__UTF_8="text/json; charset=UTF-8";
71 66
72 private final static int 67 private final static int
73 FORM_ENCODED_ORDINAL=1, 68 FORM_ENCODED_ORDINAL=1,
74 MESSAGE_HTTP_ORDINAL=2, 69 MESSAGE_HTTP_ORDINAL=2,
75 MULTIPART_BYTERANGES_ORDINAL=3, 70 MULTIPART_BYTERANGES_ORDINAL=3,
76 71
77 TEXT_HTML_ORDINAL=4, 72 TEXT_HTML_ORDINAL=4,
78 TEXT_PLAIN_ORDINAL=5, 73 TEXT_PLAIN_ORDINAL=5,
79 TEXT_XML_ORDINAL=6, 74 TEXT_XML_ORDINAL=6,
80 TEXT_JSON_ORDINAL=7, 75 TEXT_JSON_ORDINAL=7,
81 76
82 TEXT_HTML_8859_1_ORDINAL=8, 77 TEXT_HTML_8859_1_ORDINAL=8,
83 TEXT_PLAIN_8859_1_ORDINAL=9, 78 TEXT_PLAIN_8859_1_ORDINAL=9,
84 TEXT_XML_8859_1_ORDINAL=10, 79 TEXT_XML_8859_1_ORDINAL=10,
88 TEXT_XML_UTF_8_ORDINAL=13, 83 TEXT_XML_UTF_8_ORDINAL=13,
89 TEXT_JSON_UTF_8_ORDINAL=14; 84 TEXT_JSON_UTF_8_ORDINAL=14;
90 85
91 private static int __index=15; 86 private static int __index=15;
92 87
93 public final static BufferCache CACHE = new BufferCache(); 88 public final static StringCache CACHE = new StringCache();
94 89
95 public final static CachedBuffer 90 public final static byte[]
96 FORM_ENCODED_BUFFER=CACHE.add(FORM_ENCODED,FORM_ENCODED_ORDINAL), 91 FORM_ENCODED_BYTES=CACHE.add(FORM_ENCODED,FORM_ENCODED_ORDINAL),
97 MESSAGE_HTTP_BUFFER=CACHE.add(MESSAGE_HTTP, MESSAGE_HTTP_ORDINAL), 92 MESSAGE_HTTP_BYTES=CACHE.add(MESSAGE_HTTP, MESSAGE_HTTP_ORDINAL),
98 MULTIPART_BYTERANGES_BUFFER=CACHE.add(MULTIPART_BYTERANGES,MULTIPART_BYTERANGES_ORDINAL), 93 MULTIPART_BYTERANGES_BYTES=CACHE.add(MULTIPART_BYTERANGES,MULTIPART_BYTERANGES_ORDINAL),
99 94
100 TEXT_HTML_BUFFER=CACHE.add(TEXT_HTML,TEXT_HTML_ORDINAL), 95 TEXT_HTML_BYTES=CACHE.add(TEXT_HTML,TEXT_HTML_ORDINAL),
101 TEXT_PLAIN_BUFFER=CACHE.add(TEXT_PLAIN,TEXT_PLAIN_ORDINAL), 96 TEXT_PLAIN_BYTES=CACHE.add(TEXT_PLAIN,TEXT_PLAIN_ORDINAL),
102 TEXT_XML_BUFFER=CACHE.add(TEXT_XML,TEXT_XML_ORDINAL), 97 TEXT_XML_BYTES=CACHE.add(TEXT_XML,TEXT_XML_ORDINAL),
103 TEXT_JSON_BUFFER=CACHE.add(TEXT_JSON,TEXT_JSON_ORDINAL), 98 TEXT_JSON_BYTES=CACHE.add(TEXT_JSON,TEXT_JSON_ORDINAL),
104 99
105 TEXT_HTML_8859_1_BUFFER=CACHE.add(TEXT_HTML_8859_1,TEXT_HTML_8859_1_ORDINAL), 100 TEXT_HTML_8859_1_BYTES=CACHE.add(TEXT_HTML_8859_1,TEXT_HTML_8859_1_ORDINAL),
106 TEXT_PLAIN_8859_1_BUFFER=CACHE.add(TEXT_PLAIN_8859_1,TEXT_PLAIN_8859_1_ORDINAL), 101 TEXT_PLAIN_8859_1_BYTES=CACHE.add(TEXT_PLAIN_8859_1,TEXT_PLAIN_8859_1_ORDINAL),
107 TEXT_XML_8859_1_BUFFER=CACHE.add(TEXT_XML_8859_1,TEXT_XML_8859_1_ORDINAL), 102 TEXT_XML_8859_1_BYTES=CACHE.add(TEXT_XML_8859_1,TEXT_XML_8859_1_ORDINAL),
108 103
109 TEXT_HTML_UTF_8_BUFFER=CACHE.add(TEXT_HTML_UTF_8,TEXT_HTML_UTF_8_ORDINAL), 104 TEXT_HTML_UTF_8_BYTES=CACHE.add(TEXT_HTML_UTF_8,TEXT_HTML_UTF_8_ORDINAL),
110 TEXT_PLAIN_UTF_8_BUFFER=CACHE.add(TEXT_PLAIN_UTF_8,TEXT_PLAIN_UTF_8_ORDINAL), 105 TEXT_PLAIN_UTF_8_BYTES=CACHE.add(TEXT_PLAIN_UTF_8,TEXT_PLAIN_UTF_8_ORDINAL),
111 TEXT_XML_UTF_8_BUFFER=CACHE.add(TEXT_XML_UTF_8,TEXT_XML_UTF_8_ORDINAL), 106 TEXT_XML_UTF_8_BYTES=CACHE.add(TEXT_XML_UTF_8,TEXT_XML_UTF_8_ORDINAL),
112 TEXT_JSON_UTF_8_BUFFER=CACHE.add(TEXT_JSON_UTF_8,TEXT_JSON_UTF_8_ORDINAL), 107 TEXT_JSON_UTF_8_BYTES=CACHE.add(TEXT_JSON_UTF_8,TEXT_JSON_UTF_8_ORDINAL),
113 108
114 TEXT_HTML__8859_1_BUFFER=CACHE.add(TEXT_HTML__8859_1,TEXT_HTML_8859_1_ORDINAL), 109 TEXT_HTML__8859_1_BYTES=CACHE.add(TEXT_HTML__8859_1,TEXT_HTML_8859_1_ORDINAL),
115 TEXT_PLAIN__8859_1_BUFFER=CACHE.add(TEXT_PLAIN__8859_1,TEXT_PLAIN_8859_1_ORDINAL), 110 TEXT_PLAIN__8859_1_BYTES=CACHE.add(TEXT_PLAIN__8859_1,TEXT_PLAIN_8859_1_ORDINAL),
116 TEXT_XML__8859_1_BUFFER=CACHE.add(TEXT_XML__8859_1,TEXT_XML_8859_1_ORDINAL), 111 TEXT_XML__8859_1_BYTES=CACHE.add(TEXT_XML__8859_1,TEXT_XML_8859_1_ORDINAL),
117 112
118 TEXT_HTML__UTF_8_BUFFER=CACHE.add(TEXT_HTML__UTF_8,TEXT_HTML_UTF_8_ORDINAL), 113 TEXT_HTML__UTF_8_BYTES=CACHE.add(TEXT_HTML__UTF_8,TEXT_HTML_UTF_8_ORDINAL),
119 TEXT_PLAIN__UTF_8_BUFFER=CACHE.add(TEXT_PLAIN__UTF_8,TEXT_PLAIN_UTF_8_ORDINAL), 114 TEXT_PLAIN__UTF_8_BYTES=CACHE.add(TEXT_PLAIN__UTF_8,TEXT_PLAIN_UTF_8_ORDINAL),
120 TEXT_XML__UTF_8_BUFFER=CACHE.add(TEXT_XML__UTF_8,TEXT_XML_UTF_8_ORDINAL), 115 TEXT_XML__UTF_8_BYTES=CACHE.add(TEXT_XML__UTF_8,TEXT_XML_UTF_8_ORDINAL),
121 TEXT_JSON__UTF_8_BUFFER=CACHE.add(TEXT_JSON__UTF_8,TEXT_JSON_UTF_8_ORDINAL); 116 TEXT_JSON__UTF_8_BYTES=CACHE.add(TEXT_JSON__UTF_8,TEXT_JSON_UTF_8_ORDINAL);
122 117
123 118
124 /* ------------------------------------------------------------ */ 119 private final static Map<String,String> __dftMimeMap = new HashMap<String,String>();
125 /* ------------------------------------------------------------ */ 120 private final static Map<String,String> __encodings = new HashMap<String,String>();
126 private final static Map __dftMimeMap = new HashMap();
127 private final static Map __encodings = new HashMap();
128 static 121 static
129 { 122 {
130 try 123 try
131 { 124 {
132 ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime"); 125 ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime");
133 Enumeration i = mime.getKeys(); 126 Enumeration i = mime.getKeys();
134 while(i.hasMoreElements()) 127 while(i.hasMoreElements())
135 { 128 {
136 String ext = (String)i.nextElement(); 129 String ext = (String)i.nextElement();
137 String m = mime.getString(ext); 130 String m = mime.getString(ext);
138 __dftMimeMap.put(StringUtil.asciiToLowerCase(ext),normalizeMimeType(m)); 131 // __dftMimeMap.put(ext.toLowerCase(),normalizeMimeType(m));
132 __dftMimeMap.put(ext.toLowerCase(),m);
139 } 133 }
140 } 134 }
141 catch(MissingResourceException e) 135 catch(MissingResourceException e)
142 { 136 {
143 LOG.warn(e.toString()); 137 LOG.warn(e.toString());
144 LOG.debug("",e); 138 LOG.debug("",e);
145 } 139 }
146 140
147 try 141 __encodings.put("text/html","ISO-8859-1");
148 { 142 __encodings.put("text/plain","ISO-8859-1");
149 ResourceBundle encoding = ResourceBundle.getBundle("org/eclipse/jetty/http/encoding"); 143 __encodings.put("text/xml","UTF-8");
150 Enumeration i = encoding.getKeys(); 144 __encodings.put("text/json","UTF-8");
151 while(i.hasMoreElements()) 145
152 { 146 /*
153 Buffer type = normalizeMimeType((String)i.nextElement());
154 __encodings.put(type,encoding.getString(type.toString()));
155 }
156 }
157 catch(MissingResourceException e)
158 {
159 LOG.warn(e.toString());
160 LOG.debug("",e);
161 }
162
163
164 TEXT_HTML_BUFFER.setAssociate("ISO-8859-1",TEXT_HTML_8859_1_BUFFER); 147 TEXT_HTML_BUFFER.setAssociate("ISO-8859-1",TEXT_HTML_8859_1_BUFFER);
165 TEXT_HTML_BUFFER.setAssociate("ISO_8859_1",TEXT_HTML_8859_1_BUFFER); 148 TEXT_HTML_BUFFER.setAssociate("ISO_8859_1",TEXT_HTML_8859_1_BUFFER);
166 TEXT_HTML_BUFFER.setAssociate("iso-8859-1",TEXT_HTML_8859_1_BUFFER); 149 TEXT_HTML_BUFFER.setAssociate("iso-8859-1",TEXT_HTML_8859_1_BUFFER);
167 TEXT_PLAIN_BUFFER.setAssociate("ISO-8859-1",TEXT_PLAIN_8859_1_BUFFER); 150 TEXT_PLAIN_BUFFER.setAssociate("ISO-8859-1",TEXT_PLAIN_8859_1_BUFFER);
168 TEXT_PLAIN_BUFFER.setAssociate("ISO_8859_1",TEXT_PLAIN_8859_1_BUFFER); 151 TEXT_PLAIN_BUFFER.setAssociate("ISO_8859_1",TEXT_PLAIN_8859_1_BUFFER);
185 TEXT_XML_BUFFER.setAssociate("utf-8",TEXT_XML_UTF_8_BUFFER); 168 TEXT_XML_BUFFER.setAssociate("utf-8",TEXT_XML_UTF_8_BUFFER);
186 TEXT_JSON_BUFFER.setAssociate("UTF-8",TEXT_JSON_UTF_8_BUFFER); 169 TEXT_JSON_BUFFER.setAssociate("UTF-8",TEXT_JSON_UTF_8_BUFFER);
187 TEXT_JSON_BUFFER.setAssociate("UTF8",TEXT_JSON_UTF_8_BUFFER); 170 TEXT_JSON_BUFFER.setAssociate("UTF8",TEXT_JSON_UTF_8_BUFFER);
188 TEXT_JSON_BUFFER.setAssociate("utf8",TEXT_JSON_UTF_8_BUFFER); 171 TEXT_JSON_BUFFER.setAssociate("utf8",TEXT_JSON_UTF_8_BUFFER);
189 TEXT_JSON_BUFFER.setAssociate("utf-8",TEXT_JSON_UTF_8_BUFFER); 172 TEXT_JSON_BUFFER.setAssociate("utf-8",TEXT_JSON_UTF_8_BUFFER);
190 } 173 */
191 174 }
192 175
193 /* ------------------------------------------------------------ */ 176 // replace setAssociate()
194 private Map _mimeMap; 177
195 178 private static final Map<String,String> association = new HashMap<String,String>();
196 /* ------------------------------------------------------------ */ 179
197 /** Constructor. 180 private static String key(String type,String charEncoding) {
198 */ 181 return (type+'~'+charEncoding).toLowerCase();
199 public MimeTypes() 182 }
200 { 183
201 } 184 private static void setAssociate(String type,String charEncoding,String result) {
202 185 association.put( key(type,charEncoding), result );
203 /* ------------------------------------------------------------ */ 186 }
204 public synchronized Map getMimeMap() 187
205 { 188 public static String getAssociate(String type,String charEncoding) {
206 return _mimeMap; 189 return association.get( key(type,charEncoding) );
207 } 190 }
208 191
209 /* ------------------------------------------------------------ */ 192 static {
210 /** 193 setAssociate(TEXT_HTML,"ISO-8859-1",TEXT_HTML_8859_1);
211 * @param mimeMap A Map of file extension to mime-type. 194 setAssociate(TEXT_HTML,"ISO_8859_1",TEXT_HTML_8859_1);
212 */ 195 setAssociate(TEXT_PLAIN,"ISO-8859-1",TEXT_PLAIN_8859_1);
213 public void setMimeMap(Map mimeMap) 196 setAssociate(TEXT_PLAIN,"ISO_8859_1",TEXT_PLAIN_8859_1);
214 { 197 setAssociate(TEXT_XML,"ISO-8859-1",TEXT_XML_8859_1);
215 if (mimeMap==null) 198 setAssociate(TEXT_XML,"ISO_8859_1",TEXT_XML_8859_1);
216 { 199
217 _mimeMap=null; 200 setAssociate(TEXT_HTML,"UTF-8",TEXT_HTML_UTF_8);
218 return; 201 setAssociate(TEXT_HTML,"UTF8",TEXT_HTML_UTF_8);
219 } 202 setAssociate(TEXT_PLAIN,"UTF-8",TEXT_PLAIN_UTF_8);
220 203 setAssociate(TEXT_PLAIN,"UTF8",TEXT_PLAIN_UTF_8);
221 Map m=new HashMap(); 204 setAssociate(TEXT_XML,"UTF-8",TEXT_XML_UTF_8);
222 Iterator i=mimeMap.entrySet().iterator(); 205 setAssociate(TEXT_XML,"UTF8",TEXT_XML_UTF_8);
223 while (i.hasNext()) 206 setAssociate(TEXT_JSON,"UTF-8",TEXT_JSON_UTF_8);
224 { 207 setAssociate(TEXT_JSON,"UTF8",TEXT_JSON_UTF_8);
225 Map.Entry entry = (Map.Entry)i.next(); 208 }
226 m.put(entry.getKey(),normalizeMimeType(entry.getValue().toString())); 209
227 } 210
228 _mimeMap=m; 211
229 }
230
231 /* ------------------------------------------------------------ */ 212 /* ------------------------------------------------------------ */
232 /** Get the MIME type by filename extension. 213 /** Get the MIME type by filename extension.
233 * @param filename A file name 214 * @param filename A file name
234 * @return MIME type matching the longest dot extension of the 215 * @return MIME type matching the longest dot extension of the
235 * file name. 216 * file name.
236 */ 217 */
237 public Buffer getMimeByExtension(String filename) 218 public String getMimeByExtension(String filename)
238 { 219 {
239 Buffer type=null; 220 String type=null;
240 221
241 if (filename!=null) 222 if (filename!=null)
242 { 223 {
243 int i=-1; 224 int i=-1;
244 while(type==null) 225 while(type==null)
246 i=filename.indexOf(".",i+1); 227 i=filename.indexOf(".",i+1);
247 228
248 if (i<0 || i>=filename.length()) 229 if (i<0 || i>=filename.length())
249 break; 230 break;
250 231
251 String ext=StringUtil.asciiToLowerCase(filename.substring(i+1)); 232 String ext = filename.substring(i+1).toLowerCase();
252 if (_mimeMap!=null) 233 type = __dftMimeMap.get(ext);
253 type = (Buffer)_mimeMap.get(ext);
254 if (type==null)
255 type=(Buffer)__dftMimeMap.get(ext);
256 } 234 }
257 } 235 }
258 236
259 if (type==null) 237 if (type==null)
260 { 238 {
261 if (_mimeMap!=null) 239 type = __dftMimeMap.get("*");
262 type=(Buffer)_mimeMap.get("*");
263 if (type==null)
264 type=(Buffer)__dftMimeMap.get("*");
265 } 240 }
266 241
267 return type; 242 return type;
268 } 243 }
269 244 /*
270 /* ------------------------------------------------------------ */
271 /** Set a mime mapping
272 * @param extension
273 * @param type
274 */
275 public void addMimeMapping(String extension,String type)
276 {
277 if (_mimeMap==null)
278 _mimeMap=new HashMap();
279
280 _mimeMap.put(StringUtil.asciiToLowerCase(extension),normalizeMimeType(type));
281 }
282
283 /* ------------------------------------------------------------ */
284 private static synchronized Buffer normalizeMimeType(String type) 245 private static synchronized Buffer normalizeMimeType(String type)
285 { 246 {
286 Buffer b =CACHE.get(type); 247 Buffer b = CACHE.get(type);
287 if (b==null) 248 if (b==null)
288 b=CACHE.add(type,__index++); 249 b = CACHE.add(type,__index++);
289 return b; 250 return b;
290 } 251 }
291 252 */
292 /* ------------------------------------------------------------ */ 253 public static String getCharsetFromContentType(String value)
293 public static String getCharsetFromContentType(Buffer value)
294 { 254 {
295 if (value instanceof CachedBuffer) 255 switch(CACHE.getOrdinal(value))
296 { 256 {
297 switch(((CachedBuffer)value).getOrdinal()) 257 case TEXT_HTML_8859_1_ORDINAL:
298 { 258 case TEXT_PLAIN_8859_1_ORDINAL:
299 case TEXT_HTML_8859_1_ORDINAL: 259 case TEXT_XML_8859_1_ORDINAL:
300 case TEXT_PLAIN_8859_1_ORDINAL: 260 return StringUtil.__ISO_8859_1;
301 case TEXT_XML_8859_1_ORDINAL: 261
302 return StringUtil.__ISO_8859_1; 262 case TEXT_HTML_UTF_8_ORDINAL:
303 263 case TEXT_PLAIN_UTF_8_ORDINAL:
304 case TEXT_HTML_UTF_8_ORDINAL: 264 case TEXT_XML_UTF_8_ORDINAL:
305 case TEXT_PLAIN_UTF_8_ORDINAL: 265 case TEXT_JSON_UTF_8_ORDINAL:
306 case TEXT_XML_UTF_8_ORDINAL: 266 return StringUtil.__UTF8;
307 case TEXT_JSON_UTF_8_ORDINAL: 267 }
308 return StringUtil.__UTF8; 268
309 } 269 int i = 0;
310 } 270 int end = value.length();
311
312 int i=value.getIndex();
313 int end=value.putIndex();
314 int state=0; 271 int state=0;
315 int start=0; 272 int start=0;
316 boolean quote=false; 273 boolean quote=false;
317 for (;i<end;i++) 274 for (;i<end;i++)
318 { 275 {
319 byte b = value.peek(i); 276 char b = value.charAt(i);
320 277
321 if (quote && state!=10) 278 if (quote && state!=10)
322 { 279 {
323 if ('"'==b) 280 if ('"'==b)
324 quote=false; 281 quote=false;
362 break; 319 break;
363 320
364 case 10: 321 case 10:
365 if (!quote && (';'==b || ' '==b )|| 322 if (!quote && (';'==b || ' '==b )||
366 (quote && '"'==b )) 323 (quote && '"'==b ))
367 return CACHE.lookup(value.peek(start,i-start)).toString(StringUtil.__UTF8); 324 return value.substring(start,i);
368 } 325 }
369 } 326 }
370 327
371 if (state==10) 328 if (state==10)
372 return CACHE.lookup(value.peek(start,i-start)).toString(StringUtil.__UTF8); 329 return value.substring(start,i);
373 330
374 return (String)__encodings.get(value); 331 return __encodings.get(value.toLowerCase());
375 } 332 }
376 } 333 }