- /*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
-
- package javax.activation;
-
- import java.util.*;
- import java.io.*;
- import com.sun.activation.registries.MailcapFile;
- import com.sun.activation.registries.MailcapEntry;
-
- /**
- * MailcapCommandMap extends the CommandMap
- * abstract class. It implements a CommandMap whose configuration
- * is based on mailcap files (RFC 1524). 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:
- * <p>
- * <ol>
- * <li> Programatically added entries to the MailcapCommandMap instance.
- * <li> The file <code>.mailcap</code> in the user's home directory.
- * <li> The file <<i>java.home</i>><code>/lib/mailcap</code>.
- * <li> The file or resource 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>
- * <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-<name></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>
- *
- * MailcapCommandMap aware mailcap files have the
- * following general form:<p>
- * <code>
- * # Comments begin with a '#' and continue to the end of the line.<br>
- * <mime type> ; <parameter list><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 up to 5 databases, searched in order.
- * The default database is shared between all instances
- * of this class.
- * XXX - Can we safely share more databases between instances?
- */
- private static MailcapFile defDB = null;
- private MailcapFile[] DB = new MailcapFile[5];
- private static final int PROG = 0; // programmatically added entries
- private static final int HOME = 1; // the user's home directory
- private static final int SYS = 2; // the system file
- private static final int JAR = 3; // the app's entry in the jar file
- private static final int DEF = 4; // the default entry in our jar file
-
- private static boolean debug = false;
-
- static {
- try {
- debug = Boolean.getBoolean("javax.activation.debug");
- } catch (Throwable t) {
- // ignore any errors
- }
- }
-
-
- /**
- * The default Constructor.
- */
- public MailcapCommandMap() {
- super();
- if (debug)
- System.out.println("MailcapCommandMap: load HOME");
- try {
- String user_home = System.getProperty("user.home");
-
- if (user_home != null) {
- String path = user_home + File.separator + ".mailcap";
- DB[HOME] = loadFile(path);
- }
- } catch (SecurityException ex) {}
-
- if (debug)
- System.out.println("MailcapCommandMap: load SYS");
- try {
- // check system's home
- String system_mailcap = System.getProperty("java.home") +
- File.separator + "lib" + File.separator + "mailcap";
- DB[SYS] = loadFile(system_mailcap);
- } catch (SecurityException ex) {}
-
- if (debug)
- System.out.println("MailcapCommandMap: load JAR");
- // load from the app's jar file
- DB[JAR] = loadResource("/META-INF/mailcap");
-
- if (debug)
- System.out.println("MailcapCommandMap: load DEF");
- synchronized (MailcapCommandMap.class) {
- // see if another instance has created this yet.
- if (defDB == null)
- defDB = loadResource("/META-INF/mailcap.default");
- }
-
- DB[DEF] = defDB;
- }
-
- /**
- * Load from the named resource.
- */
- private MailcapFile loadResource(String name) {
- try {
- InputStream clis = this.getClass().getResourceAsStream(name);
- if (clis != null)
- return new MailcapFile(clis);
- } catch (IOException e) {
- // e.printStackTrace();
- }
- return null;
- }
-
- /**
- * 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
- */
- public MailcapCommandMap(String fileName) throws IOException {
- this();
-
- if (debug)
- System.out.println("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();
-
- if (debug)
- System.out.println("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) {
- Vector cmdVector = new Vector();
-
- for (int i = 0; i < DB.length; i++) {
- if (DB[i] == null)
- continue;
- Hashtable cmdList = DB[i].getMailcapList(mimeType);
- if (cmdList != null)
- appendPrefCmdsToVector(cmdList, cmdVector);
- }
-
- CommandInfo[] cmdInfos = new CommandInfo[cmdVector.size()];
- cmdVector.copyInto(cmdInfos);
-
- return cmdInfos;
- }
-
- /**
- * Put the commands that are in the hash table, into the vector.
- */
- private void appendPrefCmdsToVector(Hashtable typeHash, Vector cmdList) {
- Enumeration verb_enum = typeHash.keys();
-
- while (verb_enum.hasMoreElements()) {
- String verb = (String)verb_enum.nextElement();
- if (!checkForVerb(cmdList, verb)) {
- Vector cmdVector = (Vector)typeHash.get(verb); // get the list
- String className = (String)cmdVector.firstElement();
- cmdList.addElement(new CommandInfo(verb, className));
- }
- }
- }
-
- /**
- * Check the cmdVector to see if this command exists, return
- * true if the verb is there.
- */
- private boolean checkForVerb(Vector cmdVector, String verb) {
- Enumeration enum = cmdVector.elements();
- while (enum.hasMoreElements()) {
- String enum_verb =
- (String)((CommandInfo)enum.nextElement()).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) {
- Vector cmdVector = new Vector();
-
- for (int i = 0; i < DB.length; i++) {
- if (DB[i] == null)
- continue;
- Hashtable cmdList = DB[i].getMailcapList(mimeType);
- if (cmdList != null)
- appendCmdsToVector(cmdList, cmdVector);
- }
-
- CommandInfo[] cmdInfos = new CommandInfo[cmdVector.size()];
- cmdVector.copyInto(cmdInfos);
-
- return cmdInfos;
- }
-
- /**
- * Put the commands that are in the hash table, into the vector.
- */
- private void appendCmdsToVector(Hashtable typeHash, Vector cmdList) {
- Enumeration verb_enum = typeHash.keys();
-
- while (verb_enum.hasMoreElements()) {
- String verb = (String)verb_enum.nextElement();
- Vector cmdVector = (Vector)typeHash.get(verb);
- Enumeration cmd_enum = ((Vector)cmdVector).elements();
-
- while (cmd_enum.hasMoreElements()) {
- String cmd = (String)cmd_enum.nextElement();
- // cmdList.addElement(new CommandInfo(verb, cmd));
- cmdList.insertElementAt(new CommandInfo(verb, cmd), 0);
- }
- }
- }
-
- /**
- * 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) {
- for (int i = 0; i < DB.length; i++) {
- if (DB[i] == null)
- continue;
- Hashtable cmdList = DB[i].getMailcapList(mimeType);
- if (cmdList != null) {
- // get the cmd list for the cmd
- Vector v = (Vector)cmdList.get(cmdName);
- if (v != null) {
- String cmdClassName = (String)v.firstElement();
-
- 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
- if (debug)
- System.out.println("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 (debug)
- System.out.println(
- "MailcapCommandMap: createDataContentHandler for " + mimeType);
- for (int i = 0; i < DB.length; i++) {
- if (DB[i] == null)
- continue;
- if (debug)
- System.out.println(" search DB #" + i);
- Hashtable cmdList = DB[i].getMailcapList(mimeType);
- if (cmdList != null) {
- Vector v = (Vector)cmdList.get("content-handler");
- if (v != null) {
- if (debug)
- System.out.println(" got content-handler");
- try {
- if (debug)
- System.out.println(" class " +
- (String)v.firstElement());
- return (DataContentHandler)Class.forName(
- (String)v.firstElement()).newInstance();
- } catch (IllegalAccessException e) {
- } catch (ClassNotFoundException e) {
- } catch (InstantiationException e) {
- }
- }
- }
- }
- return null;
- }
-
- /**
- * 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);
- }
- */
- }