/*
 * 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 javax.activation;

import java.util.*;
import java.io.*;
import java.net.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.sun.activation.registries.MailcapFile;
import com.sun.activation.registries.LogSupport;

/**
 * MailcapCommandMap extends the CommandMap
 * abstract class. It implements a CommandMap whose configuration
 * is based on mailcap files
 * (<A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>).
 * The MailcapCommandMap can be configured both programmatically
 * and via configuration files.
 * <p>
 * <b>Mailcap file search order:</b><p>
 * The MailcapCommandMap looks in various places in the user's
 * system for mailcap file entries. When requests are made
 * to search for commands in the MailcapCommandMap, it searches  
 * mailcap files in the following order:
 * <ol>
 * <li> Programatically added entries to the MailcapCommandMap instance.
 * <li> The file <code>.mailcap</code> in the user's home directory.
 * <li> The file <code>mailcap</code> in the Java runtime.
 * <li> The file or resources named <code>META-INF/mailcap</code>.
 * <li> The file or resource named <code>META-INF/mailcap.default</code>
 * (usually found only in the <code>activation.jar</code> file).
 * </ol>
 * <p>
 * (The current implementation looks for the <code>mailcap</code> file
 * in the Java runtime in the directory <code><i>java.home</i>/conf</code>
 * if it exists, and otherwise in the directory
 * <code><i>java.home</i>/lib</code>, where <i>java.home</i> is the value
 * of the "java.home" System property.  Note that the "conf" directory was
 * introduced in JDK 9.)
 * <p>
 * <b>Mailcap file format:</b><p>
 *
 * Mailcap files must conform to the mailcap
 * file specification (RFC 1524, <i>A User Agent Configuration Mechanism
 * For Multimedia Mail Format Information</i>). 
 * The file format consists of entries corresponding to
 * particular MIME types. In general, the specification 
 * specifies <i>applications</i> for clients to use when they
 * themselves cannot operate on the specified MIME type. The 
 * MailcapCommandMap extends this specification by using a parameter mechanism
 * in mailcap files that allows JavaBeans(tm) components to be specified as
 * corresponding to particular commands for a MIME type.<p>
 *
 * When a mailcap file is
 * parsed, the MailcapCommandMap recognizes certain parameter signatures,
 * specifically those parameter names that begin with <code>x-java-</code>.
 * The MailcapCommandMap uses this signature to find
 * command entries for inclusion into its registries.
 * Parameter names with the form <code>x-java-&lt;name&gt;</code>
 * are read by the MailcapCommandMap as identifying a command
 * with the name <i>name</i>. When the <i>name</i> is <code>
 * content-handler</code> the MailcapCommandMap recognizes the class
 * signified by this parameter as a <i>DataContentHandler</i>.
 * All other commands are handled generically regardless of command 
 * name. The command implementation is specified by a fully qualified
 * class name of a JavaBean(tm) component. For example; a command for viewing
 * some data can be specified as: <code>x-java-view=com.foo.ViewBean</code>.<p>
 *
 * When the command name is <code>fallback-entry</code>, the value of
 * the command may be <code>true</code> or <code>false</code>.  An
 * entry for a MIME type that includes a parameter of
 * <code>x-java-fallback-entry=true</code> defines fallback commands
 * for that MIME type that will only be used if no non-fallback entry
 * can be found.  For example, an entry of the form <code>text/*; ;
 * x-java-fallback-entry=true; x-java-view=com.sun.TextViewer</code>
 * specifies a view command to be used for any text MIME type.  This
 * view command would only be used if a non-fallback view command for
 * the MIME type could not be found.<p>
 * 
 * MailcapCommandMap aware mailcap files have the 
 * following general form:<p>
 * <code>
 * # Comments begin with a '#' and continue to the end of the line.<br>
 * &lt;mime type&gt;; ; &lt;parameter list&gt;<br>
 * # Where a parameter list consists of one or more parameters,<br>
 * # where parameters look like: x-java-view=com.sun.TextViewer<br>
 * # and a parameter list looks like: <br>
 * text/plain; ; x-java-view=com.sun.TextViewer; x-java-edit=com.sun.TextEdit
 * <br>
 * # Note that mailcap entries that do not contain 'x-java' parameters<br>
 * # and comply to RFC 1524 are simply ignored:<br>
 * image/gif; /usr/dt/bin/sdtimage %s<br>
 *
 * </code>
 * <p>
 *
 * @author Bart Calder
 * @author Bill Shannon
 */

