1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 1999-2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *     http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 /*
  21  * $Id: Process.java,v 1.2.4.2 2005/09/15 18:21:57 jeffsuttor Exp $
  22  */
  23 package com.sun.org.apache.xalan.internal.xslt;
  24 
  25 import java.io.FileOutputStream;
  26 import java.io.FileWriter;
  27 import java.io.PrintWriter;
  28 import java.io.StringReader;
  29 import java.util.Properties;
  30 import java.util.ResourceBundle;
  31 import java.util.Vector;
  32 
  33 import javax.xml.XMLConstants;
  34 import javax.xml.parsers.DocumentBuilder;
  35 import javax.xml.parsers.DocumentBuilderFactory;
  36 import javax.xml.parsers.ParserConfigurationException;
  37 import javax.xml.transform.OutputKeys;
  38 import javax.xml.transform.Source;
  39 import javax.xml.transform.Templates;
  40 import javax.xml.transform.Transformer;
  41 import javax.xml.transform.TransformerConfigurationException;
  42 import javax.xml.transform.TransformerException;
  43 import javax.xml.transform.TransformerFactory;
  44 import javax.xml.transform.TransformerFactoryConfigurationError;
  45 import javax.xml.transform.URIResolver;
  46 import javax.xml.transform.dom.DOMResult;
  47 import javax.xml.transform.dom.DOMSource;
  48 import javax.xml.transform.sax.SAXResult;
  49 import javax.xml.transform.sax.SAXSource;
  50 import javax.xml.transform.sax.SAXTransformerFactory;
  51 import javax.xml.transform.sax.TransformerHandler;
  52 import javax.xml.transform.stream.StreamResult;
  53 import javax.xml.transform.stream.StreamSource;
  54 
  55 import com.sun.org.apache.xalan.internal.Version;
  56 import com.sun.org.apache.xalan.internal.res.XSLMessages;
  57 import com.sun.org.apache.xalan.internal.res.XSLTErrorResources;
  58 import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
  59 import com.sun.org.apache.xalan.internal.utils.ConfigurationError;
  60 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  61 
  62 //J2SE does not support Xalan interpretive
  63 /*
  64 import com.sun.org.apache.xalan.internal.trace.PrintTraceListener;
  65 import com.sun.org.apache.xalan.internal.trace.TraceManager;
  66 import com.sun.org.apache.xalan.internal.transformer.XalanProperties;
  67 */
  68 
  69 import com.sun.org.apache.xml.internal.utils.DefaultErrorHandler;
  70 
  71 import org.w3c.dom.Document;
  72 import org.w3c.dom.Node;
  73 
  74 import org.xml.sax.ContentHandler;
  75 import org.xml.sax.EntityResolver;
  76 import org.xml.sax.InputSource;
  77 import org.xml.sax.XMLReader;
  78 import org.xml.sax.helpers.XMLReaderFactory;
  79 
  80 /**
  81  * The main() method handles the Xalan command-line interface.
  82  * @xsl.usage general
  83  */
  84 public class Process
  85 {
  86   /**
  87    * Prints argument options.
  88    *
  89    * @param resbundle Resource bundle
  90    */
  91   protected static void printArgOptions(ResourceBundle resbundle)
  92   {
  93     System.out.println(resbundle.getString("xslProc_option"));  //"xslproc options: ");
  94     System.out.println("\n\t\t\t" + resbundle.getString("xslProc_common_options") + "\n");
  95     System.out.println(resbundle.getString("optionXSLTC"));  //"    [-XSLTC (use XSLTC for transformation)]
  96     System.out.println(resbundle.getString("optionIN"));  //"    [-IN inputXMLURL]");
  97     System.out.println(resbundle.getString("optionXSL"));  //"   [-XSL XSLTransformationURL]");
  98     System.out.println(resbundle.getString("optionOUT"));  //"   [-OUT outputFileName]");
  99 
 100     // System.out.println(resbundle.getString("optionE")); //"   [-E (Do not expand entity refs)]");
 101     System.out.println(resbundle.getString("optionV"));  //"   [-V (Version info)]");
 102 
 103     // System.out.println(resbundle.getString("optionVALIDATE")); //"   [-VALIDATE (Set whether validation occurs.  Validation is off by default.)]");
 104     System.out.println(resbundle.getString("optionEDUMP"));  //"   [-EDUMP {optional filename} (Do stackdump on error.)]");
 105     System.out.println(resbundle.getString("optionXML"));  //"   [-XML (Use XML formatter and add XML header.)]");
 106     System.out.println(resbundle.getString("optionTEXT"));  //"   [-TEXT (Use simple Text formatter.)]");
 107     System.out.println(resbundle.getString("optionHTML"));  //"   [-HTML (Use HTML formatter.)]");
 108     System.out.println(resbundle.getString("optionPARAM"));  //"   [-PARAM name expression (Set a stylesheet parameter)]");
 109 
 110     System.out.println(resbundle.getString("optionMEDIA"));
 111     System.out.println(resbundle.getString("optionFLAVOR"));
 112     System.out.println(resbundle.getString("optionDIAG"));
 113     System.out.println(resbundle.getString("optionURIRESOLVER"));  //"   [-URIRESOLVER full class name (URIResolver to be used to resolve URIs)]");
 114     System.out.println(resbundle.getString("optionENTITYRESOLVER"));  //"   [-ENTITYRESOLVER full class name (EntityResolver to be used to resolve entities)]");
 115     waitForReturnKey(resbundle);
 116     System.out.println(resbundle.getString("optionCONTENTHANDLER"));  //"   [-CONTENTHANDLER full class name (ContentHandler to be used to serialize output)]");
 117     System.out.println(resbundle.getString("optionSECUREPROCESSING")); //"   [-SECURE (set the secure processing feature to true)]");
 118 
 119     // J2SE does not support Xalan interpretive
 120     /*
 121     System.out.println("\n\t\t\t" + resbundle.getString("xslProc_xalan_options") + "\n");
 122 
 123     System.out.println(resbundle.getString("optionQC"));  //"   [-QC (Quiet Pattern Conflicts Warnings)]");
 124 
 125     // System.out.println(resbundle.getString("optionQ"));  //"   [-Q  (Quiet Mode)]"); // sc 28-Feb-01 commented out
 126     System.out.println(resbundle.getString("optionTT"));  //"   [-TT (Trace the templates as they are being called.)]");
 127     System.out.println(resbundle.getString("optionTG"));  //"   [-TG (Trace each generation event.)]");
 128     System.out.println(resbundle.getString("optionTS"));  //"   [-TS (Trace each selection event.)]");
 129     System.out.println(resbundle.getString("optionTTC"));  //"   [-TTC (Trace the template children as they are being processed.)]");
 130     System.out.println(resbundle.getString("optionTCLASS"));  //"   [-TCLASS (TraceListener class for trace extensions.)]");
 131     System.out.println(resbundle.getString("optionLINENUMBERS")); //"   [-L use line numbers]"
 132     System.out.println(resbundle.getString("optionINCREMENTAL"));
 133     System.out.println(resbundle.getString("optionNOOPTIMIMIZE"));
 134     System.out.println(resbundle.getString("optionRL"));
 135     */
 136 
 137     System.out.println("\n\t\t\t" + resbundle.getString("xslProc_xsltc_options") + "\n");
 138     System.out.println(resbundle.getString("optionXO"));
 139     waitForReturnKey(resbundle);
 140     System.out.println(resbundle.getString("optionXD"));
 141     System.out.println(resbundle.getString("optionXJ"));
 142     System.out.println(resbundle.getString("optionXP"));
 143     System.out.println(resbundle.getString("optionXN"));
 144     System.out.println(resbundle.getString("optionXX"));
 145     System.out.println(resbundle.getString("optionXT"));
 146   }
 147 
 148   /**
 149    * Command line interface to transform an XML document according to
 150    * the instructions found in an XSL stylesheet.
 151    * <p>The Process class provides basic functionality for
 152    * performing transformations from the command line.  To see a
 153    * list of arguments supported, call with zero arguments.</p>
 154    * <p>To set stylesheet parameters from the command line, use
 155    * <code>-PARAM name expression</code>. If you want to set the
 156    * parameter to a string value, simply pass the string value
 157    * as-is, and it will be interpreted as a string.  (Note: if
 158    * the value has spaces in it, you may need to quote it depending
 159    * on your shell environment).</p>
 160    *
 161    * @param argv Input parameters from command line
 162    */
 163   // J2SE does not support Xalan interpretive
 164   // main -> _main
 165   public static void _main(String argv[])
 166   {
 167 
 168     // Runtime.getRuntime().traceMethodCalls(false); // turns Java tracing off
 169     boolean doStackDumpOnError = false;
 170     boolean setQuietMode = false;
 171     boolean doDiag = false;
 172     String msg = null;
 173     boolean isSecureProcessing = false;
 174 
 175     // Runtime.getRuntime().traceMethodCalls(false);
 176     // Runtime.getRuntime().traceInstructions(false);
 177 
 178     /**
 179      * The default diagnostic writer...
 180      */
 181     java.io.PrintWriter diagnosticsWriter = new PrintWriter(System.err, true);
 182     java.io.PrintWriter dumpWriter = diagnosticsWriter;
 183     ResourceBundle resbundle =
 184       (SecuritySupport.getResourceBundle(
 185         com.sun.org.apache.xml.internal.utils.res.XResourceBundle.ERROR_RESOURCES));
 186     String flavor = "s2s";
 187 
 188     if (argv.length < 1)
 189     {
 190       printArgOptions(resbundle);
 191     }
 192     else
 193     {
 194         // J2SE does not support Xalan interpretive
 195         // false -> true
 196         boolean useXSLTC = true;
 197       for (int i = 0; i < argv.length; i++)
 198       {
 199         if ("-XSLTC".equalsIgnoreCase(argv[i]))
 200         {
 201           useXSLTC = true;
 202         }
 203       }
 204 
 205       TransformerFactory tfactory;
 206       if (useXSLTC)
 207       {
 208          String key = "javax.xml.transform.TransformerFactory";
 209          String value = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
 210          Properties props = System.getProperties();
 211          props.put(key, value);
 212          System.setProperties(props);
 213       }
 214 
 215       try
 216       {
 217         tfactory = TransformerFactory.newInstance();
 218         tfactory.setErrorListener(new DefaultErrorHandler());
 219       }
 220       catch (TransformerFactoryConfigurationError pfe)
 221       {
 222         pfe.printStackTrace(dumpWriter);
 223 //      "XSL Process was not successful.");
 224         msg = XSLMessages.createMessage(
 225             XSLTErrorResources.ER_NOT_SUCCESSFUL, null);
 226         diagnosticsWriter.println(msg);
 227 
 228         tfactory = null;  // shut up compiler
 229 
 230         doExit(msg);
 231       }
 232 
 233       boolean formatOutput = false;
 234       boolean useSourceLocation = false;
 235       String inFileName = null;
 236       String outFileName = null;
 237       String dumpFileName = null;
 238       String xslFileName = null;
 239       String treedumpFileName = null;
 240       // J2SE does not support Xalan interpretive
 241       /*
 242       PrintTraceListener tracer = null;
 243       */
 244       String outputType = null;
 245       String media = null;
 246       Vector params = new Vector();
 247       boolean quietConflictWarnings = false;
 248       URIResolver uriResolver = null;
 249       EntityResolver entityResolver = null;
 250       ContentHandler contentHandler = null;
 251       int recursionLimit=-1;
 252 
 253       for (int i = 0; i < argv.length; i++)
 254       {
 255         if ("-XSLTC".equalsIgnoreCase(argv[i]))
 256         {
 257           // The -XSLTC option has been processed.
 258         }
 259         // J2SE does not support Xalan interpretive
 260         /*
 261         else if ("-TT".equalsIgnoreCase(argv[i]))
 262         {
 263           if (!useXSLTC)
 264           {
 265             if (null == tracer)
 266               tracer = new PrintTraceListener(diagnosticsWriter);
 267 
 268             tracer.m_traceTemplates = true;
 269           }
 270           else
 271             printInvalidXSLTCOption("-TT");
 272 
 273           // tfactory.setTraceTemplates(true);
 274         }
 275         else if ("-TG".equalsIgnoreCase(argv[i]))
 276         {
 277           if (!useXSLTC)
 278           {
 279             if (null == tracer)
 280               tracer = new PrintTraceListener(diagnosticsWriter);
 281 
 282             tracer.m_traceGeneration = true;
 283           }
 284           else
 285             printInvalidXSLTCOption("-TG");
 286 
 287           // tfactory.setTraceSelect(true);
 288         }
 289         else if ("-TS".equalsIgnoreCase(argv[i]))
 290         {
 291           if (!useXSLTC)
 292           {
 293             if (null == tracer)
 294               tracer = new PrintTraceListener(diagnosticsWriter);
 295 
 296             tracer.m_traceSelection = true;
 297           }
 298           else
 299             printInvalidXSLTCOption("-TS");
 300 
 301           // tfactory.setTraceTemplates(true);
 302         }
 303         else if ("-TTC".equalsIgnoreCase(argv[i]))
 304         {
 305           if (!useXSLTC)
 306           {
 307             if (null == tracer)
 308               tracer = new PrintTraceListener(diagnosticsWriter);
 309 
 310             tracer.m_traceElements = true;
 311           }
 312           else
 313             printInvalidXSLTCOption("-TTC");
 314 
 315           // tfactory.setTraceTemplateChildren(true);
 316         }
 317         */
 318         else if ("-INDENT".equalsIgnoreCase(argv[i]))
 319         {
 320           int indentAmount;
 321 
 322           if (((i + 1) < argv.length) && (argv[i + 1].charAt(0) != '-'))
 323           {
 324             indentAmount = Integer.parseInt(argv[++i]);
 325           }
 326           else
 327           {
 328             indentAmount = 0;
 329           }
 330 
 331           // TBD:
 332           // xmlProcessorLiaison.setIndent(indentAmount);
 333         }
 334         else if ("-IN".equalsIgnoreCase(argv[i]))
 335         {
 336           if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 337             inFileName = argv[++i];
 338           else
 339             System.err.println(
 340               XSLMessages.createMessage(
 341                 XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 342                 new Object[]{ "-IN" }));  //"Missing argument for);
 343         }
 344         else if ("-MEDIA".equalsIgnoreCase(argv[i]))
 345         {
 346           if (i + 1 < argv.length)
 347             media = argv[++i];
 348           else
 349             System.err.println(
 350               XSLMessages.createMessage(
 351                 XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 352                 new Object[]{ "-MEDIA" }));  //"Missing argument for);
 353         }
 354         else if ("-OUT".equalsIgnoreCase(argv[i]))
 355         {
 356           if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 357             outFileName = argv[++i];
 358           else
 359             System.err.println(
 360               XSLMessages.createMessage(
 361                 XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 362                 new Object[]{ "-OUT" }));  //"Missing argument for);
 363         }
 364         else if ("-XSL".equalsIgnoreCase(argv[i]))
 365         {
 366           if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 367             xslFileName = argv[++i];
 368           else
 369             System.err.println(
 370               XSLMessages.createMessage(
 371                 XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 372                 new Object[]{ "-XSL" }));  //"Missing argument for);
 373         }
 374         else if ("-FLAVOR".equalsIgnoreCase(argv[i]))
 375         {
 376           if (i + 1 < argv.length)
 377           {
 378             flavor = argv[++i];
 379           }
 380           else
 381             System.err.println(
 382               XSLMessages.createMessage(
 383                 XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 384                 new Object[]{ "-FLAVOR" }));  //"Missing argument for);
 385         }
 386         else if ("-PARAM".equalsIgnoreCase(argv[i]))
 387         {
 388           if (i + 2 < argv.length)
 389           {
 390             String name = argv[++i];
 391 
 392             params.addElement(name);
 393 
 394             String expression = argv[++i];
 395 
 396             params.addElement(expression);
 397           }
 398           else
 399             System.err.println(
 400               XSLMessages.createMessage(
 401                 XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 402                 new Object[]{ "-PARAM" }));  //"Missing argument for);
 403         }
 404         else if ("-E".equalsIgnoreCase(argv[i]))
 405         {
 406 
 407           // TBD:
 408           // xmlProcessorLiaison.setShouldExpandEntityRefs(false);
 409         }
 410         else if ("-V".equalsIgnoreCase(argv[i]))
 411         {
 412           diagnosticsWriter.println(resbundle.getString("version")  //">>>>>>> Xalan Version "
 413                                     + Version.getVersion() + ", " +
 414 
 415           /* xmlProcessorLiaison.getParserDescription()+ */
 416           resbundle.getString("version2"));  // "<<<<<<<");
 417         }
 418         // J2SE does not support Xalan interpretive
 419         /*
 420         else if ("-QC".equalsIgnoreCase(argv[i]))
 421         {
 422           if (!useXSLTC)
 423             quietConflictWarnings = true;
 424           else
 425             printInvalidXSLTCOption("-QC");
 426         }
 427         */
 428         else if ("-Q".equalsIgnoreCase(argv[i]))
 429         {
 430           setQuietMode = true;
 431         }
 432         else if ("-DIAG".equalsIgnoreCase(argv[i]))
 433         {
 434           doDiag = true;
 435         }
 436         else if ("-XML".equalsIgnoreCase(argv[i]))
 437         {
 438           outputType = "xml";
 439         }
 440         else if ("-TEXT".equalsIgnoreCase(argv[i]))
 441         {
 442           outputType = "text";
 443         }
 444         else if ("-HTML".equalsIgnoreCase(argv[i]))
 445         {
 446           outputType = "html";
 447         }
 448         else if ("-EDUMP".equalsIgnoreCase(argv[i]))
 449         {
 450           doStackDumpOnError = true;
 451 
 452           if (((i + 1) < argv.length) && (argv[i + 1].charAt(0) != '-'))
 453           {
 454             dumpFileName = argv[++i];
 455           }
 456         }
 457         else if ("-URIRESOLVER".equalsIgnoreCase(argv[i]))
 458         {
 459           if (i + 1 < argv.length)
 460           {
 461             try
 462             {
 463               uriResolver = (URIResolver) ObjectFactory.newInstance(argv[++i], true);
 464 
 465               tfactory.setURIResolver(uriResolver);
 466             }
 467             catch (ConfigurationError cnfe)
 468             {
 469                 msg = XSLMessages.createMessage(
 470                     XSLTErrorResources.ER_CLASS_NOT_FOUND_FOR_OPTION,
 471                     new Object[]{ "-URIResolver" });
 472               System.err.println(msg);
 473               doExit(msg);
 474             }
 475           }
 476           else
 477           {
 478             msg = XSLMessages.createMessage(
 479                     XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 480                     new Object[]{ "-URIResolver" });  //"Missing argument for);
 481             System.err.println(msg);
 482             doExit(msg);
 483           }
 484         }
 485         else if ("-ENTITYRESOLVER".equalsIgnoreCase(argv[i]))
 486         {
 487           if (i + 1 < argv.length)
 488           {
 489             try
 490             {
 491               entityResolver = (EntityResolver) ObjectFactory.newInstance(argv[++i], true);
 492             }
 493             catch (ConfigurationError cnfe)
 494             {
 495                 msg = XSLMessages.createMessage(
 496                     XSLTErrorResources.ER_CLASS_NOT_FOUND_FOR_OPTION,
 497                     new Object[]{ "-EntityResolver" });
 498               System.err.println(msg);
 499               doExit(msg);
 500             }
 501           }
 502           else
 503           {
 504 //            "Missing argument for);
 505               msg = XSLMessages.createMessage(
 506                     XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 507                     new Object[]{ "-EntityResolver" });
 508             System.err.println(msg);
 509             doExit(msg);
 510           }
 511         }
 512         else if ("-CONTENTHANDLER".equalsIgnoreCase(argv[i]))
 513         {
 514           if (i + 1 < argv.length)
 515           {
 516             try
 517             {
 518               contentHandler = (ContentHandler) ObjectFactory.newInstance(argv[++i], true);
 519             }
 520             catch (ConfigurationError cnfe)
 521             {
 522                 msg = XSLMessages.createMessage(
 523                     XSLTErrorResources.ER_CLASS_NOT_FOUND_FOR_OPTION,
 524                     new Object[]{ "-ContentHandler" });
 525               System.err.println(msg);
 526               doExit(msg);
 527             }
 528           }
 529           else
 530           {
 531 //            "Missing argument for);
 532               msg = XSLMessages.createMessage(
 533                     XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 534                     new Object[]{ "-ContentHandler" });
 535             System.err.println(msg);
 536             doExit(msg);
 537           }
 538         }
 539         // J2SE does not support Xalan interpretive
 540         /*
 541         else if ("-L".equalsIgnoreCase(argv[i]))
 542         {
 543           if (!useXSLTC)
 544             tfactory.setAttribute(XalanProperties.SOURCE_LOCATION, Boolean.TRUE);
 545           else
 546             printInvalidXSLTCOption("-L");
 547         }
 548         else if ("-INCREMENTAL".equalsIgnoreCase(argv[i]))
 549         {
 550           if (!useXSLTC)
 551             tfactory.setAttribute
 552               ("http://xml.apache.org/xalan/features/incremental",
 553                java.lang.Boolean.TRUE);
 554           else
 555             printInvalidXSLTCOption("-INCREMENTAL");
 556         }
 557         else if ("-NOOPTIMIZE".equalsIgnoreCase(argv[i]))
 558         {
 559           // Default is true.
 560           //
 561           // %REVIEW% We should have a generalized syntax for negative
 562           // switches...  and probably should accept the inverse even
 563           // if it is the default.
 564           if (!useXSLTC)
 565             tfactory.setAttribute
 566               ("http://xml.apache.org/xalan/features/optimize",
 567                java.lang.Boolean.FALSE);
 568           else
 569             printInvalidXSLTCOption("-NOOPTIMIZE");
 570         }
 571         else if ("-RL".equalsIgnoreCase(argv[i]))
 572         {
 573           if (!useXSLTC)
 574           {
 575             if (i + 1 < argv.length)
 576               recursionLimit = Integer.parseInt(argv[++i]);
 577             else
 578               System.err.println(
 579                 XSLMessages.createMessage(
 580                   XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 581                   new Object[]{ "-rl" }));  //"Missing argument for);
 582           }
 583           else
 584           {
 585             if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 586              i++;
 587 
 588             printInvalidXSLTCOption("-RL");
 589           }
 590         }
 591         */
 592         // Generate the translet class and optionally specify the name
 593         // of the translet class.
 594         else if ("-XO".equalsIgnoreCase(argv[i]))
 595         {
 596           if (useXSLTC)
 597           {
 598             if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
 599             {
 600               tfactory.setAttribute("generate-translet", "true");
 601               tfactory.setAttribute("translet-name", argv[++i]);
 602             }
 603             else
 604               tfactory.setAttribute("generate-translet", "true");
 605           }
 606           else
 607           {
 608             if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 609              i++;
 610             printInvalidXalanOption("-XO");
 611           }
 612         }
 613         // Specify the destination directory for the translet classes.
 614         else if ("-XD".equalsIgnoreCase(argv[i]))
 615         {
 616           if (useXSLTC)
 617           {
 618             if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
 619               tfactory.setAttribute("destination-directory", argv[++i]);
 620             else
 621               System.err.println(
 622                 XSLMessages.createMessage(
 623                   XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 624                   new Object[]{ "-XD" }));  //"Missing argument for);
 625 
 626           }
 627           else
 628           {
 629             if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 630              i++;
 631 
 632             printInvalidXalanOption("-XD");
 633           }
 634         }
 635         // Specify the jar file name which the translet classes are packaged into.
 636         else if ("-XJ".equalsIgnoreCase(argv[i]))
 637         {
 638           if (useXSLTC)
 639           {
 640             if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
 641             {
 642               tfactory.setAttribute("generate-translet", "true");
 643               tfactory.setAttribute("jar-name", argv[++i]);
 644             }
 645             else
 646               System.err.println(
 647                 XSLMessages.createMessage(
 648                   XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 649                   new Object[]{ "-XJ" }));  //"Missing argument for);
 650           }
 651           else
 652           {
 653             if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 654              i++;
 655 
 656             printInvalidXalanOption("-XJ");
 657           }
 658 
 659         }
 660         // Specify the package name prefix for the generated translet classes.
 661         else if ("-XP".equalsIgnoreCase(argv[i]))
 662         {
 663           if (useXSLTC)
 664           {
 665             if (i + 1 < argv.length && argv[i+1].charAt(0) != '-')
 666               tfactory.setAttribute("package-name", argv[++i]);
 667             else
 668               System.err.println(
 669                 XSLMessages.createMessage(
 670                   XSLTErrorResources.ER_MISSING_ARG_FOR_OPTION,
 671                   new Object[]{ "-XP" }));  //"Missing argument for);
 672           }
 673           else
 674           {
 675             if (i + 1 < argv.length && argv[i + 1].charAt(0) != '-')
 676              i++;
 677 
 678             printInvalidXalanOption("-XP");
 679           }
 680 
 681         }
 682         // Enable template inlining.
 683         else if ("-XN".equalsIgnoreCase(argv[i]))
 684         {
 685           if (useXSLTC)
 686           {
 687             tfactory.setAttribute("enable-inlining", "true");
 688           }
 689           else
 690             printInvalidXalanOption("-XN");
 691         }
 692         // Turns on additional debugging message output
 693         else if ("-XX".equalsIgnoreCase(argv[i]))
 694         {
 695           if (useXSLTC)
 696           {
 697             tfactory.setAttribute("debug", "true");
 698           }
 699           else
 700             printInvalidXalanOption("-XX");
 701         }
 702         // Create the Transformer from the translet if the translet class is newer
 703         // than the stylesheet.
 704         else if ("-XT".equalsIgnoreCase(argv[i]))
 705         {
 706           if (useXSLTC)
 707           {
 708             tfactory.setAttribute("auto-translet", "true");
 709           }
 710           else
 711             printInvalidXalanOption("-XT");
 712         }
 713         else if ("-SECURE".equalsIgnoreCase(argv[i]))
 714         {
 715           isSecureProcessing = true;
 716           try
 717           {
 718             tfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 719           }
 720           catch (TransformerConfigurationException e) {}
 721         }
 722         else
 723           System.err.println(
 724             XSLMessages.createMessage(
 725               XSLTErrorResources.ER_INVALID_OPTION, new Object[]{ argv[i] }));  //"Invalid argument:);
 726       }
 727 
 728       // Print usage instructions if no xml and xsl file is specified in the command line
 729       if (inFileName == null && xslFileName == null)
 730       {
 731           msg = resbundle.getString("xslProc_no_input");
 732         System.err.println(msg);
 733         doExit(msg);
 734       }
 735 
 736       // Note that there are usage cases for calling us without a -IN arg
 737       // The main XSL transformation occurs here!
 738       try
 739       {
 740         long start = System.currentTimeMillis();
 741 
 742         if (null != dumpFileName)
 743         {
 744           dumpWriter = new PrintWriter(new FileWriter(dumpFileName));
 745         }
 746 
 747         Templates stylesheet = null;
 748 
 749         if (null != xslFileName)
 750         {
 751           if (flavor.equals("d2d"))
 752           {
 753 
 754             // Parse in the xml data into a DOM
 755             DocumentBuilderFactory dfactory =
 756               DocumentBuilderFactory.newInstance();
 757 
 758             dfactory.setNamespaceAware(true);
 759 
 760             if (isSecureProcessing)
 761             {
 762               try
 763               {
 764                 dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 765               }
 766               catch (ParserConfigurationException pce) {}
 767             }
 768 
 769             DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 770             Node xslDOM = docBuilder.parse(new InputSource(xslFileName));
 771 
 772             stylesheet = tfactory.newTemplates(new DOMSource(xslDOM,
 773                     xslFileName));
 774           }
 775           else
 776           {
 777             // System.out.println("Calling newTemplates: "+xslFileName);
 778             stylesheet = tfactory.newTemplates(new StreamSource(xslFileName));
 779             // System.out.println("Done calling newTemplates: "+xslFileName);
 780           }
 781         }
 782 
 783         PrintWriter resultWriter;
 784         StreamResult strResult;
 785 
 786         if (null != outFileName)
 787         {
 788           strResult = new StreamResult(new FileOutputStream(outFileName));
 789           // One possible improvement might be to ensure this is
 790           //  a valid URI before setting the systemId, but that
 791           //  might have subtle changes that pre-existing users
 792           //  might notice; we can think about that later -sc r1.46
 793           strResult.setSystemId(outFileName);
 794         }
 795         else
 796         {
 797           strResult = new StreamResult(System.out);
 798           // We used to default to incremental mode in this case.
 799           // We've since decided that since the -INCREMENTAL switch is
 800           // available, that default is probably not necessary nor
 801           // necessarily a good idea.
 802         }
 803 
 804         SAXTransformerFactory stf = (SAXTransformerFactory) tfactory;
 805 
 806         // J2SE does not support Xalan interpretive
 807         /*
 808                 // This is currently controlled via TransformerFactoryImpl.
 809         if (!useXSLTC && useSourceLocation)
 810            stf.setAttribute(XalanProperties.SOURCE_LOCATION, Boolean.TRUE);
 811         */
 812 
 813         // Did they pass in a stylesheet, or should we get it from the
 814         // document?
 815         if (null == stylesheet)
 816         {
 817           Source source =
 818             stf.getAssociatedStylesheet(new StreamSource(inFileName), media,
 819                                         null, null);
 820 
 821           if (null != source)
 822             stylesheet = tfactory.newTemplates(source);
 823           else
 824           {
 825             if (null != media)
 826               throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_STYLESHEET_IN_MEDIA, new Object[]{inFileName, media})); //"No stylesheet found in: "
 827                                             // + inFileName + ", media="
 828                                             // + media);
 829             else
 830               throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_STYLESHEET_PI, new Object[]{inFileName})); //"No xml-stylesheet PI found in: "
 831                                              //+ inFileName);
 832           }
 833         }
 834 
 835         if (null != stylesheet)
 836         {
 837           Transformer transformer = flavor.equals("th") ? null : stylesheet.newTransformer();
 838           transformer.setErrorListener(new DefaultErrorHandler());
 839 
 840           // Override the output format?
 841           if (null != outputType)
 842           {
 843             transformer.setOutputProperty(OutputKeys.METHOD, outputType);
 844           }
 845 
 846           // J2SE does not support Xalan interpretive
 847           /*
 848           if (transformer instanceof com.sun.org.apache.xalan.internal.transformer.TransformerImpl)
 849           {
 850             com.sun.org.apache.xalan.internal.transformer.TransformerImpl impl = (com.sun.org.apache.xalan.internal.transformer.TransformerImpl)transformer;
 851             TraceManager tm = impl.getTraceManager();
 852 
 853             if (null != tracer)
 854               tm.addTraceListener(tracer);
 855 
 856             impl.setQuietConflictWarnings(quietConflictWarnings);
 857 
 858                         // This is currently controlled via TransformerFactoryImpl.
 859             if (useSourceLocation)
 860               impl.setProperty(XalanProperties.SOURCE_LOCATION, Boolean.TRUE);
 861 
 862             if(recursionLimit>0)
 863               impl.setRecursionLimit(recursionLimit);
 864 
 865             // sc 28-Feb-01 if we re-implement this, please uncomment helpmsg in printArgOptions
 866             // impl.setDiagnosticsOutput( setQuietMode ? null : diagnosticsWriter );
 867           }
 868           */
 869 
 870           int nParams = params.size();
 871 
 872           for (int i = 0; i < nParams; i += 2)
 873           {
 874             transformer.setParameter((String) params.elementAt(i),
 875                                      (String) params.elementAt(i + 1));
 876           }
 877 
 878           if (uriResolver != null)
 879             transformer.setURIResolver(uriResolver);
 880 
 881           if (null != inFileName)
 882           {
 883             if (flavor.equals("d2d"))
 884             {
 885 
 886               // Parse in the xml data into a DOM
 887               DocumentBuilderFactory dfactory =
 888                 DocumentBuilderFactory.newInstance();
 889 
 890               dfactory.setCoalescing(true);
 891               dfactory.setNamespaceAware(true);
 892 
 893               if (isSecureProcessing)
 894               {
 895                 try
 896                 {
 897                   dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 898                 }
 899                 catch (ParserConfigurationException pce) {}
 900               }
 901 
 902               DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 903 
 904               if (entityResolver != null)
 905                 docBuilder.setEntityResolver(entityResolver);
 906 
 907               Node xmlDoc = docBuilder.parse(new InputSource(inFileName));
 908               Document doc = docBuilder.newDocument();
 909               org.w3c.dom.DocumentFragment outNode =
 910                 doc.createDocumentFragment();
 911 
 912               transformer.transform(new DOMSource(xmlDoc, inFileName),
 913                                     new DOMResult(outNode));
 914 
 915               // Now serialize output to disk with identity transformer
 916               Transformer serializer = stf.newTransformer();
 917               serializer.setErrorListener(new DefaultErrorHandler());
 918 
 919               Properties serializationProps =
 920                 stylesheet.getOutputProperties();
 921 
 922               serializer.setOutputProperties(serializationProps);
 923 
 924               if (contentHandler != null)
 925               {
 926                 SAXResult result = new SAXResult(contentHandler);
 927 
 928                 serializer.transform(new DOMSource(outNode), result);
 929               }
 930               else
 931                 serializer.transform(new DOMSource(outNode), strResult);
 932             }
 933             else if (flavor.equals("th"))
 934             {
 935               for (int i = 0; i < 1; i++) // Loop for diagnosing bugs with inconsistent behavior
 936               {
 937               // System.out.println("Testing the TransformerHandler...");
 938 
 939               XMLReader reader = null;
 940 
 941               // Use JAXP1.1 ( if possible )
 942               try
 943               {
 944                 javax.xml.parsers.SAXParserFactory factory =
 945                   javax.xml.parsers.SAXParserFactory.newInstance();
 946 
 947                 factory.setNamespaceAware(true);
 948 
 949                 if (isSecureProcessing)
 950                 {
 951                   try
 952                   {
 953                     factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 954                   }
 955                   catch (org.xml.sax.SAXException se) {}
 956                 }
 957 
 958                 javax.xml.parsers.SAXParser jaxpParser =
 959                   factory.newSAXParser();
 960 
 961                 reader = jaxpParser.getXMLReader();
 962               }
 963               catch (javax.xml.parsers.ParserConfigurationException ex)
 964               {
 965                 throw new org.xml.sax.SAXException(ex);
 966               }
 967               catch (javax.xml.parsers.FactoryConfigurationError ex1)
 968               {
 969                 throw new org.xml.sax.SAXException(ex1.toString());
 970               }
 971               catch (NoSuchMethodError ex2){}
 972               catch (AbstractMethodError ame){}
 973 
 974               if (null == reader)
 975               {
 976                 reader = XMLReaderFactory.createXMLReader();
 977               }
 978 
 979               // J2SE does not support Xalan interpretive
 980               /*
 981               if (!useXSLTC)
 982                 stf.setAttribute(com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.FEATURE_INCREMENTAL,
 983                    Boolean.TRUE);
 984               */
 985 
 986               TransformerHandler th = stf.newTransformerHandler(stylesheet);
 987 
 988               reader.setContentHandler(th);
 989               reader.setDTDHandler(th);
 990 
 991               if(th instanceof org.xml.sax.ErrorHandler)
 992                 reader.setErrorHandler((org.xml.sax.ErrorHandler)th);
 993 
 994               try
 995               {
 996                 reader.setProperty(
 997                   "http://xml.org/sax/properties/lexical-handler", th);
 998               }
 999               catch (org.xml.sax.SAXNotRecognizedException e){}
1000               catch (org.xml.sax.SAXNotSupportedException e){}
1001               try
1002               {
1003                 reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
1004                                   true);
1005               } catch (org.xml.sax.SAXException se) {}
1006 
1007               th.setResult(strResult);
1008 
1009               reader.parse(new InputSource(inFileName));
1010               }
1011             }
1012             else
1013             {
1014               if (entityResolver != null)
1015               {
1016                 XMLReader reader = null;
1017 
1018                 // Use JAXP1.1 ( if possible )
1019                 try
1020                 {
1021                   javax.xml.parsers.SAXParserFactory factory =
1022                     javax.xml.parsers.SAXParserFactory.newInstance();
1023 
1024                   factory.setNamespaceAware(true);
1025 
1026                   if (isSecureProcessing)
1027                   {
1028                     try
1029                     {
1030                       factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1031                     }
1032                     catch (org.xml.sax.SAXException se) {}
1033                   }
1034 
1035                   javax.xml.parsers.SAXParser jaxpParser =
1036                     factory.newSAXParser();
1037 
1038                   reader = jaxpParser.getXMLReader();
1039                 }
1040                 catch (javax.xml.parsers.ParserConfigurationException ex)
1041                 {
1042                   throw new org.xml.sax.SAXException(ex);
1043                 }
1044                 catch (javax.xml.parsers.FactoryConfigurationError ex1)
1045                 {
1046                   throw new org.xml.sax.SAXException(ex1.toString());
1047                 }
1048                 catch (NoSuchMethodError ex2){}
1049                 catch (AbstractMethodError ame){}
1050 
1051                 if (null == reader)
1052                 {
1053                   reader = XMLReaderFactory.createXMLReader();
1054                 }
1055 
1056                 reader.setEntityResolver(entityResolver);
1057 
1058                 if (contentHandler != null)
1059                 {
1060                   SAXResult result = new SAXResult(contentHandler);
1061 
1062                   transformer.transform(
1063                     new SAXSource(reader, new InputSource(inFileName)),
1064                     result);
1065                 }
1066                 else
1067                 {
1068                   transformer.transform(
1069                     new SAXSource(reader, new InputSource(inFileName)),
1070                     strResult);
1071                 }
1072               }
1073               else if (contentHandler != null)
1074               {
1075                 SAXResult result = new SAXResult(contentHandler);
1076 
1077                 transformer.transform(new StreamSource(inFileName), result);
1078               }
1079               else
1080               {
1081                 // System.out.println("Starting transform");
1082                 transformer.transform(new StreamSource(inFileName),
1083                                       strResult);
1084                 // System.out.println("Done with transform");
1085               }
1086             }
1087           }
1088           else
1089           {
1090             StringReader reader =
1091               new StringReader("<?xml version=\"1.0\"?> <doc/>");
1092 
1093             transformer.transform(new StreamSource(reader), strResult);
1094           }
1095         }
1096         else
1097         {
1098 //          "XSL Process was not successful.");
1099             msg = XSLMessages.createMessage(
1100                 XSLTErrorResources.ER_NOT_SUCCESSFUL, null);
1101           diagnosticsWriter.println(msg);
1102           doExit(msg);
1103         }
1104 
1105         // close output streams
1106         if (null != outFileName && strResult!=null)
1107         {
1108           java.io.OutputStream out = strResult.getOutputStream();
1109           java.io.Writer writer = strResult.getWriter();
1110           try
1111           {
1112             if (out != null) out.close();
1113             if (writer != null) writer.close();
1114           }
1115           catch(java.io.IOException ie) {}
1116         }
1117 
1118         long stop = System.currentTimeMillis();
1119         long millisecondsDuration = stop - start;
1120 
1121         if (doDiag)
1122         {
1123                 Object[] msgArgs = new Object[]{ inFileName, xslFileName, new Long(millisecondsDuration) };
1124             msg = XSLMessages.createMessage("diagTiming", msgArgs);
1125                 diagnosticsWriter.println('\n');
1126                 diagnosticsWriter.println(msg);
1127         }
1128 
1129       }
1130       catch (Throwable throwable)
1131       {
1132         while (throwable
1133                instanceof com.sun.org.apache.xml.internal.utils.WrappedRuntimeException)
1134         {
1135           throwable =
1136             ((com.sun.org.apache.xml.internal.utils.WrappedRuntimeException) throwable).getException();
1137         }
1138 
1139         if ((throwable instanceof NullPointerException)
1140                 || (throwable instanceof ClassCastException))
1141           doStackDumpOnError = true;
1142 
1143         diagnosticsWriter.println();
1144 
1145         if (doStackDumpOnError)
1146           throwable.printStackTrace(dumpWriter);
1147         else
1148         {
1149           DefaultErrorHandler.printLocation(diagnosticsWriter, throwable);
1150           diagnosticsWriter.println(
1151             XSLMessages.createMessage(XSLTErrorResources.ER_XSLT_ERROR, null)
1152             + " (" + throwable.getClass().getName() + "): "
1153             + throwable.getMessage());
1154         }
1155 
1156         // diagnosticsWriter.println(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_SUCCESSFUL, null)); //"XSL Process was not successful.");
1157         if (null != dumpFileName)
1158         {
1159           dumpWriter.close();
1160         }
1161 
1162         doExit(throwable.getMessage());
1163       }
1164 
1165       if (null != dumpFileName)
1166       {
1167         dumpWriter.close();
1168       }
1169 
1170       if (null != diagnosticsWriter)
1171       {
1172 
1173         // diagnosticsWriter.close();
1174       }
1175 
1176       // if(!setQuietMode)
1177       //  diagnosticsWriter.println(resbundle.getString("xsldone")); //"Xalan: done");
1178       // else
1179       // diagnosticsWriter.println("");  //"Xalan: done");
1180     }
1181   }
1182 
1183   /** It is _much_ easier to debug under VJ++ if I can set a single breakpoint
1184    * before this blows itself out of the water...
1185    * (I keep checking this in, it keeps vanishing. Grr!)
1186    * */
1187   static void doExit(String msg)
1188   {
1189     throw new RuntimeException(msg);
1190   }
1191 
1192   /**
1193    * Wait for a return key to continue
1194    *
1195    * @param resbundle The resource bundle
1196    */
1197   private static void waitForReturnKey(ResourceBundle resbundle)
1198   {
1199     System.out.println(resbundle.getString("xslProc_return_to_continue"));
1200     try
1201     {
1202       while (System.in.read() != '\n');
1203     }
1204     catch (java.io.IOException e) { }
1205   }
1206 
1207   /**
1208    * Print a message if an option cannot be used with -XSLTC.
1209    *
1210    * @param option The option String
1211    */
1212   private static void printInvalidXSLTCOption(String option)
1213   {
1214     System.err.println(XSLMessages.createMessage("xslProc_invalid_xsltc_option", new Object[]{option}));
1215   }
1216 
1217   /**
1218    * Print a message if an option can only be used with -XSLTC.
1219    *
1220    * @param option The option String
1221    */
1222   private static void printInvalidXalanOption(String option)
1223   {
1224     System.err.println(XSLMessages.createMessage("xslProc_invalid_xalan_option", new Object[]{option}));
1225   }
1226 }