/*
 * 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 MailcapFile {

    /**
     * A Map indexed by MIME type (string) that references
     * a Map of commands for each type.  The comand Map
     * is indexed by the command name and references a List of
     * class names (strings) for each command.
     */
    private Map type_hash = new HashMap();

    /**
     * Another Map like above, but for fallback entries.
     */
    private Map fallback_hash = new HashMap();

    /**
     * A Map indexed by MIME type (string) that references
     * a List of native commands (string) corresponding to the type.
     */
    private Map native_commands = new HashMap();

    private static boolean addReverse = false;

    static {
	try {
	    addReverse = Boolean.getBoolean("javax.activation.addreverse");
	} catch (Throwable t) {
	    // ignore any errors
	}
    }

    /**
     * The constructor that takes a filename as an argument.
     *
     * @param new_fname The file name of the mailcap file.
     */
    public MailcapFile(String new_fname) throws IOException {
	if (LogSupport.isLoggable())
	    LogSupport.log("new MailcapFile: file " + new_fname);
	FileReader reader = null;
	try {
	    reader = new FileReader(new_fname);
	    parse(new BufferedReader(reader));
	} finally {
	    if (reader != null) {
		try {
		    reader.close();
		} catch (IOException ex) { }
	    }
	}
    }

    /**
     * The constructor that takes an input stream as an argument.
     *
     * @param is	the input stream
     */
    public MailcapFile(InputStream is) throws IOException {
	if (LogSupport.isLoggable())
	    LogSupport.log("new MailcapFile: InputStream");
	parse(new BufferedReader(new InputStreamReader(is, "iso-8859-1")));
    }

    /**
     * Mailcap file default constructor.
     */
    public MailcapFile() {
	if (LogSupport.isLoggable())
	    LogSupport.log("new MailcapFile: default");
    }

    /**
     * Get the Map of MailcapEntries based on the MIME type.
     *
     * <p>
     * <strong>Semantics:</strong> First check for the literal mime type,
     * if that fails looks for wildcard <type>/\* and return that. Return the
     * list of all that hit.
     */
    public Map getMailcapList(String mime_type) {
	Map search_result = null;
	Map wildcard_result = null;

	// first try the literal
	search_result = (Map)type_hash.get(mime_type);

	// ok, now try the wildcard
	int separator = mime_type.indexOf('/');
	String subtype = mime_type.substring(separator + 1);
	if (!subtype.equals("*")) {
	    String type = mime_type.substring(0, separator + 1) + "*";
	    wildcard_result = (Map)type_hash.get(type);

	    if (wildcard_result != null) { // damn, we have to merge!!!
		if (search_result != null)
		    search_result =
			mergeResults(search_result, wildcard_result);
		else
		    search_result = wildcard_result;
	    }
	}
	return search_result;
    }

    /**
     * Get the Map of fallback MailcapEntries based on the MIME type.
     *
     * <p>
     * <strong>Semantics:</strong> First check for the literal mime type,
     * if that fails looks for wildcard <type>/\* and return that. Return the
     * list of all that hit.
     */
    public Map getMailcapFallbackList(String mime_type) {
	Map search_result = null;
	Map wildcard_result = null;

	// first try the literal
	search_result = (Map)fallback_hash.get(mime_type);

	// ok, now try the wildcard
	int separator = mime_type.indexOf('/');
	String subtype = mime_type.substring(separator + 1);
	if (!subtype.equals("*")) {
	    String type = mime_type.substring(0, separator + 1) + "*";
	    wildcard_result = (Map)fallback_hash.get(type);

	    if (wildcard_result != null) { // damn, we have to merge!!!
		if (search_result != null)
		    search_result =
			mergeResults(search_result, wildcard_result);
		else
		    search_result = wildcard_result;
	    }
	}
	return search_result;
    }

    /**
     * Return all the MIME types known to this mailcap file.
     */
    public String[] getMimeTypes() {
	Set types = new HashSet(type_hash.keySet());
	types.addAll(fallback_hash.keySet());
	types.addAll(native_commands.keySet());
	String[] mts = new String[types.size()];
	mts = (String[])types.toArray(mts);
	return mts;
    }

    /**
     * Return all the native comands for the given MIME type.
     */
    public String[] getNativeCommands(String mime_type) {
	String[] cmds = null;
	List v =
	    (List)native_commands.get(mime_type.toLowerCase(Locale.ENGLISH));
	if (v != null) {
	    cmds = new String[v.size()];
	    cmds = (String[])v.toArray(cmds);
	}
	return cmds;
    }

    /**
     * Merge the first hash into the second.
     * This merge will only effect the hashtable that is
     * returned, we don't want to touch the one passed in since
     * its integrity must be maintained.
     */
    private Map mergeResults(Map first, Map second) {
	Iterator verb_enum = second.keySet().iterator();
	Map clonedHash = new HashMap(first);

	// iterate through the verbs in the second map
	while (verb_enum.hasNext()) {
	    String verb = (String)verb_enum.next();
	    List cmdVector = (List)clonedHash.get(verb);
	    if (cmdVector == null) {
		clonedHash.put(verb, second.get(verb));
	    } else {
		// merge the two
		List oldV = (List)second.get(verb);
		cmdVector = new ArrayList(cmdVector);
		cmdVector.addAll(oldV);
		clonedHash.put(verb, cmdVector);
	    }
	}
	return clonedHash;
    }

    /**
     * appendToMailcap: Append to this Mailcap DB, use the mailcap
     * format:
     * Comment == "# <i>comment string</i>
     * Entry == "mimetype;        javabeanclass<nl>
     *
     * Example:
     * # this is a comment
     * image/gif       jaf.viewers.ImageViewer
     */
    public void appendToMailcap(String mail_cap) {
	if (LogSupport.isLoggable())
	    LogSupport.log("appendToMailcap: " + mail_cap);
	try {
	    parse(new StringReader(mail_cap));
	} catch (IOException ex) {
	    // can't happen
	}
    }

    /**
     * parse file into a hash table of MC Type Entry Obj
     */
    private void parse(Reader reader) throws IOException {
	BufferedReader buf_reader = new BufferedReader(reader);
	String line = null;
	String continued = null;

	while ((line = buf_reader.readLine()) != null) {
	    //    LogSupport.log("parsing line: " + line);

	    line = line.trim();

	    try {
		if (line.charAt(0) == '#')
		    continue;
		if (line.charAt(line.length() - 1) == '\\') {
		    if (continued != null)
			continued += line.substring(0, line.length() - 1);
		    else
			continued = line.substring(0, line.length() - 1);
		} else if (continued != null) {
		    // handle the two strings
		    continued = continued + line;
		    //	LogSupport.log("parse: " + continued);
		    try {
			parseLine(continued);
		    } catch (MailcapParseException e) {
			//e.printStackTrace();
		    }
		    continued = null;
		}
		else {
		    //	LogSupport.log("parse: " + line);
		    try {
			parseLine(line);
			// LogSupport.log("hash.size = " + type_hash.size());
		    } catch (MailcapParseException e) {
			//e.printStackTrace();
		    }
		}
	    } catch (StringIndexOutOfBoundsException e) {}
	}
    }

    /**
     *	A routine to parse individual entries in a Mailcap file.
     *
     *	Note that this routine does not handle line continuations.
     *	They should have been handled prior to calling this routine.
     */
    protected void parseLine(String mailcapEntry)
				throws MailcapParseException, IOException {
	MailcapTokenizer tokenizer = new MailcapTokenizer(mailcapEntry);
	tokenizer.setIsAutoquoting(false);

	if (LogSupport.isLoggable())
	    LogSupport.log("parse: " + mailcapEntry);
	//	parse the primary type
	int currentToken = tokenizer.nextToken();
	if (currentToken != MailcapTokenizer.STRING_TOKEN) {
	    reportParseError(MailcapTokenizer.STRING_TOKEN, currentToken,
					tokenizer.getCurrentTokenValue());
	}
	String primaryType =
	    tokenizer.getCurrentTokenValue().toLowerCase(Locale.ENGLISH);
	String subType = "*";

	//	parse the '/' between primary and sub
	//	if it's not present that's ok, we just don't have a subtype
	currentToken = tokenizer.nextToken();
	if ((currentToken != MailcapTokenizer.SLASH_TOKEN) &&
			(currentToken != MailcapTokenizer.SEMICOLON_TOKEN)) {
	    reportParseError(MailcapTokenizer.SLASH_TOKEN,
				MailcapTokenizer.SEMICOLON_TOKEN, currentToken,
				tokenizer.getCurrentTokenValue());
	}

	//	only need to look for a sub type if we got a '/'
	if (currentToken == MailcapTokenizer.SLASH_TOKEN) {
	    //	parse the sub type
	    currentToken = tokenizer.nextToken();
	    if (currentToken != MailcapTokenizer.STRING_TOKEN) {
		reportParseError(MailcapTokenizer.STRING_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
	    }
	    subType =
		tokenizer.getCurrentTokenValue().toLowerCase(Locale.ENGLISH);

	    //	get the next token to simplify the next step
	    currentToken = tokenizer.nextToken();
	}

	String mimeType = primaryType + "/" + subType;

	if (LogSupport.isLoggable())
	    LogSupport.log("  Type: " + mimeType);

	//	now setup the commands hashtable
	Map commands = new LinkedHashMap();	// keep commands in order found

	//	parse the ';' that separates the type from the parameters
	if (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) {
	    reportParseError(MailcapTokenizer.SEMICOLON_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
	}
	//	eat it

	//	parse the required view command
	tokenizer.setIsAutoquoting(true);
	currentToken = tokenizer.nextToken();
	tokenizer.setIsAutoquoting(false);
	if ((currentToken != MailcapTokenizer.STRING_TOKEN) &&
		    (currentToken != MailcapTokenizer.SEMICOLON_TOKEN)) {
	    reportParseError(MailcapTokenizer.STRING_TOKEN,
			    MailcapTokenizer.SEMICOLON_TOKEN, currentToken,
			    tokenizer.getCurrentTokenValue());
	}

	if (currentToken == MailcapTokenizer.STRING_TOKEN) {
	    // have a native comand, save the entire mailcap entry
	    //String nativeCommand = tokenizer.getCurrentTokenValue();
	    List v = (List)native_commands.get(mimeType);
	    if (v == null) {
		v = new ArrayList();
		v.add(mailcapEntry);
		native_commands.put(mimeType, v);
	    } else {
		// XXX - check for duplicates?
		v.add(mailcapEntry);
	    }
	}

	//	only have to get the next token if the current one isn't a ';'
	if (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) {
	    currentToken = tokenizer.nextToken();
	}

	// look for a ';' which will indicate whether
	// a parameter list is present or not
	if (currentToken == MailcapTokenizer.SEMICOLON_TOKEN) {
	    boolean isFallback = false;
	    do {
		//	eat the ';'

		//	parse the parameter name
		currentToken = tokenizer.nextToken();
		if (currentToken != MailcapTokenizer.STRING_TOKEN) {
		    reportParseError(MailcapTokenizer.STRING_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
		}
		String paramName = tokenizer.getCurrentTokenValue().
						toLowerCase(Locale.ENGLISH);

		//	parse the '=' which separates the name from the value
		currentToken = tokenizer.nextToken();
		if ((currentToken != MailcapTokenizer.EQUALS_TOKEN) &&
		    (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) &&
		    (currentToken != MailcapTokenizer.EOI_TOKEN)) {
		    reportParseError(MailcapTokenizer.EQUALS_TOKEN,
			    MailcapTokenizer.SEMICOLON_TOKEN,
			    MailcapTokenizer.EOI_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
		}

		//	we only have a useful command if it is named
		if (currentToken == MailcapTokenizer.EQUALS_TOKEN) {
		    //	eat it

		    //	parse the parameter value (which is autoquoted)
		    tokenizer.setIsAutoquoting(true);
		    currentToken = tokenizer.nextToken();
		    tokenizer.setIsAutoquoting(false);
		    if (currentToken != MailcapTokenizer.STRING_TOKEN) {
			reportParseError(MailcapTokenizer.STRING_TOKEN,
			currentToken, tokenizer.getCurrentTokenValue());
		    }
		    String paramValue =
				tokenizer.getCurrentTokenValue();

		    // add the class to the list iff it is one we care about
		    if (paramName.startsWith("x-java-")) {
			String commandName = paramName.substring(7);
			//	7 == "x-java-".length

			if (commandName.equals("fallback-entry") &&
			    paramValue.equalsIgnoreCase("true")) {
			    isFallback = true;
			} else {

			    //	setup the class entry list
			    if (LogSupport.isLoggable())
				LogSupport.log("    Command: " + commandName +
						    ", Class: " + paramValue);
			    List classes = (List)commands.get(commandName);
			    if (classes == null) {
				classes = new ArrayList();
				commands.put(commandName, classes);
			    }
			    if (addReverse)
				classes.add(0, paramValue);
			    else
				classes.add(paramValue);
			}
		    }

		    //	set up the next iteration
		    currentToken = tokenizer.nextToken();
		}
	    } while (currentToken == MailcapTokenizer.SEMICOLON_TOKEN);

	    Map masterHash = isFallback ? fallback_hash : type_hash;
	    Map curcommands =
		(Map)masterHash.get(mimeType);
	    if (curcommands == null) {
		masterHash.put(mimeType, commands);
	    } else {
		if (LogSupport.isLoggable())
		    LogSupport.log("Merging commands for type " + mimeType);
		// have to merge current and new commands
		// first, merge list of classes for commands already known
		Iterator cn = curcommands.keySet().iterator();
		while (cn.hasNext()) {
		    String cmdName = (String)cn.next();
		    List ccv = (List)curcommands.get(cmdName);
		    List cv = (List)commands.get(cmdName);
		    if (cv == null)
			continue;
		    // add everything in cv to ccv, if it's not already there
		    Iterator cvn = cv.iterator();
		    while (cvn.hasNext()) {
			String clazz = (String)cvn.next();
			if (!ccv.contains(clazz))
			    if (addReverse)
				ccv.add(0, clazz);
			    else
				ccv.add(clazz);
		    }
		}
		// now, add commands not previously known
		cn = commands.keySet().iterator();
		while (cn.hasNext()) {
		    String cmdName = (String)cn.next();
		    if (curcommands.containsKey(cmdName))
			continue;
		    List cv = (List)commands.get(cmdName);
		    curcommands.put(cmdName, cv);
		}
	    }
	} else if (currentToken != MailcapTokenizer.EOI_TOKEN) {
	    reportParseError(MailcapTokenizer.EOI_TOKEN,
		MailcapTokenizer.SEMICOLON_TOKEN,
		currentToken, tokenizer.getCurrentTokenValue());
	}
     }

     protected static void reportParseError(int expectedToken, int actualToken,
		String actualTokenValue) throws MailcapParseException {
     	throw new MailcapParseException("Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + " token.");
     }

     protected static void reportParseError(int expectedToken,
	int otherExpectedToken, int actualToken, String actualTokenValue)
					throws MailcapParseException {
     	throw new MailcapParseException("Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + " or a " +
		MailcapTokenizer.nameForToken(otherExpectedToken) + " token.");
     }

     protected static void reportParseError(int expectedToken,
	    int otherExpectedToken, int anotherExpectedToken, int actualToken,
	    String actualTokenValue) throws MailcapParseException {
	if (LogSupport.isLoggable())
	    LogSupport.log("PARSE ERROR: " + "Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + ", a " +
		MailcapTokenizer.nameForToken(otherExpectedToken) + ", or a " +
		MailcapTokenizer.nameForToken(anotherExpectedToken) + " token.");
     	throw new MailcapParseException("Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + ", a " +
		MailcapTokenizer.nameForToken(otherExpectedToken) + ", or a " +
		MailcapTokenizer.nameForToken(anotherExpectedToken) + " token.");
     }

     /** for debugging
     public static void	main(String[] args) throws Exception {
     	Map masterHash = new HashMap();
     	for (int i = 0; i < args.length; ++i) {
	    System.out.println("Entry " + i + ": " + args[i]);
	    parseLine(args[i], masterHash);
     	}

     	Enumeration types = masterHash.keys();
     	while (types.hasMoreElements()) {
	    String key = (String)types.nextElement();
	    System.out.println("MIME Type: " + key);

	    Map commandHash = (Map)masterHash.get(key);
	    Enumeration commands = commandHash.keys();
	    while (commands.hasMoreElements()) {
		String command = (String)commands.nextElement();
		System.out.println("    Command: " + command);

		Vector classes = (Vector)commandHash.get(command);
		for (int i = 0; i < classes.size(); ++i) {
			System.out.println("        Class: " +
					    (String)classes.elementAt(i));
		}
	    }

	    System.out.println("");
	}
    }
    */
}