public class MailcapCommandMap extends CommandMap {
    /*
     * We manage a collection of databases, searched in order.
     */
    private MailcapFile[] DB;
    private static final int PROG = 0;	// programmatically added entries

    private static final String confDir;

    static {
	String dir = null;
	try {
	    dir = (String)AccessController.doPrivileged(
		new PrivilegedAction() {
		    public Object run() {
			String home = System.getProperty("java.home");
			String newdir = home + File.separator + "conf";
			File conf = new File(newdir);
			if (conf.exists())
			    return newdir + File.separator;
			else
			    return home + File.separator + "lib" + File.separator;
		    }
		});
	} catch (Exception ex) {
	    // ignore any exceptions
	}
	confDir = dir;
    }

    /**
     * The default Constructor.
     */
    public MailcapCommandMap() {
	super();
	List dbv = new ArrayList(5);	// usually 5 or less databases
	MailcapFile mf = null;
	dbv.add(null);		// place holder for PROG entry

	LogSupport.log("MailcapCommandMap: load HOME");
	try {
	    String user_home = System.getProperty("user.home");

	    if (user_home != null) {
		String path = user_home + File.separator + ".mailcap";
		mf = loadFile(path);
		if (mf != null)
		    dbv.add(mf);
	    }
	} catch (SecurityException ex) {}

	LogSupport.log("MailcapCommandMap: load SYS");
	try {
	    // check system's home
	    if (confDir != null) {
		mf = loadFile(confDir + "mailcap");
		if (mf != null)
		    dbv.add(mf);
	    }
	} catch (SecurityException ex) {}

	LogSupport.log("MailcapCommandMap: load JAR");
	// load from the app's jar file
	loadAllResources(dbv, "META-INF/mailcap");

	LogSupport.log("MailcapCommandMap: load DEF");
	mf = loadResource("/META-INF/mailcap.default");

	if (mf != null)
	    dbv.add(mf);

	DB = new MailcapFile[dbv.size()];
	DB = (MailcapFile[])dbv.toArray(DB);
    }

    /**
     * Load from the named resource.
     */
    private MailcapFile loadResource(String name) {
	InputStream clis = null;
	try {
	    clis = SecuritySupport.getResourceAsStream(this.getClass(), name);
	    if (clis != null) {
		MailcapFile mf = new MailcapFile(clis);
		if (LogSupport.isLoggable())
		    LogSupport.log("MailcapCommandMap: successfully loaded " +
			"mailcap file: " + name);
		return mf;
	    } else {
		if (LogSupport.isLoggable())
		    LogSupport.log("MailcapCommandMap: not loading " +
			"mailcap file: " + name);
	    }
	} catch (IOException e) {
	    if (LogSupport.isLoggable())
		LogSupport.log("MailcapCommandMap: can't load " + name, e);
	} catch (SecurityException sex) {
	    if (LogSupport.isLoggable())
		LogSupport.log("MailcapCommandMap: can't load " + name, sex);
	} finally {
	    try {
		if (clis != null)
		    clis.close();
	    } catch (IOException ex) { }	// ignore it
	}
	return null;
    }

