Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java
38877 views
/*1* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package javax.activation;2728import java.util.*;29import java.io.*;30import java.net.*;31import com.sun.activation.registries.MailcapFile;32import com.sun.activation.registries.LogSupport;3334/**35* MailcapCommandMap extends the CommandMap36* abstract class. It implements a CommandMap whose configuration37* is based on mailcap files38* (<A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>).39* The MailcapCommandMap can be configured both programmatically40* and via configuration files.41* <p>42* <b>Mailcap file search order:</b><p>43* The MailcapCommandMap looks in various places in the user's44* system for mailcap file entries. When requests are made45* to search for commands in the MailcapCommandMap, it searches46* mailcap files in the following order:47* <p>48* <ol>49* <li> Programatically added entries to the MailcapCommandMap instance.50* <li> The file <code>.mailcap</code> in the user's home directory.51* <li> The file <<i>java.home</i>><code>/lib/mailcap</code>.52* <li> The file or resources named <code>META-INF/mailcap</code>.53* <li> The file or resource named <code>META-INF/mailcap.default</code>54* (usually found only in the <code>activation.jar</code> file).55* </ol>56* <p>57* <b>Mailcap file format:</b><p>58*59* Mailcap files must conform to the mailcap60* file specification (RFC 1524, <i>A User Agent Configuration Mechanism61* For Multimedia Mail Format Information</i>).62* The file format consists of entries corresponding to63* particular MIME types. In general, the specification64* specifies <i>applications</i> for clients to use when they65* themselves cannot operate on the specified MIME type. The66* MailcapCommandMap extends this specification by using a parameter mechanism67* in mailcap files that allows JavaBeans(tm) components to be specified as68* corresponding to particular commands for a MIME type.<p>69*70* When a mailcap file is71* parsed, the MailcapCommandMap recognizes certain parameter signatures,72* specifically those parameter names that begin with <code>x-java-</code>.73* The MailcapCommandMap uses this signature to find74* command entries for inclusion into its registries.75* Parameter names with the form <code>x-java-<name></code>76* are read by the MailcapCommandMap as identifying a command77* with the name <i>name</i>. When the <i>name</i> is <code>78* content-handler</code> the MailcapCommandMap recognizes the class79* signified by this parameter as a <i>DataContentHandler</i>.80* All other commands are handled generically regardless of command81* name. The command implementation is specified by a fully qualified82* class name of a JavaBean(tm) component. For example; a command for viewing83* some data can be specified as: <code>x-java-view=com.foo.ViewBean</code>.<p>84*85* When the command name is <code>fallback-entry</code>, the value of86* the command may be <code>true</code> or <code>false</code>. An87* entry for a MIME type that includes a parameter of88* <code>x-java-fallback-entry=true</code> defines fallback commands89* for that MIME type that will only be used if no non-fallback entry90* can be found. For example, an entry of the form <code>text/*; ;91* x-java-fallback-entry=true; x-java-view=com.sun.TextViewer</code>92* specifies a view command to be used for any text MIME type. This93* view command would only be used if a non-fallback view command for94* the MIME type could not be found.<p>95*96* MailcapCommandMap aware mailcap files have the97* following general form:<p>98* <code>99* # Comments begin with a '#' and continue to the end of the line.<br>100* <mime type>; ; <parameter list><br>101* # Where a parameter list consists of one or more parameters,<br>102* # where parameters look like: x-java-view=com.sun.TextViewer<br>103* # and a parameter list looks like: <br>104* text/plain; ; x-java-view=com.sun.TextViewer; x-java-edit=com.sun.TextEdit105* <br>106* # Note that mailcap entries that do not contain 'x-java' parameters<br>107* # and comply to RFC 1524 are simply ignored:<br>108* image/gif; /usr/dt/bin/sdtimage %s<br>109*110* </code>111* <p>112*113* @author Bart Calder114* @author Bill Shannon115*116* @since 1.6117*/118119public class MailcapCommandMap extends CommandMap {120/*121* We manage a collection of databases, searched in order.122*/123private MailcapFile[] DB;124private static final int PROG = 0; // programmatically added entries125126/**127* The default Constructor.128*/129public MailcapCommandMap() {130super();131List dbv = new ArrayList(5); // usually 5 or less databases132MailcapFile mf = null;133dbv.add(null); // place holder for PROG entry134135LogSupport.log("MailcapCommandMap: load HOME");136try {137String user_home = System.getProperty("user.home");138139if (user_home != null) {140String path = user_home + File.separator + ".mailcap";141mf = loadFile(path);142if (mf != null)143dbv.add(mf);144}145} catch (SecurityException ex) {}146147LogSupport.log("MailcapCommandMap: load SYS");148try {149// check system's home150String system_mailcap = System.getProperty("java.home") +151File.separator + "lib" + File.separator + "mailcap";152mf = loadFile(system_mailcap);153if (mf != null)154dbv.add(mf);155} catch (SecurityException ex) {}156157LogSupport.log("MailcapCommandMap: load JAR");158// load from the app's jar file159loadAllResources(dbv, "META-INF/mailcap");160161LogSupport.log("MailcapCommandMap: load DEF");162mf = loadResource("/META-INF/mailcap.default");163164if (mf != null)165dbv.add(mf);166167DB = new MailcapFile[dbv.size()];168DB = (MailcapFile[])dbv.toArray(DB);169}170171/**172* Load from the named resource.173*/174private MailcapFile loadResource(String name) {175InputStream clis = null;176try {177clis = SecuritySupport.getResourceAsStream(this.getClass(), name);178if (clis != null) {179MailcapFile mf = new MailcapFile(clis);180if (LogSupport.isLoggable())181LogSupport.log("MailcapCommandMap: successfully loaded " +182"mailcap file: " + name);183return mf;184} else {185if (LogSupport.isLoggable())186LogSupport.log("MailcapCommandMap: not loading " +187"mailcap file: " + name);188}189} catch (IOException e) {190if (LogSupport.isLoggable())191LogSupport.log("MailcapCommandMap: can't load " + name, e);192} catch (SecurityException sex) {193if (LogSupport.isLoggable())194LogSupport.log("MailcapCommandMap: can't load " + name, sex);195} finally {196try {197if (clis != null)198clis.close();199} catch (IOException ex) { } // ignore it200}201return null;202}203204/**205* Load all of the named resource.206*/207private void loadAllResources(List v, String name) {208boolean anyLoaded = false;209try {210URL[] urls;211ClassLoader cld = null;212// First try the "application's" class loader.213cld = SecuritySupport.getContextClassLoader();214if (cld == null)215cld = this.getClass().getClassLoader();216if (cld != null)217urls = SecuritySupport.getResources(cld, name);218else219urls = SecuritySupport.getSystemResources(name);220if (urls != null) {221if (LogSupport.isLoggable())222LogSupport.log("MailcapCommandMap: getResources");223for (int i = 0; i < urls.length; i++) {224URL url = urls[i];225InputStream clis = null;226if (LogSupport.isLoggable())227LogSupport.log("MailcapCommandMap: URL " + url);228try {229clis = SecuritySupport.openStream(url);230if (clis != null) {231v.add(new MailcapFile(clis));232anyLoaded = true;233if (LogSupport.isLoggable())234LogSupport.log("MailcapCommandMap: " +235"successfully loaded " +236"mailcap file from URL: " +237url);238} else {239if (LogSupport.isLoggable())240LogSupport.log("MailcapCommandMap: " +241"not loading mailcap " +242"file from URL: " + url);243}244} catch (IOException ioex) {245if (LogSupport.isLoggable())246LogSupport.log("MailcapCommandMap: can't load " +247url, ioex);248} catch (SecurityException sex) {249if (LogSupport.isLoggable())250LogSupport.log("MailcapCommandMap: can't load " +251url, sex);252} finally {253try {254if (clis != null)255clis.close();256} catch (IOException cex) { }257}258}259}260} catch (Exception ex) {261if (LogSupport.isLoggable())262LogSupport.log("MailcapCommandMap: can't load " + name, ex);263}264265// if failed to load anything, fall back to old technique, just in case266if (!anyLoaded) {267if (LogSupport.isLoggable())268LogSupport.log("MailcapCommandMap: !anyLoaded");269MailcapFile mf = loadResource("/" + name);270if (mf != null)271v.add(mf);272}273}274275/**276* Load from the named file.277*/278private MailcapFile loadFile(String name) {279MailcapFile mtf = null;280281try {282mtf = new MailcapFile(name);283} catch (IOException e) {284// e.printStackTrace();285}286return mtf;287}288289/**290* Constructor that allows the caller to specify the path291* of a <i>mailcap</i> file.292*293* @param fileName The name of the <i>mailcap</i> file to open294* @exception IOException if the file can't be accessed295*/296public MailcapCommandMap(String fileName) throws IOException {297this();298299if (LogSupport.isLoggable())300LogSupport.log("MailcapCommandMap: load PROG from " + fileName);301if (DB[PROG] == null) {302DB[PROG] = new MailcapFile(fileName);303}304}305306307/**308* Constructor that allows the caller to specify an <i>InputStream</i>309* containing a mailcap file.310*311* @param is InputStream of the <i>mailcap</i> file to open312*/313public MailcapCommandMap(InputStream is) {314this();315316LogSupport.log("MailcapCommandMap: load PROG");317if (DB[PROG] == null) {318try {319DB[PROG] = new MailcapFile(is);320} catch (IOException ex) {321// XXX - should throw it322}323}324}325326/**327* Get the preferred command list for a MIME Type. The MailcapCommandMap328* searches the mailcap files as described above under329* <i>Mailcap file search order</i>.<p>330*331* The result of the search is a proper subset of available332* commands in all mailcap files known to this instance of333* MailcapCommandMap. The first entry for a particular command334* is considered the preferred command.335*336* @param mimeType the MIME type337* @return the CommandInfo objects representing the preferred commands.338*/339public synchronized CommandInfo[] getPreferredCommands(String mimeType) {340List cmdList = new ArrayList();341if (mimeType != null)342mimeType = mimeType.toLowerCase(Locale.ENGLISH);343344for (int i = 0; i < DB.length; i++) {345if (DB[i] == null)346continue;347Map cmdMap = DB[i].getMailcapList(mimeType);348if (cmdMap != null)349appendPrefCmdsToList(cmdMap, cmdList);350}351352// now add the fallback commands353for (int i = 0; i < DB.length; i++) {354if (DB[i] == null)355continue;356Map cmdMap = DB[i].getMailcapFallbackList(mimeType);357if (cmdMap != null)358appendPrefCmdsToList(cmdMap, cmdList);359}360361CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()];362cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos);363364return cmdInfos;365}366367/**368* Put the commands that are in the hash table, into the list.369*/370private void appendPrefCmdsToList(Map cmdHash, List cmdList) {371Iterator verb_enum = cmdHash.keySet().iterator();372373while (verb_enum.hasNext()) {374String verb = (String)verb_enum.next();375if (!checkForVerb(cmdList, verb)) {376List cmdList2 = (List)cmdHash.get(verb); // get the list377String className = (String)cmdList2.get(0);378cmdList.add(new CommandInfo(verb, className));379}380}381}382383/**384* Check the cmdList to see if this command exists, return385* true if the verb is there.386*/387private boolean checkForVerb(List cmdList, String verb) {388Iterator ee = cmdList.iterator();389while (ee.hasNext()) {390String enum_verb =391(String)((CommandInfo)ee.next()).getCommandName();392if (enum_verb.equals(verb))393return true;394}395return false;396}397398/**399* Get all the available commands in all mailcap files known to400* this instance of MailcapCommandMap for this MIME type.401*402* @param mimeType the MIME type403* @return the CommandInfo objects representing all the commands.404*/405public synchronized CommandInfo[] getAllCommands(String mimeType) {406List cmdList = new ArrayList();407if (mimeType != null)408mimeType = mimeType.toLowerCase(Locale.ENGLISH);409410for (int i = 0; i < DB.length; i++) {411if (DB[i] == null)412continue;413Map cmdMap = DB[i].getMailcapList(mimeType);414if (cmdMap != null)415appendCmdsToList(cmdMap, cmdList);416}417418// now add the fallback commands419for (int i = 0; i < DB.length; i++) {420if (DB[i] == null)421continue;422Map cmdMap = DB[i].getMailcapFallbackList(mimeType);423if (cmdMap != null)424appendCmdsToList(cmdMap, cmdList);425}426427CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()];428cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos);429430return cmdInfos;431}432433/**434* Put the commands that are in the hash table, into the list.435*/436private void appendCmdsToList(Map typeHash, List cmdList) {437Iterator verb_enum = typeHash.keySet().iterator();438439while (verb_enum.hasNext()) {440String verb = (String)verb_enum.next();441List cmdList2 = (List)typeHash.get(verb);442Iterator cmd_enum = ((List)cmdList2).iterator();443444while (cmd_enum.hasNext()) {445String cmd = (String)cmd_enum.next();446cmdList.add(new CommandInfo(verb, cmd));447// cmdList.add(0, new CommandInfo(verb, cmd));448}449}450}451452/**453* Get the command corresponding to <code>cmdName</code> for the MIME type.454*455* @param mimeType the MIME type456* @param cmdName the command name457* @return the CommandInfo object corresponding to the command.458*/459public synchronized CommandInfo getCommand(String mimeType,460String cmdName) {461if (mimeType != null)462mimeType = mimeType.toLowerCase(Locale.ENGLISH);463464for (int i = 0; i < DB.length; i++) {465if (DB[i] == null)466continue;467Map cmdMap = DB[i].getMailcapList(mimeType);468if (cmdMap != null) {469// get the cmd list for the cmd470List v = (List)cmdMap.get(cmdName);471if (v != null) {472String cmdClassName = (String)v.get(0);473474if (cmdClassName != null)475return new CommandInfo(cmdName, cmdClassName);476}477}478}479480// now try the fallback list481for (int i = 0; i < DB.length; i++) {482if (DB[i] == null)483continue;484Map cmdMap = DB[i].getMailcapFallbackList(mimeType);485if (cmdMap != null) {486// get the cmd list for the cmd487List v = (List)cmdMap.get(cmdName);488if (v != null) {489String cmdClassName = (String)v.get(0);490491if (cmdClassName != null)492return new CommandInfo(cmdName, cmdClassName);493}494}495}496return null;497}498499/**500* Add entries to the registry. Programmatically501* added entries are searched before other entries.<p>502*503* The string that is passed in should be in mailcap504* format.505*506* @param mail_cap a correctly formatted mailcap string507*/508public synchronized void addMailcap(String mail_cap) {509// check to see if one exists510LogSupport.log("MailcapCommandMap: add to PROG");511if (DB[PROG] == null)512DB[PROG] = new MailcapFile();513514DB[PROG].appendToMailcap(mail_cap);515}516517/**518* Return the DataContentHandler for the specified MIME type.519*520* @param mimeType the MIME type521* @return the DataContentHandler522*/523public synchronized DataContentHandler createDataContentHandler(524String mimeType) {525if (LogSupport.isLoggable())526LogSupport.log(527"MailcapCommandMap: createDataContentHandler for " + mimeType);528if (mimeType != null)529mimeType = mimeType.toLowerCase(Locale.ENGLISH);530531for (int i = 0; i < DB.length; i++) {532if (DB[i] == null)533continue;534if (LogSupport.isLoggable())535LogSupport.log(" search DB #" + i);536Map cmdMap = DB[i].getMailcapList(mimeType);537if (cmdMap != null) {538List v = (List)cmdMap.get("content-handler");539if (v != null) {540String name = (String)v.get(0);541DataContentHandler dch = getDataContentHandler(name);542if (dch != null)543return dch;544}545}546}547548// now try the fallback entries549for (int i = 0; i < DB.length; i++) {550if (DB[i] == null)551continue;552if (LogSupport.isLoggable())553LogSupport.log(" search fallback DB #" + i);554Map cmdMap = DB[i].getMailcapFallbackList(mimeType);555if (cmdMap != null) {556List v = (List)cmdMap.get("content-handler");557if (v != null) {558String name = (String)v.get(0);559DataContentHandler dch = getDataContentHandler(name);560if (dch != null)561return dch;562}563}564}565return null;566}567568private DataContentHandler getDataContentHandler(String name) {569if (LogSupport.isLoggable())570LogSupport.log(" got content-handler");571if (LogSupport.isLoggable())572LogSupport.log(" class " + name);573try {574ClassLoader cld = null;575// First try the "application's" class loader.576cld = SecuritySupport.getContextClassLoader();577if (cld == null)578cld = this.getClass().getClassLoader();579Class cl = null;580try {581cl = cld.loadClass(name);582} catch (Exception ex) {583// if anything goes wrong, do it the old way584cl = Class.forName(name);585}586if (cl != null) // XXX - always true?587return (DataContentHandler)cl.newInstance();588} catch (IllegalAccessException e) {589if (LogSupport.isLoggable())590LogSupport.log("Can't load DCH " + name, e);591} catch (ClassNotFoundException e) {592if (LogSupport.isLoggable())593LogSupport.log("Can't load DCH " + name, e);594} catch (InstantiationException e) {595if (LogSupport.isLoggable())596LogSupport.log("Can't load DCH " + name, e);597}598return null;599}600601/**602* Get all the MIME types known to this command map.603*604* @return array of MIME types as strings605* @since JAF 1.1606*/607public synchronized String[] getMimeTypes() {608List mtList = new ArrayList();609610for (int i = 0; i < DB.length; i++) {611if (DB[i] == null)612continue;613String[] ts = DB[i].getMimeTypes();614if (ts != null) {615for (int j = 0; j < ts.length; j++) {616// eliminate duplicates617if (!mtList.contains(ts[j]))618mtList.add(ts[j]);619}620}621}622623String[] mts = new String[mtList.size()];624mts = (String[])mtList.toArray(mts);625626return mts;627}628629/**630* Get the native commands for the given MIME type.631* Returns an array of strings where each string is632* an entire mailcap file entry. The application633* will need to parse the entry to extract the actual634* command as well as any attributes it needs. See635* <A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>636* for details of the mailcap entry syntax. Only mailcap637* entries that specify a view command for the specified638* MIME type are returned.639*640* @return array of native command entries641* @since JAF 1.1642*/643public synchronized String[] getNativeCommands(String mimeType) {644List cmdList = new ArrayList();645if (mimeType != null)646mimeType = mimeType.toLowerCase(Locale.ENGLISH);647648for (int i = 0; i < DB.length; i++) {649if (DB[i] == null)650continue;651String[] cmds = DB[i].getNativeCommands(mimeType);652if (cmds != null) {653for (int j = 0; j < cmds.length; j++) {654// eliminate duplicates655if (!cmdList.contains(cmds[j]))656cmdList.add(cmds[j]);657}658}659}660661String[] cmds = new String[cmdList.size()];662cmds = (String[])cmdList.toArray(cmds);663664return cmds;665}666667/**668* for debugging...669*670public static void main(String[] argv) throws Exception {671MailcapCommandMap map = new MailcapCommandMap();672CommandInfo[] cmdInfo;673674cmdInfo = map.getPreferredCommands(argv[0]);675System.out.println("Preferred Commands:");676for (int i = 0; i < cmdInfo.length; i++)677System.out.println("Command " + cmdInfo[i].getCommandName() + " [" +678cmdInfo[i].getCommandClass() + "]");679cmdInfo = map.getAllCommands(argv[0]);680System.out.println();681System.out.println("All Commands:");682for (int i = 0; i < cmdInfo.length; i++)683System.out.println("Command " + cmdInfo[i].getCommandName() + " [" +684cmdInfo[i].getCommandClass() + "]");685DataContentHandler dch = map.createDataContentHandler(argv[0]);686if (dch != null)687System.out.println("DataContentHandler " +688dch.getClass().toString());689System.exit(0);690}691*/692}693694695