001: // ========================================================================
002: // Copyright 2000-2005 Mort Bay Consulting Pty. Ltd.
003: // ------------------------------------------------------------------------
004: // Licensed under the Apache License, Version 2.0 (the "License");
005: // you may not use this file except in compliance with the License.
006: // You may obtain a copy of the License at
007: // http://www.apache.org/licenses/LICENSE-2.0
008: // Unless required by applicable law or agreed to in writing, software
009: // distributed under the License is distributed on an "AS IS" BASIS,
010: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: // See the License for the specific language governing permissions and
012: // limitations under the License.
013: // ========================================================================
014:
015: package org.mortbay.jetty;
016:
017: import java.util.Enumeration;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.Map;
021: import java.util.ResourceBundle;
022:
023: import org.mortbay.io.Buffer;
024: import org.mortbay.io.BufferCache;
025: import org.mortbay.io.BufferCache.CachedBuffer;
026: import org.mortbay.util.StringUtil;
027:
028: /* ------------------------------------------------------------ */
029: /**
030: * @author Greg Wilkins
031: */
032: public class MimeTypes {
033: public final static String FORM_ENCODED = "application/x-www-form-urlencoded",
034: MESSAGE_HTTP = "message/http",
035: MULTIPART_BYTERANGES = "multipart/byteranges",
036: TEXT_HTML = "text/html",
037: TEXT_PLAIN = "text/plain",
038: TEXT_XML = "text/xml",
039: TEXT_HTML_8859_1 = "text/html; charset=iso-8859-1",
040: TEXT_PLAIN_8859_1 = "text/plain; charset=iso-8859-1",
041: TEXT_XML_8859_1 = "text/xml; charset=iso-8859-1",
042: TEXT_HTML_UTF_8 = "text/html; charset=utf-8",
043: TEXT_PLAIN_UTF_8 = "text/plain; charset=utf-8",
044: TEXT_XML_UTF_8 = "text/xml; charset=utf-8";
045:
046: private final static int FORM_ENCODED_ORDINAL = 1,
047: MESSAGE_HTTP_ORDINAL = 2, MULTIPART_BYTERANGES_ORDINAL = 3,
048: TEXT_HTML_ORDINAL = 4, TEXT_PLAIN_ORDINAL = 5,
049: TEXT_XML_ORDINAL = 6, TEXT_HTML_8859_1_ORDINAL = 7,
050: TEXT_PLAIN_8859_1_ORDINAL = 8, TEXT_XML_8859_1_ORDINAL = 9,
051: TEXT_HTML_UTF_8_ORDINAL = 10,
052: TEXT_PLAIN_UTF_8_ORDINAL = 11, TEXT_XML_UTF_8_ORDINAL = 12;
053:
054: private static int __index = 13;
055:
056: public final static BufferCache CACHE = new BufferCache();
057:
058: public final static CachedBuffer FORM_ENCODED_BUFFER = CACHE.add(
059: FORM_ENCODED, FORM_ENCODED_ORDINAL),
060: MESSAGE_HTTP_BUFFER = CACHE.add(MESSAGE_HTTP,
061: MESSAGE_HTTP_ORDINAL),
062: MULTIPART_BYTERANGES_BUFFER = CACHE.add(
063: MULTIPART_BYTERANGES, MULTIPART_BYTERANGES_ORDINAL),
064:
065: TEXT_HTML_BUFFER = CACHE.add(TEXT_HTML, TEXT_HTML_ORDINAL),
066: TEXT_PLAIN_BUFFER = CACHE.add(TEXT_PLAIN,
067: TEXT_PLAIN_ORDINAL), TEXT_XML_BUFFER = CACHE.add(
068: TEXT_XML, TEXT_XML_ORDINAL),
069:
070: TEXT_HTML_8859_1_BUFFER = new CachedBuffer(
071: TEXT_HTML_8859_1, TEXT_HTML_8859_1_ORDINAL),
072: TEXT_PLAIN_8859_1_BUFFER = new CachedBuffer(
073: TEXT_PLAIN_8859_1, TEXT_PLAIN_8859_1_ORDINAL),
074: TEXT_XML_8859_1_BUFFER = new CachedBuffer(TEXT_XML_8859_1,
075: TEXT_XML_8859_1_ORDINAL),
076: TEXT_HTML_UTF_8_BUFFER = new CachedBuffer(TEXT_HTML_UTF_8,
077: TEXT_HTML_UTF_8_ORDINAL),
078: TEXT_PLAIN_UTF_8_BUFFER = new CachedBuffer(
079: TEXT_PLAIN_UTF_8, TEXT_PLAIN_UTF_8_ORDINAL),
080: TEXT_XML_UTF_8_BUFFER = new CachedBuffer(TEXT_XML_UTF_8,
081: TEXT_XML_UTF_8_ORDINAL);
082:
083: /* ------------------------------------------------------------ */
084: /* ------------------------------------------------------------ */
085: private final static Map __dftMimeMap = new HashMap();
086: private final static Map __encodings = new HashMap();
087: static {
088: ResourceBundle mime = ResourceBundle
089: .getBundle("org/mortbay/jetty/mime");
090: Enumeration i = mime.getKeys();
091: while (i.hasMoreElements()) {
092: String ext = (String) i.nextElement();
093: String m = mime.getString(ext);
094: __dftMimeMap.put(StringUtil.asciiToLowerCase(ext),
095: normalizeMimeType(m));
096: }
097:
098: ResourceBundle encoding = ResourceBundle
099: .getBundle("org/mortbay/jetty/encoding");
100: i = encoding.getKeys();
101: while (i.hasMoreElements()) {
102: Buffer type = normalizeMimeType((String) i.nextElement());
103: __encodings.put(type, encoding.getString(type.toString()));
104: }
105:
106: TEXT_HTML_BUFFER.setAssociate("ISO-8859-1",
107: TEXT_HTML_8859_1_BUFFER);
108: TEXT_HTML_BUFFER.setAssociate("ISO_8859_1",
109: TEXT_HTML_8859_1_BUFFER);
110: TEXT_HTML_BUFFER.setAssociate("iso-8859-1",
111: TEXT_HTML_8859_1_BUFFER);
112: TEXT_PLAIN_BUFFER.setAssociate("ISO-8859-1",
113: TEXT_PLAIN_8859_1_BUFFER);
114: TEXT_PLAIN_BUFFER.setAssociate("ISO_8859_1",
115: TEXT_PLAIN_8859_1_BUFFER);
116: TEXT_PLAIN_BUFFER.setAssociate("iso-8859-1",
117: TEXT_PLAIN_8859_1_BUFFER);
118: TEXT_XML_BUFFER.setAssociate("ISO-8859-1",
119: TEXT_XML_8859_1_BUFFER);
120: TEXT_XML_BUFFER.setAssociate("ISO_8859_1",
121: TEXT_XML_8859_1_BUFFER);
122: TEXT_XML_BUFFER.setAssociate("iso-8859-1",
123: TEXT_XML_8859_1_BUFFER);
124:
125: TEXT_HTML_BUFFER.setAssociate("UTF-8", TEXT_HTML_UTF_8_BUFFER);
126: TEXT_HTML_BUFFER.setAssociate("UTF8", TEXT_HTML_UTF_8_BUFFER);
127: TEXT_HTML_BUFFER.setAssociate("utf8", TEXT_HTML_UTF_8_BUFFER);
128: TEXT_HTML_BUFFER.setAssociate("utf-8", TEXT_HTML_UTF_8_BUFFER);
129: TEXT_PLAIN_BUFFER
130: .setAssociate("UTF-8", TEXT_PLAIN_UTF_8_BUFFER);
131: TEXT_PLAIN_BUFFER.setAssociate("UTF8", TEXT_PLAIN_UTF_8_BUFFER);
132: TEXT_PLAIN_BUFFER
133: .setAssociate("utf-8", TEXT_PLAIN_UTF_8_BUFFER);
134: TEXT_XML_BUFFER.setAssociate("UTF-8", TEXT_XML_UTF_8_BUFFER);
135: TEXT_XML_BUFFER.setAssociate("utf8", TEXT_XML_UTF_8_BUFFER);
136: TEXT_XML_BUFFER.setAssociate("UTF8", TEXT_XML_UTF_8_BUFFER);
137: TEXT_XML_BUFFER.setAssociate("utf-8", TEXT_XML_UTF_8_BUFFER);
138: }
139:
140: /* ------------------------------------------------------------ */
141: private Map _mimeMap;
142:
143: /* ------------------------------------------------------------ */
144: /** Constructor.
145: */
146: public MimeTypes() {
147: }
148:
149: /* ------------------------------------------------------------ */
150: public synchronized Map getMimeMap() {
151: return _mimeMap;
152: }
153:
154: /* ------------------------------------------------------------ */
155: /**
156: * @param mimeMap A Map of file extension to mime-type.
157: */
158: public void setMimeMap(Map mimeMap) {
159: if (mimeMap == null) {
160: _mimeMap = null;
161: return;
162: }
163:
164: Map m = new HashMap();
165: Iterator i = mimeMap.entrySet().iterator();
166: while (i.hasNext()) {
167: Map.Entry entry = (Map.Entry) i.next();
168: m.put(entry.getKey(), normalizeMimeType(entry.getValue()
169: .toString()));
170: }
171: _mimeMap = m;
172: }
173:
174: /* ------------------------------------------------------------ */
175: /** Get the MIME type by filename extension.
176: * @param filename A file name
177: * @return MIME type matching the longest dot extension of the
178: * file name.
179: */
180: public Buffer getMimeByExtension(String filename) {
181: Buffer type = null;
182:
183: if (filename != null) {
184: int i = -1;
185: while (type == null) {
186: i = filename.indexOf(".", i + 1);
187:
188: if (i < 0 || i >= filename.length())
189: break;
190:
191: String ext = StringUtil.asciiToLowerCase(filename
192: .substring(i + 1));
193: if (_mimeMap != null)
194: type = (Buffer) _mimeMap.get(ext);
195: if (type == null)
196: type = (Buffer) __dftMimeMap.get(ext);
197: }
198: }
199:
200: if (type == null) {
201: if (_mimeMap != null)
202: type = (Buffer) _mimeMap.get("*");
203: if (type == null)
204: type = (Buffer) __dftMimeMap.get("*");
205: }
206:
207: return type;
208: }
209:
210: /* ------------------------------------------------------------ */
211: /** Set a mime mapping
212: * @param extension
213: * @param type
214: */
215: public void addMimeMapping(String extension, String type) {
216: if (_mimeMap == null)
217: _mimeMap = new HashMap();
218:
219: _mimeMap.put(StringUtil.asciiToLowerCase(extension),
220: normalizeMimeType(type));
221: }
222:
223: /* ------------------------------------------------------------ */
224: private static synchronized Buffer normalizeMimeType(String type) {
225: Buffer b = CACHE.get(type);
226: if (b == null)
227: b = CACHE.add(type, __index++);
228: return b;
229: }
230:
231: /* ------------------------------------------------------------ */
232: public static String getCharsetFromContentType(Buffer value) {
233: if (value instanceof CachedBuffer) {
234: switch (((CachedBuffer) value).getOrdinal()) {
235: case TEXT_HTML_8859_1_ORDINAL:
236: case TEXT_PLAIN_8859_1_ORDINAL:
237: case TEXT_XML_8859_1_ORDINAL:
238: return StringUtil.__ISO_8859_1;
239:
240: case TEXT_HTML_UTF_8_ORDINAL:
241: case TEXT_PLAIN_UTF_8_ORDINAL:
242: case TEXT_XML_UTF_8_ORDINAL:
243: return StringUtil.__UTF8;
244: }
245: }
246:
247: String charset = value.toString();
248: int i = charset.indexOf(';');
249: if (i > 0) {
250: i = charset.indexOf("charset", i);
251: if (i > 0) {
252: i = charset.indexOf('=', i + 6);
253: if (i > 0) {
254: int s = i + 1;
255: while (s < charset.length()
256: && charset.charAt(s) == ' ')
257: s++;
258: i = charset.indexOf(' ', s);
259: if (i < 0)
260: i = charset.indexOf(';', s);
261: if (i < 0)
262: return charset.substring(s);
263: return charset.substring(s, i);
264: }
265: }
266: }
267:
268: return null;
269: }
270:
271: }
|