1 /*
   2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package javax.activation;
  28 
  29 import java.util.*;
  30 import java.io.*;
  31 import java.net.*;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedAction;
  34 import com.sun.activation.registries.MailcapFile;
  35 import com.sun.activation.registries.LogSupport;
  36 
  37 /**
  38  * MailcapCommandMap extends the CommandMap
  39  * abstract class. It implements a CommandMap whose configuration
  40  * is based on mailcap files
  41  * (<A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>).
  42  * The MailcapCommandMap can be configured both programmatically
  43  * and via configuration files.
  44  * <p>
  45  * <b>Mailcap file search order:</b><p>
  46  * The MailcapCommandMap looks in various places in the user's
  47  * system for mailcap file entries. When requests are made
  48  * to search for commands in the MailcapCommandMap, it searches
  49  * mailcap files in the following order:
  50  * <ol>
  51  * <li> Programatically added entries to the MailcapCommandMap instance.
  52  * <li> The file {@code .mailcap} in the user's home directory.
  53  * <li> The file <i>java.home</i>{@code /}<i>conf</i>{@code /mailcap}.
  54  * <li> The file or resources named {@code META-INF/mailcap}.
  55  * <li> The file or resource named {@code META-INF/mailcap.default}
  56  * (usually found only in the {@code activation.jar} file).
  57  * </ol>
  58  * <p>
  59  * (Where <i>java.home</i> is the value of the "java.home" System property
  60  * and <i>conf</i> is the directory named "conf" if it exists,
  61  * otherwise the directory named "lib"; the "conf" directory was
  62  * introduced in JDK 1.9.)
  63  * <p>
  64  * <b>Mailcap file format:</b><p>
  65  *
  66  * Mailcap files must conform to the mailcap
  67  * file specification (RFC 1524, <i>A User Agent Configuration Mechanism
  68  * For Multimedia Mail Format Information</i>).
  69  * The file format consists of entries corresponding to
  70  * particular MIME types. In general, the specification
  71  * specifies <i>applications</i> for clients to use when they
  72  * themselves cannot operate on the specified MIME type. The
  73  * MailcapCommandMap extends this specification by using a parameter mechanism
  74  * in mailcap files that allows JavaBeans(tm) components to be specified as
  75  * corresponding to particular commands for a MIME type.<p>
  76  *
  77  * When a mailcap file is
  78  * parsed, the MailcapCommandMap recognizes certain parameter signatures,
  79  * specifically those parameter names that begin with {@code x-java-}.
  80  * The MailcapCommandMap uses this signature to find
  81  * command entries for inclusion into its registries.
  82  * Parameter names with the form {@code x-java-<name>}
  83  * are read by the MailcapCommandMap as identifying a command
  84  * with the name <i>name</i>. When the <i>name</i> is {@code
  85  * content-handler} the MailcapCommandMap recognizes the class
  86  * signified by this parameter as a <i>DataContentHandler</i>.
  87  * All other commands are handled generically regardless of command
  88  * name. The command implementation is specified by a fully qualified
  89  * class name of a JavaBean(tm) component. For example; a command for viewing
  90  * some data can be specified as: {@code x-java-view=com.foo.ViewBean}.<p>
  91  *
  92  * When the command name is {@code fallback-entry}, the value of
  93  * the command may be {@code true} or {@code false}.  An
  94  * entry for a MIME type that includes a parameter of
  95  * {@code x-java-fallback-entry=true} defines fallback commands
  96  * for that MIME type that will only be used if no non-fallback entry
  97  * can be found.  For example, an entry of the form {@code text/*; ;
  98  * x-java-fallback-entry=true; x-java-view=com.sun.TextViewer}
  99  * specifies a view command to be used for any text MIME type.  This
 100  * view command would only be used if a non-fallback view command for
 101  * the MIME type could not be found.<p>
 102  *
 103  * MailcapCommandMap aware mailcap files have the
 104  * following general form:
 105  * <pre>{@code
 106  * # Comments begin with a '#' and continue to the end of the line.
 107  * <mime type>; ; <parameter list>
 108  * # Where a parameter list consists of one or more parameters,
 109  * # where parameters look like: x-java-view=com.sun.TextViewer
 110  * # and a parameter list looks like:
 111  * text/plain; ; x-java-view=com.sun.TextViewer; x-java-edit=com.sun.TextEdit
 112  * # Note that mailcap entries that do not contain 'x-java' parameters
 113  * # and comply to RFC 1524 are simply ignored:
 114  * image/gif; /usr/dt/bin/sdtimage %s
 115  * }</pre>
 116  *
 117  * @author Bart Calder
 118  * @author Bill Shannon
 119  *
 120  * @since 1.6
 121  */
 122 
 123 public class MailcapCommandMap extends CommandMap {
 124     /*
 125      * We manage a collection of databases, searched in order.
 126      */
 127     private MailcapFile[] DB;
 128     private static final int PROG = 0;  // programmatically added entries
 129 
 130     private static final String confDir;
 131 
 132     static {
 133         String dir = null;
 134         try {
 135             dir = (String)AccessController.doPrivileged(
 136                 new PrivilegedAction() {
 137                     public Object run() {
 138                         String home = System.getProperty("java.home");
 139                         String newdir = home + File.separator + "conf";
 140                         File conf = new File(newdir);
 141                         if (conf.exists())
 142                             return newdir + File.separator;
 143                         else
 144                             return home + File.separator + "lib" + File.separator;
 145                     }
 146                 });
 147         } catch (Exception ex) {
 148             // ignore any exceptions
 149         }
 150         confDir = dir;
 151     }
 152 
 153     /**
 154      * The default Constructor.
 155      */
 156     public MailcapCommandMap() {
 157         super();
 158         List dbv = new ArrayList(5);    // usually 5 or less databases
 159         MailcapFile mf = null;
 160         dbv.add(null);          // place holder for PROG entry
 161 
 162         LogSupport.log("MailcapCommandMap: load HOME");
 163         try {
 164             String user_home = System.getProperty("user.home");
 165 
 166             if (user_home != null) {
 167                 String path = user_home + File.separator + ".mailcap";
 168                 mf = loadFile(path);
 169                 if (mf != null)
 170                     dbv.add(mf);
 171             }
 172         } catch (SecurityException ex) {}
 173 
 174         LogSupport.log("MailcapCommandMap: load SYS");
 175         try {
 176             // check system's home
 177             if (confDir != null) {
 178                 mf = loadFile(confDir + "mailcap");
 179                 if (mf != null)
 180                     dbv.add(mf);
 181             }
 182         } catch (SecurityException ex) {}
 183 
 184         LogSupport.log("MailcapCommandMap: load JAR");
 185         // load from the app's jar file
 186         loadAllResources(dbv, "META-INF/mailcap");
 187 
 188         LogSupport.log("MailcapCommandMap: load DEF");
 189         mf = loadResource("/META-INF/mailcap.default");
 190 
 191         if (mf != null)
 192             dbv.add(mf);
 193 
 194         DB = new MailcapFile[dbv.size()];
 195         DB = (MailcapFile[])dbv.toArray(DB);
 196     }
 197 
 198     /**
 199      * Load from the named resource.
 200      */
 201     private MailcapFile loadResource(String name) {
 202         InputStream clis = null;
 203         try {
 204             clis = SecuritySupport.getResourceAsStream(this.getClass(), name);
 205             if (clis != null) {
 206                 MailcapFile mf = new MailcapFile(clis);
 207                 if (LogSupport.isLoggable())
 208                     LogSupport.log("MailcapCommandMap: successfully loaded " +
 209                         "mailcap file: " + name);
 210                 return mf;
 211             } else {
 212                 if (LogSupport.isLoggable())
 213                     LogSupport.log("MailcapCommandMap: not loading " +
 214                         "mailcap file: " + name);
 215             }
 216         } catch (IOException e) {
 217             if (LogSupport.isLoggable())
 218                 LogSupport.log("MailcapCommandMap: can't load " + name, e);
 219         } catch (SecurityException sex) {
 220             if (LogSupport.isLoggable())
 221                 LogSupport.log("MailcapCommandMap: can't load " + name, sex);
 222         } finally {
 223             try {
 224                 if (clis != null)
 225                     clis.close();
 226             } catch (IOException ex) { }        // ignore it
 227         }
 228         return null;
 229     }
 230 
 231     /**
 232      * Load all of the named resource.
 233      */
 234     private void loadAllResources(List v, String name) {
 235         boolean anyLoaded = false;
 236         try {
 237             URL[] urls;
 238             ClassLoader cld = null;
 239             // First try the "application's" class loader.
 240             cld = SecuritySupport.getContextClassLoader();
 241             if (cld == null)
 242                 cld = this.getClass().getClassLoader();
 243             if (cld != null)
 244                 urls = SecuritySupport.getResources(cld, name);
 245             else
 246                 urls = SecuritySupport.getSystemResources(name);
 247             if (urls != null) {
 248                 if (LogSupport.isLoggable())
 249                     LogSupport.log("MailcapCommandMap: getResources");
 250                 for (int i = 0; i < urls.length; i++) {
 251                     URL url = urls[i];
 252                     InputStream clis = null;
 253                     if (LogSupport.isLoggable())
 254                         LogSupport.log("MailcapCommandMap: URL " + url);
 255                     try {
 256                         clis = SecuritySupport.openStream(url);
 257                         if (clis != null) {
 258                             v.add(new MailcapFile(clis));
 259                             anyLoaded = true;
 260                             if (LogSupport.isLoggable())
 261                                 LogSupport.log("MailcapCommandMap: " +
 262                                     "successfully loaded " +
 263                                     "mailcap file from URL: " +
 264                                     url);
 265                         } else {
 266                             if (LogSupport.isLoggable())
 267                                 LogSupport.log("MailcapCommandMap: " +
 268                                     "not loading mailcap " +
 269                                     "file from URL: " + url);
 270                         }
 271                     } catch (IOException ioex) {
 272                         if (LogSupport.isLoggable())
 273                             LogSupport.log("MailcapCommandMap: can't load " +
 274                                                 url, ioex);
 275                     } catch (SecurityException sex) {
 276                         if (LogSupport.isLoggable())
 277                             LogSupport.log("MailcapCommandMap: can't load " +
 278                                                 url, sex);
 279                     } finally {
 280                         try {
 281                             if (clis != null)
 282                                 clis.close();
 283                         } catch (IOException cex) { }
 284                     }
 285                 }
 286             }
 287         } catch (Exception ex) {
 288             if (LogSupport.isLoggable())
 289                 LogSupport.log("MailcapCommandMap: can't load " + name, ex);
 290         }
 291 
 292         // if failed to load anything, fall back to old technique, just in case
 293         if (!anyLoaded) {
 294             if (LogSupport.isLoggable())
 295                 LogSupport.log("MailcapCommandMap: !anyLoaded");
 296             MailcapFile mf = loadResource("/" + name);
 297             if (mf != null)
 298                 v.add(mf);
 299         }
 300     }
 301 
 302     /**
 303      * Load from the named file.
 304      */
 305     private MailcapFile loadFile(String name) {
 306         MailcapFile mtf = null;
 307 
 308         try {
 309             mtf = new MailcapFile(name);
 310         } catch (IOException e) {
 311             //  e.printStackTrace();
 312         }
 313         return mtf;
 314     }
 315 
 316     /**
 317      * Constructor that allows the caller to specify the path
 318      * of a <i>mailcap</i> file.
 319      *
 320      * @param fileName The name of the <i>mailcap</i> file to open
 321      * @exception       IOException     if the file can't be accessed
 322      */
 323     public MailcapCommandMap(String fileName) throws IOException {
 324         this();
 325 
 326         if (LogSupport.isLoggable())
 327             LogSupport.log("MailcapCommandMap: load PROG from " + fileName);
 328         if (DB[PROG] == null) {
 329             DB[PROG] = new MailcapFile(fileName);
 330         }
 331     }
 332 
 333 
 334     /**
 335      * Constructor that allows the caller to specify an <i>InputStream</i>
 336      * containing a mailcap file.
 337      *
 338      * @param is        InputStream of the <i>mailcap</i> file to open
 339      */
 340     public MailcapCommandMap(InputStream is) {
 341         this();
 342 
 343         LogSupport.log("MailcapCommandMap: load PROG");
 344         if (DB[PROG] == null) {
 345             try {
 346                 DB[PROG] = new MailcapFile(is);
 347             } catch (IOException ex) {
 348                 // XXX - should throw it
 349             }
 350         }
 351     }
 352 
 353     /**
 354      * Get the preferred command list for a MIME Type. The MailcapCommandMap
 355      * searches the mailcap files as described above under
 356      * <i>Mailcap file search order</i>.<p>
 357      *
 358      * The result of the search is a proper subset of available
 359      * commands in all mailcap files known to this instance of
 360      * MailcapCommandMap.  The first entry for a particular command
 361      * is considered the preferred command.
 362      *
 363      * @param mimeType  the MIME type
 364      * @return the CommandInfo objects representing the preferred commands.
 365      */
 366     public synchronized CommandInfo[] getPreferredCommands(String mimeType) {
 367         List cmdList = new ArrayList();
 368         if (mimeType != null)
 369             mimeType = mimeType.toLowerCase(Locale.ENGLISH);
 370 
 371         for (int i = 0; i < DB.length; i++) {
 372             if (DB[i] == null)
 373                 continue;
 374             Map cmdMap = DB[i].getMailcapList(mimeType);
 375             if (cmdMap != null)
 376                 appendPrefCmdsToList(cmdMap, cmdList);
 377         }
 378 
 379         // now add the fallback commands
 380         for (int i = 0; i < DB.length; i++) {
 381             if (DB[i] == null)
 382                 continue;
 383             Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
 384             if (cmdMap != null)
 385                 appendPrefCmdsToList(cmdMap, cmdList);
 386         }
 387 
 388         CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()];
 389         cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos);
 390 
 391         return cmdInfos;
 392     }
 393 
 394     /**
 395      * Put the commands that are in the hash table, into the list.
 396      */
 397     private void appendPrefCmdsToList(Map cmdHash, List cmdList) {
 398         Iterator verb_enum = cmdHash.keySet().iterator();
 399 
 400         while (verb_enum.hasNext()) {
 401             String verb = (String)verb_enum.next();
 402             if (!checkForVerb(cmdList, verb)) {
 403                 List cmdList2 = (List)cmdHash.get(verb); // get the list
 404                 String className = (String)cmdList2.get(0);
 405                 cmdList.add(new CommandInfo(verb, className));
 406             }
 407         }
 408     }
 409 
 410     /**
 411      * Check the cmdList to see if this command exists, return
 412      * true if the verb is there.
 413      */
 414     private boolean checkForVerb(List cmdList, String verb) {
 415         Iterator ee = cmdList.iterator();
 416         while (ee.hasNext()) {
 417             String enum_verb =
 418                 (String)((CommandInfo)ee.next()).getCommandName();
 419             if (enum_verb.equals(verb))
 420                 return true;
 421         }
 422         return false;
 423     }
 424 
 425     /**
 426      * Get all the available commands in all mailcap files known to
 427      * this instance of MailcapCommandMap for this MIME type.
 428      *
 429      * @param mimeType  the MIME type
 430      * @return the CommandInfo objects representing all the commands.
 431      */
 432     public synchronized CommandInfo[] getAllCommands(String mimeType) {
 433         List cmdList = new ArrayList();
 434         if (mimeType != null)
 435             mimeType = mimeType.toLowerCase(Locale.ENGLISH);
 436 
 437         for (int i = 0; i < DB.length; i++) {
 438             if (DB[i] == null)
 439                 continue;
 440             Map cmdMap = DB[i].getMailcapList(mimeType);
 441             if (cmdMap != null)
 442                 appendCmdsToList(cmdMap, cmdList);
 443         }
 444 
 445         // now add the fallback commands
 446         for (int i = 0; i < DB.length; i++) {
 447             if (DB[i] == null)
 448                 continue;
 449             Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
 450             if (cmdMap != null)
 451                 appendCmdsToList(cmdMap, cmdList);
 452         }
 453 
 454         CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()];
 455         cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos);
 456 
 457         return cmdInfos;
 458     }
 459 
 460     /**
 461      * Put the commands that are in the hash table, into the list.
 462      */
 463     private void appendCmdsToList(Map typeHash, List cmdList) {
 464         Iterator verb_enum = typeHash.keySet().iterator();
 465 
 466         while (verb_enum.hasNext()) {
 467             String verb = (String)verb_enum.next();
 468             List cmdList2 = (List)typeHash.get(verb);
 469             Iterator cmd_enum = ((List)cmdList2).iterator();
 470 
 471             while (cmd_enum.hasNext()) {
 472                 String cmd = (String)cmd_enum.next();
 473                 cmdList.add(new CommandInfo(verb, cmd));
 474                 // cmdList.add(0, new CommandInfo(verb, cmd));
 475             }
 476         }
 477     }
 478 
 479     /**
 480      * Get the command corresponding to {@code cmdName} for the MIME type.
 481      *
 482      * @param mimeType  the MIME type
 483      * @param cmdName   the command name
 484      * @return the CommandInfo object corresponding to the command.
 485      */
 486     public synchronized CommandInfo getCommand(String mimeType,
 487                                                         String cmdName) {
 488         if (mimeType != null)
 489             mimeType = mimeType.toLowerCase(Locale.ENGLISH);
 490 
 491         for (int i = 0; i < DB.length; i++) {
 492             if (DB[i] == null)
 493                 continue;
 494             Map cmdMap = DB[i].getMailcapList(mimeType);
 495             if (cmdMap != null) {
 496                 // get the cmd list for the cmd
 497                 List v = (List)cmdMap.get(cmdName);
 498                 if (v != null) {
 499                     String cmdClassName = (String)v.get(0);
 500 
 501                     if (cmdClassName != null)
 502                         return new CommandInfo(cmdName, cmdClassName);
 503                 }
 504             }
 505         }
 506 
 507         // now try the fallback list
 508         for (int i = 0; i < DB.length; i++) {
 509             if (DB[i] == null)
 510                 continue;
 511             Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
 512             if (cmdMap != null) {
 513                 // get the cmd list for the cmd
 514                 List v = (List)cmdMap.get(cmdName);
 515                 if (v != null) {
 516                     String cmdClassName = (String)v.get(0);
 517 
 518                     if (cmdClassName != null)
 519                         return new CommandInfo(cmdName, cmdClassName);
 520                 }
 521             }
 522         }
 523         return null;
 524     }
 525 
 526     /**
 527      * Add entries to the registry.  Programmatically
 528      * added entries are searched before other entries.<p>
 529      *
 530      * The string that is passed in should be in mailcap
 531      * format.
 532      *
 533      * @param mail_cap a correctly formatted mailcap string
 534      */
 535     public synchronized void addMailcap(String mail_cap) {
 536         // check to see if one exists
 537         LogSupport.log("MailcapCommandMap: add to PROG");
 538         if (DB[PROG] == null)
 539             DB[PROG] = new MailcapFile();
 540 
 541         DB[PROG].appendToMailcap(mail_cap);
 542     }
 543 
 544     /**
 545      * Return the DataContentHandler for the specified MIME type.
 546      *
 547      * @param mimeType  the MIME type
 548      * @return          the DataContentHandler
 549      */
 550     public synchronized DataContentHandler createDataContentHandler(
 551                                                         String mimeType) {
 552         if (LogSupport.isLoggable())
 553             LogSupport.log(
 554                 "MailcapCommandMap: createDataContentHandler for " + mimeType);
 555         if (mimeType != null)
 556             mimeType = mimeType.toLowerCase(Locale.ENGLISH);
 557 
 558         for (int i = 0; i < DB.length; i++) {
 559             if (DB[i] == null)
 560                 continue;
 561             if (LogSupport.isLoggable())
 562                 LogSupport.log("  search DB #" + i);
 563             Map cmdMap = DB[i].getMailcapList(mimeType);
 564             if (cmdMap != null) {
 565                 List v = (List)cmdMap.get("content-handler");
 566                 if (v != null) {
 567                     String name = (String)v.get(0);
 568                     DataContentHandler dch = getDataContentHandler(name);
 569                     if (dch != null)
 570                         return dch;
 571                 }
 572             }
 573         }
 574 
 575         // now try the fallback entries
 576         for (int i = 0; i < DB.length; i++) {
 577             if (DB[i] == null)
 578                 continue;
 579             if (LogSupport.isLoggable())
 580                 LogSupport.log("  search fallback DB #" + i);
 581             Map cmdMap = DB[i].getMailcapFallbackList(mimeType);
 582             if (cmdMap != null) {
 583                 List v = (List)cmdMap.get("content-handler");
 584                 if (v != null) {
 585                     String name = (String)v.get(0);
 586                     DataContentHandler dch = getDataContentHandler(name);
 587                     if (dch != null)
 588                         return dch;
 589                 }
 590             }
 591         }
 592         return null;
 593     }
 594 
 595     private DataContentHandler getDataContentHandler(String name) {
 596         if (LogSupport.isLoggable())
 597             LogSupport.log("    got content-handler");
 598         if (LogSupport.isLoggable())
 599             LogSupport.log("      class " + name);
 600         try {
 601             ClassLoader cld = null;
 602             // First try the "application's" class loader.
 603             cld = SecuritySupport.getContextClassLoader();
 604             if (cld == null)
 605                 cld = this.getClass().getClassLoader();
 606             Class cl = null;
 607             try {
 608                 cl = cld.loadClass(name);
 609             } catch (Exception ex) {
 610                 // if anything goes wrong, do it the old way
 611                 cl = Class.forName(name);
 612             }
 613             return (DataContentHandler) cl.newInstance();
 614         } catch (IllegalAccessException e) {
 615             if (LogSupport.isLoggable())
 616                 LogSupport.log("Can't load DCH " + name, e);
 617         } catch (ClassNotFoundException e) {
 618             if (LogSupport.isLoggable())
 619                 LogSupport.log("Can't load DCH " + name, e);
 620         } catch (InstantiationException e) {
 621             if (LogSupport.isLoggable())
 622                 LogSupport.log("Can't load DCH " + name, e);
 623         }
 624         return null;
 625     }
 626 
 627     /**
 628      * Get all the MIME types known to this command map.
 629      *
 630      * @return          array of MIME types as strings
 631      * @since   1.6, JAF 1.1
 632      */
 633     public synchronized String[] getMimeTypes() {
 634         List mtList = new ArrayList();
 635 
 636         for (int i = 0; i < DB.length; i++) {
 637             if (DB[i] == null)
 638                 continue;
 639             String[] ts = DB[i].getMimeTypes();
 640             if (ts != null) {
 641                 for (int j = 0; j < ts.length; j++) {
 642                     // eliminate duplicates
 643                     if (!mtList.contains(ts[j]))
 644                         mtList.add(ts[j]);
 645                 }
 646             }
 647         }
 648 
 649         String[] mts = new String[mtList.size()];
 650         mts = (String[])mtList.toArray(mts);
 651 
 652         return mts;
 653     }
 654 
 655     /**
 656      * Get the native commands for the given MIME type.
 657      * Returns an array of strings where each string is
 658      * an entire mailcap file entry.  The application
 659      * will need to parse the entry to extract the actual
 660      * command as well as any attributes it needs. See
 661      * <A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>
 662      * for details of the mailcap entry syntax.  Only mailcap
 663      * entries that specify a view command for the specified
 664      * MIME type are returned.
 665      *
 666      * @param   mimeType        the MIME type
 667      * @return          array of native command entries
 668      * @since   1.6, JAF 1.1
 669      */
 670     public synchronized String[] getNativeCommands(String mimeType) {
 671         List cmdList = new ArrayList();
 672         if (mimeType != null)
 673             mimeType = mimeType.toLowerCase(Locale.ENGLISH);
 674 
 675         for (int i = 0; i < DB.length; i++) {
 676             if (DB[i] == null)
 677                 continue;
 678             String[] cmds = DB[i].getNativeCommands(mimeType);
 679             if (cmds != null) {
 680                 for (int j = 0; j < cmds.length; j++) {
 681                     // eliminate duplicates
 682                     if (!cmdList.contains(cmds[j]))
 683                         cmdList.add(cmds[j]);
 684                 }
 685             }
 686         }
 687 
 688         String[] cmds = new String[cmdList.size()];
 689         cmds = (String[])cmdList.toArray(cmds);
 690 
 691         return cmds;
 692     }
 693 
 694     /**
 695      * for debugging...
 696      *
 697     public static void main(String[] argv) throws Exception {
 698         MailcapCommandMap map = new MailcapCommandMap();
 699         CommandInfo[] cmdInfo;
 700 
 701         cmdInfo = map.getPreferredCommands(argv[0]);
 702         System.out.println("Preferred Commands:");
 703         for (int i = 0; i < cmdInfo.length; i++)
 704             System.out.println("Command " + cmdInfo[i].getCommandName() + " [" +
 705                                             cmdInfo[i].getCommandClass() + "]");
 706         cmdInfo = map.getAllCommands(argv[0]);
 707         System.out.println();
 708         System.out.println("All Commands:");
 709         for (int i = 0; i < cmdInfo.length; i++)
 710             System.out.println("Command " + cmdInfo[i].getCommandName() + " [" +
 711                                             cmdInfo[i].getCommandClass() + "]");
 712         DataContentHandler dch = map.createDataContentHandler(argv[0]);
 713         if (dch != null)
 714             System.out.println("DataContentHandler " +
 715                                                 dch.getClass().toString());
 716         System.exit(0);
 717     }
 718     */
 719 }