blob: 43bf32755f21efe0fcd9669bec18f53892b56306 [file] [log] [blame]
/*
* 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);
}
}