| /* |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
| * |
| * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved. |
| * |
| * The contents of this file are subject to the terms of either the GNU |
| * General Public License Version 2 only ("GPL") or the Common Development |
| * and Distribution License("CDDL") (collectively, the "License"). You |
| * may not use this file except in compliance with the License. You can |
| * obtain a copy of the License at |
| * https://oss.oracle.com/licenses/CDDL+GPL-1.1 |
| * or LICENSE.txt. See the License for the specific |
| * language governing permissions and limitations under the License. |
| * |
| * When distributing the software, include this License Header Notice in each |
| * file and include the License file at LICENSE.txt. |
| * |
| * GPL Classpath Exception: |
| * Oracle designates this particular file as subject to the "Classpath" |
| * exception as provided by Oracle in the GPL Version 2 section of the License |
| * file that accompanied this code. |
| * |
| * Modifications: |
| * If applicable, add the following below the License Header, with the fields |
| * enclosed by brackets [] replaced by your own identifying information: |
| * "Portions Copyright [year] [name of copyright owner]" |
| * |
| * Contributor(s): |
| * If you wish your version of this file to be governed by only the CDDL or |
| * only the GPL Version 2, indicate your decision by adding "[Contributor] |
| * elects to include this software in this distribution under the [CDDL or GPL |
| * Version 2] license." If you don't indicate a single choice of license, a |
| * recipient has the option to distribute your version of this file under |
| * either the CDDL, the GPL Version 2 or to extend the choice of license to |
| * its licensees as provided above. However, if you add GPL Version 2 code |
| * and therefore, elected the GPL Version 2 license, then the option applies |
| * only if the new code is made subject to such option by the copyright |
| * holder. |
| */ |
| |
| package com.sun.activation.registries; |
| |
| import java.io.*; |
| import java.util.*; |
| |
| public class MimeTypeFile { |
| private String fname = null; |
| private Hashtable type_hash = new Hashtable(); |
| |
| /** |
| * The construtor that takes a filename as an argument. |
| * |
| * @param new_fname The file name of the mime types file. |
| */ |
| public MimeTypeFile(String new_fname) throws IOException { |
| File mime_file = null; |
| FileReader fr = null; |
| |
| fname = new_fname; // remember the file name |
| |
| mime_file = new File(fname); // get a file object |
| |
| fr = new FileReader(mime_file); |
| |
| try { |
| parse(new BufferedReader(fr)); |
| } finally { |
| try { |
| fr.close(); // close it |
| } catch (IOException e) { |
| // ignore it |
| } |
| } |
| } |
| |
| public MimeTypeFile(InputStream is) throws IOException { |
| parse(new BufferedReader(new InputStreamReader(is, "iso-8859-1"))); |
| } |
| |
| /** |
| * Creates an empty DB. |
| */ |
| public MimeTypeFile() { |
| } |
| |
| /** |
| * get the MimeTypeEntry based on the file extension |
| */ |
| public MimeTypeEntry getMimeTypeEntry(String file_ext) { |
| return (MimeTypeEntry)type_hash.get((Object)file_ext); |
| } |
| |
| /** |
| * Get the MIME type string corresponding to the file extension. |
| */ |
| public String getMIMETypeString(String file_ext) { |
| MimeTypeEntry entry = this.getMimeTypeEntry(file_ext); |
| |
| if (entry != null) |
| return entry.getMIMEType(); |
| else |
| return null; |
| } |
| |
| /** |
| * Appends string of entries to the types registry, must be valid |
| * .mime.types format. |
| * A mime.types entry is one of two forms: |
| * |
| * type/subtype ext1 ext2 ... |
| * or |
| * type=type/subtype desc="description of type" exts=ext1,ext2,... |
| * |
| * Example: |
| * # this is a test |
| * audio/basic au |
| * text/plain txt text |
| * type=application/postscript exts=ps,eps |
| */ |
| public void appendToRegistry(String mime_types) { |
| try { |
| parse(new BufferedReader(new StringReader(mime_types))); |
| } catch (IOException ex) { |
| // can't happen |
| } |
| } |
| |
| /** |
| * Parse a stream of mime.types entries. |
| */ |
| private void parse(BufferedReader buf_reader) throws IOException { |
| String line = null, prev = null; |
| |
| while ((line = buf_reader.readLine()) != null) { |
| if (prev == null) |
| prev = line; |
| else |
| prev += line; |
| int end = prev.length(); |
| if (prev.length() > 0 && prev.charAt(end - 1) == '\\') { |
| prev = prev.substring(0, end - 1); |
| continue; |
| } |
| this.parseEntry(prev); |
| prev = null; |
| } |
| if (prev != null) |
| this.parseEntry(prev); |
| } |
| |
| /** |
| * Parse single mime.types entry. |
| */ |
| private void parseEntry(String line) { |
| String mime_type = null; |
| String file_ext = null; |
| line = line.trim(); |
| |
| if (line.length() == 0) // empty line... |
| return; // BAIL! |
| |
| // check to see if this is a comment line? |
| if (line.charAt(0) == '#') |
| return; // then we are done! |
| |
| // is it a new format line or old format? |
| if (line.indexOf('=') > 0) { |
| // new format |
| LineTokenizer lt = new LineTokenizer(line); |
| while (lt.hasMoreTokens()) { |
| String name = lt.nextToken(); |
| String value = null; |
| if (lt.hasMoreTokens() && lt.nextToken().equals("=") && |
| lt.hasMoreTokens()) |
| value = lt.nextToken(); |
| if (value == null) { |
| if (LogSupport.isLoggable()) |
| LogSupport.log("Bad .mime.types entry: " + line); |
| return; |
| } |
| if (name.equals("type")) |
| mime_type = value; |
| else if (name.equals("exts")) { |
| StringTokenizer st = new StringTokenizer(value, ","); |
| while (st.hasMoreTokens()) { |
| file_ext = st.nextToken(); |
| MimeTypeEntry entry = |
| new MimeTypeEntry(mime_type, file_ext); |
| type_hash.put(file_ext, entry); |
| if (LogSupport.isLoggable()) |
| LogSupport.log("Added: " + entry.toString()); |
| } |
| } |
| } |
| } else { |
| // old format |
| // count the tokens |
| StringTokenizer strtok = new StringTokenizer(line); |
| int num_tok = strtok.countTokens(); |
| |
| if (num_tok == 0) // empty line |
| return; |
| |
| mime_type = strtok.nextToken(); // get the MIME type |
| |
| while (strtok.hasMoreTokens()) { |
| MimeTypeEntry entry = null; |
| |
| file_ext = strtok.nextToken(); |
| entry = new MimeTypeEntry(mime_type, file_ext); |
| type_hash.put(file_ext, entry); |
| if (LogSupport.isLoggable()) |
| LogSupport.log("Added: " + entry.toString()); |
| } |
| } |
| } |
| |
| // for debugging |
| /* |
| public static void main(String[] argv) throws Exception { |
| MimeTypeFile mf = new MimeTypeFile(argv[0]); |
| System.out.println("ext " + argv[1] + " type " + |
| mf.getMIMETypeString(argv[1])); |
| System.exit(0); |
| } |
| */ |
| } |
| |
| class LineTokenizer { |
| private int currentPosition; |
| private int maxPosition; |
| private String str; |
| private Vector stack = new Vector(); |
| private static final String singles = "="; // single character tokens |
| |
| /** |
| * Constructs a tokenizer for the specified string. |
| * <p> |
| * |
| * @param str a string to be parsed. |
| */ |
| public LineTokenizer(String str) { |
| currentPosition = 0; |
| this.str = str; |
| maxPosition = str.length(); |
| } |
| |
| /** |
| * Skips white space. |
| */ |
| private void skipWhiteSpace() { |
| while ((currentPosition < maxPosition) && |
| Character.isWhitespace(str.charAt(currentPosition))) { |
| currentPosition++; |
| } |
| } |
| |
| /** |
| * Tests if there are more tokens available from this tokenizer's string. |
| * |
| * @return <code>true</code> if there are more tokens available from this |
| * tokenizer's string; <code>false</code> otherwise. |
| */ |
| public boolean hasMoreTokens() { |
| if (stack.size() > 0) |
| return true; |
| skipWhiteSpace(); |
| return (currentPosition < maxPosition); |
| } |
| |
| /** |
| * Returns the next token from this tokenizer. |
| * |
| * @return the next token from this tokenizer. |
| * @exception NoSuchElementException if there are no more tokens in this |
| * tokenizer's string. |
| */ |
| public String nextToken() { |
| int size = stack.size(); |
| if (size > 0) { |
| String t = (String)stack.elementAt(size - 1); |
| stack.removeElementAt(size - 1); |
| return t; |
| } |
| skipWhiteSpace(); |
| |
| if (currentPosition >= maxPosition) { |
| throw new NoSuchElementException(); |
| } |
| |
| int start = currentPosition; |
| char c = str.charAt(start); |
| if (c == '"') { |
| currentPosition++; |
| boolean filter = false; |
| while (currentPosition < maxPosition) { |
| c = str.charAt(currentPosition++); |
| if (c == '\\') { |
| currentPosition++; |
| filter = true; |
| } else if (c == '"') { |
| String s; |
| |
| if (filter) { |
| StringBuffer sb = new StringBuffer(); |
| for (int i = start + 1; i < currentPosition - 1; i++) { |
| c = str.charAt(i); |
| if (c != '\\') |
| sb.append(c); |
| } |
| s = sb.toString(); |
| } else |
| s = str.substring(start + 1, currentPosition - 1); |
| return s; |
| } |
| } |
| } else if (singles.indexOf(c) >= 0) { |
| currentPosition++; |
| } else { |
| while ((currentPosition < maxPosition) && |
| singles.indexOf(str.charAt(currentPosition)) < 0 && |
| !Character.isWhitespace(str.charAt(currentPosition))) { |
| currentPosition++; |
| } |
| } |
| return str.substring(start, currentPosition); |
| } |
| |
| public void pushToken(String token) { |
| stack.addElement(token); |
| } |
| } |