001: /*
002: * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.activation.registries;
027:
028: import java.io.*;
029: import java.util.*;
030:
031: public class MimeTypeFile {
032: private String fname = null;
033: private Hashtable type_hash = new Hashtable();
034:
035: /**
036: * The construtor that takes a filename as an argument.
037: *
038: * @param new_fname The file name of the mime types file.
039: */
040: public MimeTypeFile(String new_fname) throws IOException {
041: File mime_file = null;
042: FileReader fr = null;
043:
044: fname = new_fname; // remember the file name
045:
046: mime_file = new File(fname); // get a file object
047:
048: fr = new FileReader(mime_file);
049:
050: try {
051: parse(new BufferedReader(fr));
052: } finally {
053: try {
054: fr.close(); // close it
055: } catch (IOException e) {
056: // ignore it
057: }
058: }
059: }
060:
061: public MimeTypeFile(InputStream is) throws IOException {
062: parse(new BufferedReader(
063: new InputStreamReader(is, "iso-8859-1")));
064: }
065:
066: /**
067: * Creates an empty DB.
068: */
069: public MimeTypeFile() {
070: }
071:
072: /**
073: * get the MimeTypeEntry based on the file extension
074: */
075: public MimeTypeEntry getMimeTypeEntry(String file_ext) {
076: return (MimeTypeEntry) type_hash.get((Object) file_ext);
077: }
078:
079: /**
080: * Get the MIME type string corresponding to the file extension.
081: */
082: public String getMIMETypeString(String file_ext) {
083: MimeTypeEntry entry = this .getMimeTypeEntry(file_ext);
084:
085: if (entry != null)
086: return entry.getMIMEType();
087: else
088: return null;
089: }
090:
091: /**
092: * Appends string of entries to the types registry, must be valid
093: * .mime.types format.
094: * A mime.types entry is one of two forms:
095: *
096: * type/subtype ext1 ext2 ...
097: * or
098: * type=type/subtype desc="description of type" exts=ext1,ext2,...
099: *
100: * Example:
101: * # this is a test
102: * audio/basic au
103: * text/plain txt text
104: * type=application/postscript exts=ps,eps
105: */
106: public void appendToRegistry(String mime_types) {
107: try {
108: parse(new BufferedReader(new StringReader(mime_types)));
109: } catch (IOException ex) {
110: // can't happen
111: }
112: }
113:
114: /**
115: * Parse a stream of mime.types entries.
116: */
117: private void parse(BufferedReader buf_reader) throws IOException {
118: String line = null, prev = null;
119:
120: while ((line = buf_reader.readLine()) != null) {
121: if (prev == null)
122: prev = line;
123: else
124: prev += line;
125: int end = prev.length();
126: if (prev.length() > 0 && prev.charAt(end - 1) == '\\') {
127: prev = prev.substring(0, end - 1);
128: continue;
129: }
130: this .parseEntry(prev);
131: prev = null;
132: }
133: if (prev != null)
134: this .parseEntry(prev);
135: }
136:
137: /**
138: * Parse single mime.types entry.
139: */
140: private void parseEntry(String line) {
141: String mime_type = null;
142: String file_ext = null;
143: line = line.trim();
144:
145: if (line.length() == 0) // empty line...
146: return; // BAIL!
147:
148: // check to see if this is a comment line?
149: if (line.charAt(0) == '#')
150: return; // then we are done!
151:
152: // is it a new format line or old format?
153: if (line.indexOf('=') > 0) {
154: // new format
155: LineTokenizer lt = new LineTokenizer(line);
156: while (lt.hasMoreTokens()) {
157: String name = lt.nextToken();
158: String value = null;
159: if (lt.hasMoreTokens() && lt.nextToken().equals("=")
160: && lt.hasMoreTokens())
161: value = lt.nextToken();
162: if (value == null) {
163: if (LogSupport.isLoggable())
164: LogSupport
165: .log("Bad .mime.types entry: " + line);
166: return;
167: }
168: if (name.equals("type"))
169: mime_type = value;
170: else if (name.equals("exts")) {
171: StringTokenizer st = new StringTokenizer(value, ",");
172: while (st.hasMoreTokens()) {
173: file_ext = st.nextToken();
174: MimeTypeEntry entry = new MimeTypeEntry(
175: mime_type, file_ext);
176: type_hash.put(file_ext, entry);
177: if (LogSupport.isLoggable())
178: LogSupport
179: .log("Added: " + entry.toString());
180: }
181: }
182: }
183: } else {
184: // old format
185: // count the tokens
186: StringTokenizer strtok = new StringTokenizer(line);
187: int num_tok = strtok.countTokens();
188:
189: if (num_tok == 0) // empty line
190: return;
191:
192: mime_type = strtok.nextToken(); // get the MIME type
193:
194: while (strtok.hasMoreTokens()) {
195: MimeTypeEntry entry = null;
196:
197: file_ext = strtok.nextToken();
198: entry = new MimeTypeEntry(mime_type, file_ext);
199: type_hash.put(file_ext, entry);
200: if (LogSupport.isLoggable())
201: LogSupport.log("Added: " + entry.toString());
202: }
203: }
204: }
205:
206: // for debugging
207: /*
208: public static void main(String[] argv) throws Exception {
209: MimeTypeFile mf = new MimeTypeFile(argv[0]);
210: System.out.println("ext " + argv[1] + " type " +
211: mf.getMIMETypeString(argv[1]));
212: System.exit(0);
213: }
214: */
215: }
216:
217: class LineTokenizer {
218: private int currentPosition;
219: private int maxPosition;
220: private String str;
221: private Vector stack = new Vector();
222: private static final String singles = "="; // single character tokens
223:
224: /**
225: * Constructs a tokenizer for the specified string.
226: * <p>
227: *
228: * @param str a string to be parsed.
229: */
230: public LineTokenizer(String str) {
231: currentPosition = 0;
232: this .str = str;
233: maxPosition = str.length();
234: }
235:
236: /**
237: * Skips white space.
238: */
239: private void skipWhiteSpace() {
240: while ((currentPosition < maxPosition)
241: && Character.isWhitespace(str.charAt(currentPosition))) {
242: currentPosition++;
243: }
244: }
245:
246: /**
247: * Tests if there are more tokens available from this tokenizer's string.
248: *
249: * @return <code>true</code> if there are more tokens available from this
250: * tokenizer's string; <code>false</code> otherwise.
251: */
252: public boolean hasMoreTokens() {
253: if (stack.size() > 0)
254: return true;
255: skipWhiteSpace();
256: return (currentPosition < maxPosition);
257: }
258:
259: /**
260: * Returns the next token from this tokenizer.
261: *
262: * @return the next token from this tokenizer.
263: * @exception NoSuchElementException if there are no more tokens in this
264: * tokenizer's string.
265: */
266: public String nextToken() {
267: int size = stack.size();
268: if (size > 0) {
269: String t = (String) stack.elementAt(size - 1);
270: stack.removeElementAt(size - 1);
271: return t;
272: }
273: skipWhiteSpace();
274:
275: if (currentPosition >= maxPosition) {
276: throw new NoSuchElementException();
277: }
278:
279: int start = currentPosition;
280: char c = str.charAt(start);
281: if (c == '"') {
282: currentPosition++;
283: boolean filter = false;
284: while (currentPosition < maxPosition) {
285: c = str.charAt(currentPosition++);
286: if (c == '\\') {
287: currentPosition++;
288: filter = true;
289: } else if (c == '"') {
290: String s;
291:
292: if (filter) {
293: StringBuffer sb = new StringBuffer();
294: for (int i = start + 1; i < currentPosition - 1; i++) {
295: c = str.charAt(i);
296: if (c != '\\')
297: sb.append(c);
298: }
299: s = sb.toString();
300: } else
301: s = str.substring(start + 1,
302: currentPosition - 1);
303: return s;
304: }
305: }
306: } else if (singles.indexOf(c) >= 0) {
307: currentPosition++;
308: } else {
309: while ((currentPosition < maxPosition)
310: && singles.indexOf(str.charAt(currentPosition)) < 0
311: && !Character.isWhitespace(str
312: .charAt(currentPosition))) {
313: currentPosition++;
314: }
315: }
316: return str.substring(start, currentPosition);
317: }
318:
319: public void pushToken(String token) {
320: stack.addElement(token);
321: }
322: }
|