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 }