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