/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. 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://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/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 glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [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.
 */

/*
 * @(#)MimeTypeFile.java	1.9 07/05/14
 */

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);
    }
}