    /**
     * Load all of the named resource.
     */
    private void loadAllResources(List v, String name) {
	boolean anyLoaded = false;
	try {
	    URL[] urls;
	    ClassLoader cld = null;
	    // First try the "application's" class loader.
	    cld = SecuritySupport.getContextClassLoader();
	    if (cld == null)
		cld = this.getClass().getClassLoader();
	    if (cld != null)
		urls = SecuritySupport.getResources(cld, name);
	    else
		urls = SecuritySupport.getSystemResources(name);
	    if (urls != null) {
		if (LogSupport.isLoggable())
		    LogSupport.log("MailcapCommandMap: getResources");
		for (int i = 0; i < urls.length; i++) {
		    URL url = urls[i];
		    InputStream clis = null;
		    if (LogSupport.isLoggable())
			LogSupport.log("MailcapCommandMap: URL " + url);
		    try {
			clis = SecuritySupport.openStream(url);
			if (clis != null) {
			    v.add(new MailcapFile(clis));
			    anyLoaded = true;
			    if (LogSupport.isLoggable())
				LogSupport.log("MailcapCommandMap: " +
				    "successfully loaded " +
				    "mailcap file from URL: " +
				    url);
			} else {
			    if (LogSupport.isLoggable())
				LogSupport.log("MailcapCommandMap: " +
				    "not loading mailcap " +
				    "file from URL: " + url);
			}
		    } catch (IOException ioex) {
			if (LogSupport.isLoggable())
			    LogSupport.log("MailcapCommandMap: can't load " +
						url, ioex);
		    } catch (SecurityException sex) {
			if (LogSupport.isLoggable())
			    LogSupport.log("MailcapCommandMap: can't load " +
						url, sex);
		    } finally {
			try {
			    if (clis != null)
				clis.close();
			} catch (IOException cex) { }
		    }
		}
	    }
	} catch (Exception ex) {
	    if (LogSupport.isLoggable())
		LogSupport.log("MailcapCommandMap: can't load " + name, ex);
	}

	// if failed to load anything, fall back to old technique, just in case
	if (!anyLoaded) {
	    if (LogSupport.isLoggable())
		LogSupport.log("MailcapCommandMap: !anyLoaded");
	    MailcapFile mf = loadResource("/" + name);
	    if (mf != null)
		v.add(mf);
	}
    }

    /**
     * Load from the named file.
     */
    private MailcapFile loadFile(String name) {
	MailcapFile mtf = null;

	try {
	    mtf = new MailcapFile(name);
	} catch (IOException e) {
	    //	e.printStackTrace();
	}
	return mtf;
    }

    /**
     * Constructor that allows the caller to specify the path
     * of a <i>mailcap</i> file.
     *
     * @param fileName The name of the <i>mailcap</i> file to open
     * @exception	IOException	if the file can't be accessed
     */
    public MailcapCommandMap(String fileName) throws IOException {
	this();

	if (LogSupport.isLoggable())
	    LogSupport.log("MailcapCommandMap: load PROG from " + fileName);
	if (DB[PROG] == null) {
	    DB[PROG] = new MailcapFile(fileName);
	}
    }


    /**
     * Constructor that allows the caller to specify an <i>InputStream</i>
     * containing a mailcap file.
     *
     * @param is	InputStream of the <i>mailcap</i> file to open
     */
    public MailcapCommandMap(InputStream is) {
	this();

	LogSupport.log("MailcapCommandMap: load PROG");
	if (DB[PROG] == null) {
	    try {
		DB[PROG] = new MailcapFile(is);
	    } catch (IOException ex) {
		// XXX - should throw it
	    }
	}
    }

    /**
     * Get the preferred command list for a MIME Type. The MailcapCommandMap
     * searches the mailcap files as described above under
     * <i>Mailcap file search order</i>.<p>
     *
     * The result of the search is a proper subset of available
     * commands in all mailcap files known to this instance of 
     * MailcapCommandMap.  The first entry for a particular command
     * is considered the preferred command.
     *
     * @param mimeType	the MIME type
     * @return the CommandInfo objects representing the preferred commands.
     */
    public synchronized CommandInfo[] getPreferredCommands(String mimeType) {
	List cmdList = new ArrayList();
	if (mimeType != null)
	    mimeType = mimeType.toLowerCase(Locale.ENGLISH);

	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    Map cmdMap = DB[i].getMailcapList(mimeType);
	    if (cmdMap != null)
		appendPrefCmdsToList(cmdMap, cmdList);
	}

