1 /* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.activation.registries; 27 28 import java.io.*; 29 import java.util.*; 30 31 public class MimeTypeFile { 32 private String fname = null; 33 private Hashtable type_hash = new Hashtable(); 34 35 /** 36 * The construtor that takes a filename as an argument. 37 * 38 * @param new_fname The file name of the mime types file. 39 */ 40 public MimeTypeFile(String new_fname) throws IOException { 41 File mime_file = null; 42 FileReader fr = null; 43 44 fname = new_fname; // remember the file name 45 46 mime_file = new File(fname); // get a file object 47 48 fr = new FileReader(mime_file); 49 50 try { 51 parse(new BufferedReader(fr)); 52 } finally { 53 try { 54 fr.close(); // close it 55 } catch (IOException e) { 56 // ignore it 57 } 58 } 59 } 60 61 public MimeTypeFile(InputStream is) throws IOException { 62 parse(new BufferedReader(new InputStreamReader(is, "iso-8859-1"))); 63 } 64 65 /** 66 * Creates an empty DB. 67 */ 68 public MimeTypeFile() { 69 } 70 71 /** 72 * get the MimeTypeEntry based on the file extension 73 */ 74 public MimeTypeEntry getMimeTypeEntry(String file_ext) { 75 return (MimeTypeEntry)type_hash.get((Object)file_ext); 76 } 77 78 /** 79 * Get the MIME type string corresponding to the file extension. 80 */ 81 public String getMIMETypeString(String file_ext) { 82 MimeTypeEntry entry = this.getMimeTypeEntry(file_ext); 83 84 if (entry != null) 85 return entry.getMIMEType(); 86 else 87 return null; 88 } 89 90 /** 91 * Appends string of entries to the types registry, must be valid 92 * .mime.types format. 93 * A mime.types entry is one of two forms: 94 * 95 * type/subtype ext1 ext2 ... 96 * or 97 * type=type/subtype desc="description of type" exts=ext1,ext2,... 98 * 99 * Example: 100 * # this is a test 101 * audio/basic au 102 * text/plain txt text 103 * type=application/postscript exts=ps,eps 104 */ 105 public void appendToRegistry(String mime_types) { 106 try { 107 parse(new BufferedReader(new StringReader(mime_types))); 108 } catch (IOException ex) { 109 // can't happen 110 } 111 } 112 113 /** 114 * Parse a stream of mime.types entries. 115 */ 116 private void parse(BufferedReader buf_reader) throws IOException { 117 String line = null, prev = null; 118 119 while ((line = buf_reader.readLine()) != null) { 120 if (prev == null) 121 prev = line; 122 else 123 prev += line; 124 int end = prev.length(); 125 if (prev.length() > 0 && prev.charAt(end - 1) == '\\') { 126 prev = prev.substring(0, end - 1); 127 continue; 128 } 129 this.parseEntry(prev); 130 prev = null; 131 } 132 if (prev != null) 133 this.parseEntry(prev); 134 } 135 136 /** 137 * Parse single mime.types entry. 138 */ 139 private void parseEntry(String line) { 140 String mime_type = null; 141 String file_ext = null; 142 line = line.trim(); 143 144 if (line.length() == 0) // empty line... 145 return; // BAIL! 146 147 // check to see if this is a comment line? 148 if (line.charAt(0) == '#') 149 return; // then we are done! 150 151 // is it a new format line or old format? 152 if (line.indexOf('=') > 0) { 153 // new format 154 LineTokenizer lt = new LineTokenizer(line); 155 while (lt.hasMoreTokens()) { 156 String name = lt.nextToken(); 157 String value = null; 158 if (lt.hasMoreTokens() && lt.nextToken().equals("=") && 159 lt.hasMoreTokens()) 160 value = lt.nextToken(); 161 if (value == null) { 162 if (LogSupport.isLoggable()) 163 LogSupport.log("Bad .mime.types entry: " + line); 164 return; 165 } 166 if (name.equals("type")) 167 mime_type = value; 168 else if (name.equals("exts")) { 169 StringTokenizer st = new StringTokenizer(value, ","); 170 while (st.hasMoreTokens()) { 171 file_ext = st.nextToken(); 172 MimeTypeEntry entry = 173 new MimeTypeEntry(mime_type, file_ext); 174 type_hash.put(file_ext, entry); 175 if (LogSupport.isLoggable()) 176 LogSupport.log("Added: " + entry.toString()); 177 } 178 } 179 } 180 } else { 181 // old format 182 // count the tokens 183 StringTokenizer strtok = new StringTokenizer(line); 184 int num_tok = strtok.countTokens(); 185 186 if (num_tok == 0) // empty line 187 return; 188 189 mime_type = strtok.nextToken(); // get the MIME type 190 191 while (strtok.hasMoreTokens()) { 192 MimeTypeEntry entry = null; 193 194 file_ext = strtok.nextToken(); 195 entry = new MimeTypeEntry(mime_type, file_ext); 196 type_hash.put(file_ext, entry); 197 if (LogSupport.isLoggable()) 198 LogSupport.log("Added: " + entry.toString()); 199 } 200 } 201 } 202 203 // for debugging 204 /* 205 public static void main(String[] argv) throws Exception { 206 MimeTypeFile mf = new MimeTypeFile(argv[0]); 207 System.out.println("ext " + argv[1] + " type " + 208 mf.getMIMETypeString(argv[1])); 209 System.exit(0); 210 } 211 */ 212 } 213 214 class LineTokenizer { 215 private int currentPosition; 216 private int maxPosition; 217 private String str; 218 private Vector stack = new Vector(); 219 private static final String singles = "="; // single character tokens 220 221 /** 222 * Constructs a tokenizer for the specified string. 223 * <p> 224 * 225 * @param str a string to be parsed. 226 */ 227 public LineTokenizer(String str) { 228 currentPosition = 0; 229 this.str = str; 230 maxPosition = str.length(); 231 } 232 233 /** 234 * Skips white space. 235 */ 236 private void skipWhiteSpace() { 237 while ((currentPosition < maxPosition) && 238 Character.isWhitespace(str.charAt(currentPosition))) { 239 currentPosition++; 240 } 241 } 242 243 /** 244 * Tests if there are more tokens available from this tokenizer's string. 245 * 246 * @return <code>true</code> if there are more tokens available from this 247 * tokenizer's string; <code>false</code> otherwise. 248 */ 249 public boolean hasMoreTokens() { 250 if (stack.size() > 0) 251 return true; 252 skipWhiteSpace(); 253 return (currentPosition < maxPosition); 254 } 255 256 /** 257 * Returns the next token from this tokenizer. 258 * 259 * @return the next token from this tokenizer. 260 * @exception NoSuchElementException if there are no more tokens in this 261 * tokenizer's string. 262 */ 263 public String nextToken() { 264 int size = stack.size(); 265 if (size > 0) { 266 String t = (String)stack.elementAt(size - 1); 267 stack.removeElementAt(size - 1); 268 return t; 269 } 270 skipWhiteSpace(); 271 272 if (currentPosition >= maxPosition) { 273 throw new NoSuchElementException(); 274 } 275 276 int start = currentPosition; 277 char c = str.charAt(start); 278 if (c == '"') { 279 currentPosition++; 280 boolean filter = false; 281 while (currentPosition < maxPosition) { 282 c = str.charAt(currentPosition++); 283 if (c == '\\') { 284 currentPosition++; 285 filter = true; 286 } else if (c == '"') { 287 String s; 288 289 if (filter) { 290 StringBuffer sb = new StringBuffer(); 291 for (int i = start + 1; i < currentPosition - 1; i++) { 292 c = str.charAt(i); 293 if (c != '\\') 294 sb.append(c); 295 } 296 s = sb.toString(); 297 } else 298 s = str.substring(start + 1, currentPosition - 1); 299 return s; 300 } 301 } 302 } else if (singles.indexOf(c) >= 0) { 303 currentPosition++; 304 } else { 305 while ((currentPosition < maxPosition) && 306 singles.indexOf(str.charAt(currentPosition)) < 0 && 307 !Character.isWhitespace(str.charAt(currentPosition))) { 308 currentPosition++; 309 } 310 } 311 return str.substring(start, currentPosition); 312 } 313 314 public void pushToken(String token) { 315 stack.addElement(token); 316 } 317 }