	// now add the fallback commands
	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
	    if (cmdMap != null)
		appendPrefCmdsToList(cmdMap, cmdList);
	}

	CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()];
	cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos);

	return cmdInfos;
    }

    /**
     * Put the commands that are in the hash table, into the list.
     */
    private void appendPrefCmdsToList(Map cmdHash, List cmdList) {
	Iterator verb_enum = cmdHash.keySet().iterator();

	while (verb_enum.hasNext()) {
	    String verb = (String)verb_enum.next();
	    if (!checkForVerb(cmdList, verb)) {
		List cmdList2 = (List)cmdHash.get(verb); // get the list
		String className = (String)cmdList2.get(0);
		cmdList.add(new CommandInfo(verb, className));
	    }
	}
    }

    /**
     * Check the cmdList to see if this command exists, return
     * true if the verb is there.
     */
    private boolean checkForVerb(List cmdList, String verb) {
	Iterator ee = cmdList.iterator();
	while (ee.hasNext()) {
	    String enum_verb =
		(String)((CommandInfo)ee.next()).getCommandName();
	    if (enum_verb.equals(verb))
		return true;
	}
	return false;
    }

    /**
     * Get all the available commands in all mailcap files known to
     * this instance of MailcapCommandMap for this MIME type.
     *
     * @param mimeType	the MIME type
     * @return the CommandInfo objects representing all the commands.
     */
    public synchronized CommandInfo[] getAllCommands(String mimeType) {
	List cmdList = new ArrayList();
	if (mimeType != null)
	    mimeType = mimeType.toLowerCase(Locale.ENGLISH);

	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    Map cmdMap = DB[i].getMailcapList(mimeType);
	    if (cmdMap != null)
		appendCmdsToList(cmdMap, cmdList);
	}

	// now add the fallback commands
	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
	    if (cmdMap != null)
		appendCmdsToList(cmdMap, cmdList);
	}

	CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()];
	cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos);

	return cmdInfos;
    }

    /**
     * Put the commands that are in the hash table, into the list.
     */
    private void appendCmdsToList(Map typeHash, List cmdList) {
	Iterator verb_enum = typeHash.keySet().iterator();

	while (verb_enum.hasNext()) {
	    String verb = (String)verb_enum.next();
	    List cmdList2 = (List)typeHash.get(verb);
	    Iterator cmd_enum = ((List)cmdList2).iterator();

	    while (cmd_enum.hasNext()) {
		String cmd = (String)cmd_enum.next();
		cmdList.add(new CommandInfo(verb, cmd));
		// cmdList.add(0, new CommandInfo(verb, cmd));
	    }
	}
    }

    /**
     * Get the command corresponding to <code>cmdName</code> for the MIME type.
     *
     * @param mimeType	the MIME type
     * @param cmdName	the command name
     * @return the CommandInfo object corresponding to the command.
     */
    public synchronized CommandInfo getCommand(String mimeType,
							String cmdName) {
	if (mimeType != null)
	    mimeType = mimeType.toLowerCase(Locale.ENGLISH);

	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    Map cmdMap = DB[i].getMailcapList(mimeType);
	    if (cmdMap != null) {
		// get the cmd list for the cmd
		List v = (List)cmdMap.get(cmdName);
		if (v != null) {
		    String cmdClassName = (String)v.get(0);

		    if (cmdClassName != null)
			return new CommandInfo(cmdName, cmdClassName);
		}
	    }
	}

	// now try the fallback list
	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
	    if (cmdMap != null) {
		// get the cmd list for the cmd
		List v = (List)cmdMap.get(cmdName);
		if (v != null) {
		    String cmdClassName = (String)v.get(0);

		    if (cmdClassName != null)
			return new CommandInfo(cmdName, cmdClassName);
		}
	    }
	}
	return null;
    }

    /**
     * Add entries to the registry.  Programmatically 
     * added entries are searched before other entries.<p>
     *
     * The string that is passed in should be in mailcap
     * format.
     *
     * @param mail_cap a correctly formatted mailcap string
     */
    public synchronized void addMailcap(String mail_cap) {
	// check to see if one exists
	LogSupport.log("MailcapCommandMap: add to PROG");
	if (DB[PROG] == null)
	    DB[PROG] = new MailcapFile();

	DB[PROG].appendToMailcap(mail_cap);
    }

    /**
     * Return the DataContentHandler for the specified MIME type.
     *
     * @param mimeType	the MIME type
     * @return		the DataContentHandler
     */
    public synchronized DataContentHandler createDataContentHandler(
							String mimeType) {
	if (LogSupport.isLoggable())
	    LogSupport.log(
		"MailcapCommandMap: createDataContentHandler for " + mimeType);
	if (mimeType != null)
	    mimeType = mimeType.toLowerCase(Locale.ENGLISH);

	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    if (LogSupport.isLoggable())
		LogSupport.log("  search DB #" + i);
	    Map cmdMap = DB[i].getMailcapList(mimeType);
	    if (cmdMap != null) {
		List v = (List)cmdMap.get("content-handler");
		if (v != null) {
		    String name = (String)v.get(0);
		    DataContentHandler dch = getDataContentHandler(name);
		    if (dch != null)
			return dch;
		}
	    }
	}

	// now try the fallback entries
	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    if (LogSupport.isLoggable())
		LogSupport.log("  search fallback DB #" + i);
	    Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
	    if (cmdMap != null) {
		List v = (List)cmdMap.get("content-handler");
		if (v != null) {
		    String name = (String)v.get(0);
		    DataContentHandler dch = getDataContentHandler(name);
		    if (dch != null)
			return dch;
		}
	    }
	}
	return null;
    }

    private DataContentHandler getDataContentHandler(String name) {
	if (LogSupport.isLoggable())
	    LogSupport.log("    got content-handler");
	if (LogSupport.isLoggable())
	    LogSupport.log("      class " + name);
	try {
	    ClassLoader cld = null;
	    // First try the "application's" class loader.
	    cld = SecuritySupport.getContextClassLoader();
	    if (cld == null)
		cld = this.getClass().getClassLoader();
	    Class cl = null;
	    try {
		cl = cld.loadClass(name);
	    } catch (Exception ex) {
		// if anything goes wrong, do it the old way
		cl = Class.forName(name);
	    }
	    if (cl != null)		// XXX - always true?
		return (DataContentHandler)cl.newInstance();
	} catch (IllegalAccessException e) {
	    if (LogSupport.isLoggable())
		LogSupport.log("Can't load DCH " + name, e);
	} catch (ClassNotFoundException e) {
	    if (LogSupport.isLoggable())
		LogSupport.log("Can't load DCH " + name, e);
	} catch (InstantiationException e) {
	    if (LogSupport.isLoggable())
		LogSupport.log("Can't load DCH " + name, e);
	}
	return null;
    }

    /**
     * Get all the MIME types known to this command map.
     *
     * @return		array of MIME types as strings
     * @since	JAF 1.1
     */
    public synchronized String[] getMimeTypes() {
	List mtList = new ArrayList();

	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    String[] ts = DB[i].getMimeTypes();
	    if (ts != null) {
		for (int j = 0; j < ts.length; j++) {
		    // eliminate duplicates
		    if (!mtList.contains(ts[j]))
			mtList.add(ts[j]);
		}
	    }
	}

	String[] mts = new String[mtList.size()];
	mts = (String[])mtList.toArray(mts);

	return mts;
    }

    /**
     * Get the native commands for the given MIME type.
     * Returns an array of strings where each string is
     * an entire mailcap file entry.  The application
     * will need to parse the entry to extract the actual
     * command as well as any attributes it needs. See
     * <A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>
     * for details of the mailcap entry syntax.  Only mailcap
     * entries that specify a view command for the specified
     * MIME type are returned.
     *
     * @param	mimeType	the MIME type
     * @return		array of native command entries
     * @since	JAF 1.1
     */
    public synchronized String[] getNativeCommands(String mimeType) {
	List cmdList = new ArrayList();
	if (mimeType != null)
	    mimeType = mimeType.toLowerCase(Locale.ENGLISH);

	for (int i = 0; i < DB.length; i++) {
	    if (DB[i] == null)
		continue;
	    String[] cmds = DB[i].getNativeCommands(mimeType);
	    if (cmds != null) {
		for (int j = 0; j < cmds.length; j++) {
		    // eliminate duplicates
		    if (!cmdList.contains(cmds[j]))
			cmdList.add(cmds[j]);
		}
	    }
	}

	String[] cmds = new String[cmdList.size()];
	cmds = (String[])cmdList.toArray(cmds);

	return cmds;
    }

    /**
     * for debugging...
     *
    public static void main(String[] argv) throws Exception {
	MailcapCommandMap map = new MailcapCommandMap();
	CommandInfo[] cmdInfo;

	cmdInfo = map.getPreferredCommands(argv[0]);
	System.out.println("Preferred Commands:");
	for (int i = 0; i < cmdInfo.length; i++)
	    System.out.println("Command " + cmdInfo[i].getCommandName() + " [" +
					    cmdInfo[i].getCommandClass() + "]");
	cmdInfo = map.getAllCommands(argv[0]);
	System.out.println();
	System.out.println("All Commands:");
	for (int i = 0; i < cmdInfo.length; i++)
	    System.out.println("Command " + cmdInfo[i].getCommandName() + " [" +
					    cmdInfo[i].getCommandClass() + "]");
	DataContentHandler dch = map.createDataContentHandler(argv[0]);
	if (dch != null)
	    System.out.println("DataContentHandler " +
						dch.getClass().toString());
	System.exit(0);
    }
    */
}
