1 /*
   2  * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  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 package com.sun.org.apache.xalan.internal.xsltc.trax;
  22 
  23 import com.sun.org.apache.xalan.internal.XalanConstants;
  24 import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
  25 import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase;
  26 import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
  27 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  28 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
  29 import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager;
  30 import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property;
  31 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
  32 import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader;
  33 import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
  34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  35 import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager;
  36 import com.sun.org.apache.xml.internal.utils.StopParseException;
  37 import com.sun.org.apache.xml.internal.utils.StylesheetPIHandler;
  38 import java.io.File;
  39 import java.io.FileInputStream;
  40 import java.io.FileNotFoundException;
  41 import java.io.FilenameFilter;
  42 import java.io.IOException;
  43 import java.io.InputStream;
  44 import java.net.MalformedURLException;
  45 import java.net.URL;
  46 import java.util.ArrayList;
  47 import java.util.Enumeration;
  48 import java.util.Map;
  49 import java.util.Properties;
  50 import java.util.Vector;
  51 import java.util.zip.ZipEntry;
  52 import java.util.zip.ZipFile;
  53 import javax.xml.XMLConstants;
  54 import javax.xml.catalog.CatalogFeatures;
  55 import javax.xml.catalog.CatalogFeatures.Feature;
  56 import javax.xml.catalog.CatalogManager;
  57 import javax.xml.catalog.CatalogUriResolver;
  58 import javax.xml.parsers.SAXParser;
  59 import javax.xml.parsers.SAXParserFactory;
  60 import javax.xml.transform.ErrorListener;
  61 import javax.xml.transform.Source;
  62 import javax.xml.transform.Templates;
  63 import javax.xml.transform.Transformer;
  64 import javax.xml.transform.TransformerConfigurationException;
  65 import javax.xml.transform.TransformerException;
  66 import javax.xml.transform.TransformerFactory;
  67 import javax.xml.transform.URIResolver;
  68 import javax.xml.transform.dom.DOMResult;
  69 import javax.xml.transform.dom.DOMSource;
  70 import javax.xml.transform.sax.SAXResult;
  71 import javax.xml.transform.sax.SAXSource;
  72 import javax.xml.transform.sax.SAXTransformerFactory;
  73 import javax.xml.transform.sax.TemplatesHandler;
  74 import javax.xml.transform.sax.TransformerHandler;
  75 import javax.xml.transform.stax.*;
  76 import javax.xml.transform.stream.StreamResult;
  77 import javax.xml.transform.stream.StreamSource;
  78 import jdk.xml.internal.JdkXmlFeatures;
  79 import jdk.xml.internal.JdkXmlUtils;
  80 import org.xml.sax.InputSource;
  81 import org.xml.sax.XMLFilter;
  82 import org.xml.sax.XMLReader;
  83 import org.xml.sax.helpers.XMLReaderFactory;
  84 
  85 /**
  86  * Implementation of a JAXP1.1 TransformerFactory for Translets.
  87  * @author G. Todd Miller
  88  * @author Morten Jorgensen
  89  * @author Santiago Pericas-Geertsen
  90  */
  91 @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory
  92 public class TransformerFactoryImpl
  93     extends SAXTransformerFactory implements SourceLoader, ErrorListener
  94 {
  95     // Public constants for attributes supported by the XSLTC TransformerFactory.
  96     public final static String TRANSLET_NAME = "translet-name";
  97     public final static String DESTINATION_DIRECTORY = "destination-directory";
  98     public final static String PACKAGE_NAME = "package-name";
  99     public final static String JAR_NAME = "jar-name";
 100     public final static String GENERATE_TRANSLET = "generate-translet";
 101     public final static String AUTO_TRANSLET = "auto-translet";
 102     public final static String USE_CLASSPATH = "use-classpath";
 103     public final static String DEBUG = "debug";
 104     public final static String ENABLE_INLINING = "enable-inlining";
 105     public final static String INDENT_NUMBER = "indent-number";
 106 
 107     /**
 108      * This error listener is used only for this factory and is not passed to
 109      * the Templates or Transformer objects that we create.
 110      */
 111     private ErrorListener _errorListener = this;
 112 
 113     /**
 114      * This URIResolver is passed to all created Templates and Transformers
 115      */
 116     private URIResolver _uriResolver = null;
 117 
 118     /**
 119      * As Gregor Samsa awoke one morning from uneasy dreams he found himself
 120      * transformed in his bed into a gigantic insect. He was lying on his hard,
 121      * as it were armour plated, back, and if he lifted his head a little he
 122      * could see his big, brown belly divided into stiff, arched segments, on
 123      * top of which the bed quilt could hardly keep in position and was about
 124      * to slide off completely. His numerous legs, which were pitifully thin
 125      * compared to the rest of his bulk, waved helplessly before his eyes.
 126      * "What has happened to me?", he thought. It was no dream....
 127      */
 128     protected final static String DEFAULT_TRANSLET_NAME = "GregorSamsa";
 129 
 130     /**
 131      * The class name of the translet
 132      */
 133     private String _transletName = DEFAULT_TRANSLET_NAME;
 134 
 135     /**
 136      * The destination directory for the translet
 137      */
 138     private String _destinationDirectory = null;
 139 
 140     /**
 141      * The package name prefix for all generated translet classes
 142      */
 143     private static final String DEFAULT_TRANSLATE_PACKAGE = "die.verwandlung";
 144     private String _packageName = DEFAULT_TRANSLATE_PACKAGE;
 145 
 146     /**
 147      * The jar file name which the translet classes are packaged into
 148      */
 149     private String _jarFileName = null;
 150 
 151     /**
 152      * This Map is used to store parameters for locating
 153      * <?xml-stylesheet ...?> processing instructions in XML docs.
 154      */
 155     private Map<Source, PIParamWrapper> _piParams = null;
 156 
 157     /**
 158      * The above Map stores objects of this class.
 159      */
 160     private static class PIParamWrapper {
 161         public String _media = null;
 162         public String _title = null;
 163         public String _charset = null;
 164 
 165         public PIParamWrapper(String media, String title, String charset) {
 166             _media = media;
 167             _title = title;
 168             _charset = charset;
 169         }
 170     }
 171 
 172     /**
 173      * Set to <code>true</code> when debugging is enabled.
 174      */
 175     private boolean _debug = false;
 176 
 177     /**
 178      * Set to <code>true</code> when templates are inlined.
 179      */
 180     private boolean _enableInlining = false;
 181 
 182     /**
 183      * Set to <code>true</code> when we want to generate
 184      * translet classes from the stylesheet.
 185      */
 186     private boolean _generateTranslet = false;
 187 
 188     /**
 189      * If this is set to <code>true</code>, we attempt to use translet classes
 190      * for transformation if possible without compiling the stylesheet. The
 191      * translet class is only used if its timestamp is newer than the timestamp
 192      * of the stylesheet.
 193      */
 194     private boolean _autoTranslet = false;
 195 
 196     /**
 197      * If this is set to <code>true</code>, we attempt to load the translet
 198      * from the CLASSPATH.
 199      */
 200     private boolean _useClasspath = false;
 201 
 202     /**
 203      * Number of indent spaces when indentation is turned on.
 204      */
 205     private int _indentNumber = -1;
 206 
 207     /**
 208      * <p>State of secure processing feature.</p>
 209      */
 210     private boolean _isNotSecureProcessing = true;
 211     /**
 212      * <p>State of secure mode.</p>
 213      */
 214     private boolean _isSecureMode = false;
 215 
 216     /**
 217      * Indicates whether implementation parts should use
 218      *   service loader (or similar).
 219      * Note the default value (false) is the safe option..
 220      */
 221     private boolean _useServicesMechanism;
 222 
 223     /**
 224      * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
 225      */
 226     private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
 227      /**
 228      * protocols allowed for external DTD references in source file and/or stylesheet.
 229      */
 230     private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
 231 
 232     private XMLSecurityPropertyManager _xmlSecurityPropertyMgr;
 233     private XMLSecurityManager _xmlSecurityManager;
 234 
 235     private final JdkXmlFeatures _xmlFeatures;
 236 
 237     private ClassLoader _extensionClassLoader = null;
 238 
 239     // Unmodifiable view of external extension function from xslt compiler
 240     // It will be populated by user-specified extension functions during the
 241     // type checking
 242     private Map<String, Class> _xsltcExtensionFunctions;
 243 
 244     CatalogUriResolver _catalogUriResolver;
 245     CatalogFeatures _catalogFeatures;
 246     CatalogFeatures.Builder cfBuilder = CatalogFeatures.builder();
 247     // Catalog features
 248     String _catalogFiles = null;
 249     String _catalogDefer = null;
 250     String _catalogPrefer = null;
 251     String _catalogResolve = null;
 252 
 253     /**
 254      * javax.xml.transform.sax.TransformerFactory implementation.
 255      */
 256     public TransformerFactoryImpl() {
 257         this(true);
 258     }
 259 
 260     public static TransformerFactory newTransformerFactoryNoServiceLoader() {
 261         return new TransformerFactoryImpl(false);
 262     }
 263 
 264     private TransformerFactoryImpl(boolean useServicesMechanism) {
 265         this._useServicesMechanism = useServicesMechanism;
 266 
 267         if (System.getSecurityManager() != null) {
 268             _isSecureMode = true;
 269             _isNotSecureProcessing = false;
 270         }
 271 
 272         _xmlFeatures = new JdkXmlFeatures(!_isNotSecureProcessing);
 273         _xmlSecurityPropertyMgr = new XMLSecurityPropertyManager();
 274         _accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
 275                 Property.ACCESS_EXTERNAL_DTD);
 276         _accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(
 277                 Property.ACCESS_EXTERNAL_STYLESHEET);
 278 
 279         //Parser's security manager
 280         _xmlSecurityManager = new XMLSecurityManager(true);
 281         //Unmodifiable hash map with loaded external extension functions
 282         _xsltcExtensionFunctions = null;
 283     }
 284 
 285     public Map<String,Class> getExternalExtensionsMap() {
 286         return _xsltcExtensionFunctions;
 287     }
 288 
 289     /**
 290      * javax.xml.transform.sax.TransformerFactory implementation.
 291      * Set the error event listener for the TransformerFactory, which is used
 292      * for the processing of transformation instructions, and not for the
 293      * transformation itself.
 294      *
 295      * @param listener The error listener to use with the TransformerFactory
 296      * @throws IllegalArgumentException
 297      */
 298     @Override
 299     public void setErrorListener(ErrorListener listener)
 300         throws IllegalArgumentException
 301     {
 302         if (listener == null) {
 303             ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR,
 304                                         "TransformerFactory");
 305             throw new IllegalArgumentException(err.toString());
 306         }
 307         _errorListener = listener;
 308     }
 309 
 310     /**
 311      * javax.xml.transform.sax.TransformerFactory implementation.
 312      * Get the error event handler for the TransformerFactory.
 313      *
 314      * @return The error listener used with the TransformerFactory
 315      */
 316     @Override
 317     public ErrorListener getErrorListener() {
 318         return _errorListener;
 319     }
 320 
 321     /**
 322      * Returns the package name.
 323      */
 324     String getPackageName() {
 325         return _packageName;
 326     }
 327 
 328     /**
 329      * javax.xml.transform.sax.TransformerFactory implementation.
 330      * Returns the value set for a TransformerFactory attribute
 331      *
 332      * @param name The attribute name
 333      * @return An object representing the attribute value
 334      * @throws IllegalArgumentException
 335      */
 336     @Override
 337     public Object getAttribute(String name)
 338         throws IllegalArgumentException
 339     {
 340         // Return value for attribute 'translet-name'
 341         if (name.equals(TRANSLET_NAME)) {
 342             return _transletName;
 343         }
 344         else if (name.equals(GENERATE_TRANSLET)) {
 345             return _generateTranslet;
 346         }
 347         else if (name.equals(AUTO_TRANSLET)) {
 348             return _autoTranslet;
 349         }
 350         else if (name.equals(ENABLE_INLINING)) {
 351             if (_enableInlining)
 352               return Boolean.TRUE;
 353             else
 354               return Boolean.FALSE;
 355         } else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
 356             return _xmlSecurityManager;
 357         } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
 358            return _extensionClassLoader;
 359         } else if (JdkXmlUtils.CATALOG_FILES.equals(name)) {
 360             return _catalogFiles;
 361         } else if (JdkXmlUtils.CATALOG_DEFER.equals(name)) {
 362             return _catalogDefer;
 363         } else if (JdkXmlUtils.CATALOG_PREFER.equals(name)) {
 364             return _catalogPrefer;
 365         } else if (JdkXmlUtils.CATALOG_RESOLVE.equals(name)) {
 366             return _catalogResolve;
 367         } else if (JdkXmlFeatures.CATALOG_FEATURES.equals(name)) {
 368             return buildCatalogFeatures();
 369         }
 370 
 371         /** Check to see if the property is managed by the security manager **/
 372         String propertyValue = (_xmlSecurityManager != null) ?
 373                 _xmlSecurityManager.getLimitAsString(name) : null;
 374         if (propertyValue != null) {
 375             return propertyValue;
 376         } else {
 377             propertyValue = (_xmlSecurityPropertyMgr != null) ?
 378                 _xmlSecurityPropertyMgr.getValue(name) : null;
 379             if (propertyValue != null) {
 380                 return propertyValue;
 381             }
 382         }
 383 
 384         // Throw an exception for all other attributes
 385         ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name);
 386         throw new IllegalArgumentException(err.toString());
 387     }
 388 
 389     /**
 390      * javax.xml.transform.sax.TransformerFactory implementation.
 391      * Sets the value for a TransformerFactory attribute.
 392      *
 393      * @param name The attribute name
 394      * @param value An object representing the attribute value
 395      * @throws IllegalArgumentException
 396      */
 397     @Override
 398     public void setAttribute(String name, Object value)
 399         throws IllegalArgumentException
 400     {
 401         // Set the default translet name (ie. class name), which will be used
 402         // for translets that cannot be given a name from their system-id.
 403         if (name.equals(TRANSLET_NAME) && value instanceof String) {
 404             _transletName = (String) value;
 405             return;
 406         }
 407         else if (name.equals(DESTINATION_DIRECTORY) && value instanceof String) {
 408             _destinationDirectory = (String) value;
 409             return;
 410         }
 411         else if (name.equals(PACKAGE_NAME) && value instanceof String) {
 412             _packageName = (String) value;
 413             return;
 414         }
 415         else if (name.equals(JAR_NAME) && value instanceof String) {
 416             _jarFileName = (String) value;
 417             return;
 418         }
 419         else if (name.equals(GENERATE_TRANSLET)) {
 420             if (value instanceof Boolean) {
 421                 _generateTranslet = ((Boolean) value);
 422                 return;
 423             }
 424             else if (value instanceof String) {
 425                 _generateTranslet = ((String) value).equalsIgnoreCase("true");
 426                 return;
 427             }
 428         }
 429         else if (name.equals(AUTO_TRANSLET)) {
 430             if (value instanceof Boolean) {
 431                 _autoTranslet = ((Boolean) value);
 432                 return;
 433             }
 434             else if (value instanceof String) {
 435                 _autoTranslet = ((String) value).equalsIgnoreCase("true");
 436                 return;
 437             }
 438         }
 439         else if (name.equals(USE_CLASSPATH)) {
 440             if (value instanceof Boolean) {
 441                 _useClasspath = ((Boolean) value);
 442                 return;
 443             }
 444             else if (value instanceof String) {
 445                 _useClasspath = ((String) value).equalsIgnoreCase("true");
 446                 return;
 447             }
 448         }
 449         else if (name.equals(DEBUG)) {
 450             if (value instanceof Boolean) {
 451                 _debug = ((Boolean) value);
 452                 return;
 453             }
 454             else if (value instanceof String) {
 455                 _debug = ((String) value).equalsIgnoreCase("true");
 456                 return;
 457             }
 458         }
 459         else if (name.equals(ENABLE_INLINING)) {
 460             if (value instanceof Boolean) {
 461                 _enableInlining = ((Boolean) value);
 462                 return;
 463             }
 464             else if (value instanceof String) {
 465                 _enableInlining = ((String) value).equalsIgnoreCase("true");
 466                 return;
 467             }
 468         }
 469         else if (name.equals(INDENT_NUMBER)) {
 470             if (value instanceof String) {
 471                 try {
 472                     _indentNumber = Integer.parseInt((String) value);
 473                     return;
 474                 }
 475                 catch (NumberFormatException e) {
 476                     // Falls through
 477                 }
 478             }
 479             else if (value instanceof Integer) {
 480                 _indentNumber = ((Integer) value);
 481                 return;
 482             }
 483         }
 484         else if ( name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
 485             if (value instanceof ClassLoader) {
 486                 _extensionClassLoader = (ClassLoader) value;
 487                 return;
 488             } else {
 489                 final ErrorMsg err
 490                     = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_VALUE_ERR, "Extension Functions ClassLoader");
 491                 throw new IllegalArgumentException(err.toString());
 492             }
 493         } else if (JdkXmlUtils.CATALOG_FILES.equals(name)) {
 494             _catalogFiles = (String) value;
 495             cfBuilder = CatalogFeatures.builder().with(Feature.FILES, _catalogFiles);
 496             return;
 497         } else if (JdkXmlUtils.CATALOG_DEFER.equals(name)) {
 498             _catalogDefer = (String) value;
 499             cfBuilder = CatalogFeatures.builder().with(Feature.DEFER, _catalogDefer);
 500             return;
 501         } else if (JdkXmlUtils.CATALOG_PREFER.equals(name)) {
 502             _catalogPrefer = (String) value;
 503             cfBuilder = CatalogFeatures.builder().with(Feature.PREFER, _catalogPrefer);
 504             return;
 505         } else if (JdkXmlUtils.CATALOG_RESOLVE.equals(name)) {
 506             _catalogResolve = (String) value;
 507             cfBuilder = CatalogFeatures.builder().with(Feature.RESOLVE, _catalogResolve);
 508             return;
 509         }
 510 
 511         if (_xmlSecurityManager != null &&
 512                 _xmlSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) {
 513             return;
 514         }
 515 
 516         if (_xmlSecurityPropertyMgr != null &&
 517             _xmlSecurityPropertyMgr.setValue(name, XMLSecurityPropertyManager.State.APIPROPERTY, value)) {
 518             _accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
 519                     Property.ACCESS_EXTERNAL_DTD);
 520             _accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(
 521                     Property.ACCESS_EXTERNAL_STYLESHEET);
 522             return;
 523         }
 524 
 525         // Throw an exception for all other attributes
 526         final ErrorMsg err
 527             = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name);
 528         throw new IllegalArgumentException(err.toString());
 529     }
 530 
 531     /**
 532      * <p>Set a feature for this <code>TransformerFactory</code> and <code>Transformer</code>s
 533      * or <code>Template</code>s created by this factory.</p>
 534      *
 535      * <p>
 536      * Feature names are fully qualified {@link java.net.URI}s.
 537      * Implementations may define their own features.
 538      * An {@link TransformerConfigurationException} is thrown if this <code>TransformerFactory</code> or the
 539      * <code>Transformer</code>s or <code>Template</code>s it creates cannot support the feature.
 540      * It is possible for an <code>TransformerFactory</code> to expose a feature value but be unable to change its state.
 541      * </p>
 542      *
 543      * <p>See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.</p>
 544      *
 545      * @param name Feature name.
 546      * @param value Is feature state <code>true</code> or <code>false</code>.
 547      *
 548      * @throws TransformerConfigurationException if this <code>TransformerFactory</code>
 549      *   or the <code>Transformer</code>s or <code>Template</code>s it creates cannot support this feature.
 550      * @throws NullPointerException If the <code>name</code> parameter is null.
 551      */
 552     @Override
 553     public void setFeature(String name, boolean value)
 554         throws TransformerConfigurationException {
 555 
 556         // feature name cannot be null
 557         if (name == null) {
 558             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_FEATURE_NULL_NAME);
 559             throw new NullPointerException(err.toString());
 560         }
 561         // secure processing?
 562         else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 563             if ((_isSecureMode) && (!value)) {
 564                 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SECUREPROCESSING_FEATURE);
 565                 throw new TransformerConfigurationException(err.toString());
 566             }
 567             _isNotSecureProcessing = !value;
 568             _xmlSecurityManager.setSecureProcessing(value);
 569 
 570             // set external access restriction when FSP is explicitly set
 571             if (value) {
 572                 _xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_DTD,
 573                         FeaturePropertyBase.State.FSP, XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
 574                 _xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_STYLESHEET,
 575                         FeaturePropertyBase.State.FSP, XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
 576                 _accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
 577                         Property.ACCESS_EXTERNAL_DTD);
 578                 _accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(
 579                         Property.ACCESS_EXTERNAL_STYLESHEET);
 580             }
 581 
 582             if (value && _xmlFeatures != null) {
 583                 _xmlFeatures.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION,
 584                         JdkXmlFeatures.State.FSP, false);
 585             }
 586         }
 587         else if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) {
 588             //in secure mode, let _useServicesMechanism be determined by the constructor
 589             if (!_isSecureMode)
 590                 _useServicesMechanism = value;
 591         }
 592         else {
 593             if (_xmlFeatures != null &&
 594                     _xmlFeatures.setFeature(name, JdkXmlFeatures.State.APIPROPERTY, value)) {
 595                 return;
 596             }
 597 
 598             // unknown feature
 599             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name);
 600             throw new TransformerConfigurationException(err.toString());
 601         }
 602     }
 603 
 604     /**
 605      * javax.xml.transform.sax.TransformerFactory implementation.
 606      * Look up the value of a feature (to see if it is supported).
 607      * This method must be updated as the various methods and features of this
 608      * class are implemented.
 609      *
 610      * @param name The feature name
 611      * @return 'true' if feature is supported, 'false' if not
 612      */
 613     @Override
 614     public boolean getFeature(String name) {
 615         // All supported features should be listed here
 616         String[] features = {
 617             DOMSource.FEATURE,
 618             DOMResult.FEATURE,
 619             SAXSource.FEATURE,
 620             SAXResult.FEATURE,
 621             StAXSource.FEATURE,
 622             StAXResult.FEATURE,
 623             StreamSource.FEATURE,
 624             StreamResult.FEATURE,
 625             SAXTransformerFactory.FEATURE,
 626             SAXTransformerFactory.FEATURE_XMLFILTER,
 627             XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM
 628         };
 629 
 630         // feature name cannot be null
 631         if (name == null) {
 632             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_GET_FEATURE_NULL_NAME);
 633             throw new NullPointerException(err.toString());
 634         }
 635 
 636         // Inefficient, but array is small
 637         for (int i =0; i < features.length; i++) {
 638             if (name.equals(features[i])) {
 639                 return true;
 640             }
 641         }
 642 
 643         if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 644             return !_isNotSecureProcessing;
 645         }
 646 
 647         /** Check to see if the property is managed by the JdkXmlFeatues **/
 648         int index = _xmlFeatures.getIndex(name);
 649         if (index > -1) {
 650             return _xmlFeatures.getFeature(index);
 651         }
 652 
 653         // Feature not supported
 654         return false;
 655     }
 656     /**
 657      * Return the state of the services mechanism feature.
 658      */
 659     public boolean useServicesMechnism() {
 660         return _useServicesMechanism;
 661     }
 662 
 663      /**
 664      * @return the feature manager
 665      */
 666     public JdkXmlFeatures getJdkXmlFeatures() {
 667         return _xmlFeatures;
 668     }
 669 
 670     /**
 671      * javax.xml.transform.sax.TransformerFactory implementation.
 672      * Get the object that is used by default during the transformation to
 673      * resolve URIs used in document(), xsl:import, or xsl:include.
 674      *
 675      * @return The URLResolver used for this TransformerFactory and all
 676      * Templates and Transformer objects created using this factory
 677      */
 678     @Override
 679     public URIResolver getURIResolver() {
 680         return _uriResolver;
 681     }
 682 
 683     /**
 684      * javax.xml.transform.sax.TransformerFactory implementation.
 685      * Set the object that is used by default during the transformation to
 686      * resolve URIs used in document(), xsl:import, or xsl:include. Note that
 687      * this does not affect Templates and Transformers that are already
 688      * created with this factory.
 689      *
 690      * @param resolver The URLResolver used for this TransformerFactory and all
 691      * Templates and Transformer objects created using this factory
 692      */
 693     @Override
 694     public void setURIResolver(URIResolver resolver) {
 695         _uriResolver = resolver;
 696     }
 697 
 698     /**
 699      * javax.xml.transform.sax.TransformerFactory implementation.
 700      * Get the stylesheet specification(s) associated via the xml-stylesheet
 701      * processing instruction (see http://www.w3.org/TR/xml-stylesheet/) with
 702      * the document document specified in the source parameter, and that match
 703      * the given criteria.
 704      *
 705      * @param source The XML source document.
 706      * @param media The media attribute to be matched. May be null, in which
 707      * case the prefered templates will be used (i.e. alternate = no).
 708      * @param title The value of the title attribute to match. May be null.
 709      * @param charset The value of the charset attribute to match. May be null.
 710      * @return A Source object suitable for passing to the TransformerFactory.
 711      * @throws TransformerConfigurationException
 712      */
 713     @Override
 714     public Source  getAssociatedStylesheet(Source source, String media,
 715                                           String title, String charset)
 716         throws TransformerConfigurationException {
 717 
 718         String baseId;
 719         XMLReader reader;
 720         InputSource isource;
 721 
 722 
 723         /**
 724          * Fix for bugzilla bug 24187
 725          */
 726         StylesheetPIHandler _stylesheetPIHandler = new StylesheetPIHandler(null,media,title,charset);
 727 
 728         try {
 729 
 730             if (source instanceof DOMSource ) {
 731                 final DOMSource domsrc = (DOMSource) source;
 732                 baseId = domsrc.getSystemId();
 733                 final org.w3c.dom.Node node = domsrc.getNode();
 734                 final DOM2SAX dom2sax = new DOM2SAX(node);
 735 
 736                 _stylesheetPIHandler.setBaseId(baseId);
 737 
 738                 dom2sax.setContentHandler( _stylesheetPIHandler);
 739                 dom2sax.parse();
 740             } else {
 741                 isource = SAXSource.sourceToInputSource(source);
 742                 baseId = isource.getSystemId();
 743 
 744                 SAXParserFactory factory = FactoryImpl.getSAXFactory(_useServicesMechanism);
 745                 factory.setNamespaceAware(true);
 746 
 747                 if (!_isNotSecureProcessing) {
 748                     try {
 749                         factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 750                     }
 751                     catch (org.xml.sax.SAXException e) {}
 752                 }
 753 
 754                 SAXParser jaxpParser = factory.newSAXParser();
 755 
 756                 reader = jaxpParser.getXMLReader();
 757                 if (reader == null) {
 758                     reader = XMLReaderFactory.createXMLReader();
 759                 }
 760 
 761                 _stylesheetPIHandler.setBaseId(baseId);
 762                 reader.setContentHandler(_stylesheetPIHandler);
 763                 reader.parse(isource);
 764 
 765             }
 766 
 767             if (_uriResolver != null ) {
 768                 _stylesheetPIHandler.setURIResolver(_uriResolver);
 769             }
 770 
 771         } catch (StopParseException e ) {
 772           // startElement encountered so do not parse further
 773 
 774         } catch (javax.xml.parsers.ParserConfigurationException | org.xml.sax.SAXException | IOException e) {
 775              throw new TransformerConfigurationException(
 776              "getAssociatedStylesheets failed", e);
 777         }
 778 
 779          return _stylesheetPIHandler.getAssociatedStylesheet();
 780 
 781     }
 782 
 783     /**
 784      * javax.xml.transform.sax.TransformerFactory implementation.
 785      * Create a Transformer object that copies the input document to the result.
 786      *
 787      * @return A Transformer object that simply copies the source to the result.
 788      * @throws TransformerConfigurationException
 789      */
 790     @Override
 791     public Transformer newTransformer()
 792         throws TransformerConfigurationException
 793     {
 794         // create CatalogFeatures that is accessible by the Transformer
 795         // through the factory instance
 796         buildCatalogFeatures();
 797         TransformerImpl result = new TransformerImpl(new Properties(),
 798             _indentNumber, this);
 799         if (_uriResolver != null) {
 800             result.setURIResolver(_uriResolver);
 801         }
 802 
 803         if (!_isNotSecureProcessing) {
 804             result.setSecureProcessing(true);
 805         }
 806         return result;
 807     }
 808 
 809     /**
 810      * javax.xml.transform.sax.TransformerFactory implementation.
 811      * Process the Source into a Templates object, which is a a compiled
 812      * representation of the source. Note that this method should not be
 813      * used with XSLTC, as the time-consuming compilation is done for each
 814      * and every transformation.
 815      *
 816      * @return A Templates object that can be used to create Transformers.
 817      * @throws TransformerConfigurationException
 818      */
 819     @Override
 820     public Transformer newTransformer(Source source) throws
 821         TransformerConfigurationException
 822     {
 823         final Templates templates = newTemplates(source);
 824         final Transformer transformer = templates.newTransformer();
 825         if (_uriResolver != null) {
 826             transformer.setURIResolver(_uriResolver);
 827         }
 828         return(transformer);
 829     }
 830 
 831     /**
 832      * Pass warning messages from the compiler to the error listener
 833      */
 834     private void passWarningsToListener(ArrayList<ErrorMsg> messages)
 835         throws TransformerException
 836     {
 837         if (_errorListener == null || messages == null) {
 838             return;
 839         }
 840         // Pass messages to listener, one by one
 841         final int count = messages.size();
 842         for (int pos = 0; pos < count; pos++) {
 843             ErrorMsg msg = messages.get(pos);
 844             // Workaround for the TCK failure ErrorListener.errorTests.error001.
 845             if (msg.isWarningError())
 846                 _errorListener.error(
 847                     new TransformerConfigurationException(msg.toString()));
 848             else
 849                 _errorListener.warning(
 850                     new TransformerConfigurationException(msg.toString()));
 851         }
 852     }
 853 
 854     /**
 855      * Pass error messages from the compiler to the error listener
 856      */
 857     private void passErrorsToListener(ArrayList<ErrorMsg> messages) {
 858         try {
 859             if (_errorListener == null || messages == null) {
 860                 return;
 861             }
 862             // Pass messages to listener, one by one
 863             final int count = messages.size();
 864             for (int pos = 0; pos < count; pos++) {
 865                 String message = messages.get(pos).toString();
 866                 _errorListener.error(new TransformerException(message));
 867             }
 868         }
 869         catch (TransformerException e) {
 870             // nada
 871         }
 872     }
 873 
 874     /**
 875      * javax.xml.transform.sax.TransformerFactory implementation.
 876      * Process the Source into a Templates object, which is a a compiled
 877      * representation of the source.
 878      *
 879      * @param source The input stylesheet - DOMSource not supported!!!
 880      * @return A Templates object that can be used to create Transformers.
 881      * @throws TransformerConfigurationException
 882      */
 883     @Override
 884     public Templates newTemplates(Source source)
 885         throws TransformerConfigurationException
 886     {
 887         // If the _useClasspath attribute is true, try to load the translet from
 888         // the CLASSPATH and create a template object using the loaded
 889         // translet.
 890         if (_useClasspath) {
 891             String transletName = getTransletBaseName(source);
 892 
 893             if (_packageName != null)
 894                 transletName = _packageName + "." + transletName;
 895 
 896             try {
 897                 final Class clazz = ObjectFactory.findProviderClass(transletName, true);
 898                 resetTransientAttributes();
 899 
 900                 return new TemplatesImpl(new Class[]{clazz}, transletName, null, _indentNumber, this);
 901             }
 902             catch (ClassNotFoundException cnfe) {
 903                 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, transletName);
 904                 throw new TransformerConfigurationException(err.toString());
 905             }
 906             catch (Exception e) {
 907                 ErrorMsg err = new ErrorMsg(
 908                                      new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)
 909                                      + e.getMessage());
 910                 throw new TransformerConfigurationException(err.toString());
 911             }
 912         }
 913 
 914         // If _autoTranslet is true, we will try to load the bytecodes
 915         // from the translet classes without compiling the stylesheet.
 916         if (_autoTranslet)  {
 917             byte[][] bytecodes;
 918             String transletClassName = getTransletBaseName(source);
 919 
 920             if (_packageName != null)
 921                transletClassName = _packageName + "." + transletClassName;
 922 
 923             if (_jarFileName != null)
 924                 bytecodes = getBytecodesFromJar(source, transletClassName);
 925             else
 926                 bytecodes = getBytecodesFromClasses(source, transletClassName);
 927 
 928             if (bytecodes != null) {
 929                 if (_debug) {
 930                     if (_jarFileName != null)
 931                         System.err.println(new ErrorMsg(
 932                             ErrorMsg.TRANSFORM_WITH_JAR_STR, transletClassName, _jarFileName));
 933                     else
 934                         System.err.println(new ErrorMsg(
 935                             ErrorMsg.TRANSFORM_WITH_TRANSLET_STR, transletClassName));
 936                 }
 937 
 938                 // Reset the per-session attributes to their default values
 939                 // after each newTemplates() call.
 940                 resetTransientAttributes();
 941                 return new TemplatesImpl(bytecodes, transletClassName, null, _indentNumber, this);
 942             }
 943         }
 944 
 945         // Create and initialize a stylesheet compiler
 946         final XSLTC xsltc = new XSLTC(_useServicesMechanism, _xmlFeatures);
 947         if (_debug) xsltc.setDebug(true);
 948         if (_enableInlining)
 949                 xsltc.setTemplateInlining(true);
 950         else
 951                 xsltc.setTemplateInlining(false);
 952 
 953         if (!_isNotSecureProcessing) xsltc.setSecureProcessing(true);
 954         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet);
 955         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
 956         xsltc.setProperty(XalanConstants.SECURITY_MANAGER, _xmlSecurityManager);
 957         xsltc.setProperty(XalanConstants.JDK_EXTENSION_CLASSLOADER, _extensionClassLoader);
 958 
 959         // set Catalog features
 960         buildCatalogFeatures();
 961         xsltc.setProperty(JdkXmlFeatures.CATALOG_FEATURES, _catalogFeatures);
 962 
 963         xsltc.init();
 964         if (!_isNotSecureProcessing)
 965             _xsltcExtensionFunctions = xsltc.getExternalExtensionFunctions();
 966         // Set a document loader (for xsl:include/import) if defined
 967         if (_uriResolver != null || (_xmlFeatures.getFeature(JdkXmlFeatures.XmlFeature.USE_CATALOG) && _catalogFiles != null)) {
 968             xsltc.setSourceLoader(this);
 969         }
 970 
 971         // Pass parameters to the Parser to make sure it locates the correct
 972         // <?xml-stylesheet ...?> PI in an XML input document
 973         if ((_piParams != null) && (_piParams.get(source) != null)) {
 974             // Get the parameters for this Source object
 975             PIParamWrapper p = _piParams.get(source);
 976             // Pass them on to the compiler (which will pass then to the parser)
 977             if (p != null) {
 978                 xsltc.setPIParameters(p._media, p._title, p._charset);
 979             }
 980         }
 981 
 982         // Set the attributes for translet generation
 983         int outputType = XSLTC.BYTEARRAY_OUTPUT;
 984         if (_generateTranslet || _autoTranslet) {
 985             // Set the translet name
 986             xsltc.setClassName(getTransletBaseName(source));
 987 
 988             if (_destinationDirectory != null)
 989                 xsltc.setDestDirectory(_destinationDirectory);
 990             else {
 991                 String xslName = getStylesheetFileName(source);
 992                 if (xslName != null) {
 993                     File xslFile = new File(xslName);
 994                     String xslDir = xslFile.getParent();
 995 
 996                     if (xslDir != null)
 997                         xsltc.setDestDirectory(xslDir);
 998                 }
 999             }
1000 
1001             if (_packageName != null)
1002                 xsltc.setPackageName(_packageName);
1003 
1004             if (_jarFileName != null) {
1005                 xsltc.setJarFileName(_jarFileName);
1006                 outputType = XSLTC.BYTEARRAY_AND_JAR_OUTPUT;
1007             }
1008             else
1009                 outputType = XSLTC.BYTEARRAY_AND_FILE_OUTPUT;
1010         }
1011 
1012         // Compile the stylesheet
1013         final InputSource input = Util.getInputSource(xsltc, source);
1014         byte[][] bytecodes = xsltc.compile(null, input, outputType);
1015         final String transletName = xsltc.getClassName();
1016 
1017         // Output to the jar file if the jar file name is set.
1018         if ((_generateTranslet || _autoTranslet)
1019                 && bytecodes != null && _jarFileName != null) {
1020             try {
1021                 xsltc.outputToJar();
1022             }
1023             catch (java.io.IOException e) { }
1024         }
1025 
1026         // Reset the per-session attributes to their default values
1027         // after each newTemplates() call.
1028         resetTransientAttributes();
1029 
1030         // Pass compiler warnings to the error listener
1031         if (_errorListener != this) {
1032             try {
1033                 passWarningsToListener(xsltc.getWarnings());
1034             }
1035             catch (TransformerException e) {
1036                 throw new TransformerConfigurationException(e);
1037             }
1038         }
1039         else {
1040             xsltc.printWarnings();
1041         }
1042 
1043         // Check that the transformation went well before returning
1044         if (bytecodes == null) {
1045             ArrayList<ErrorMsg> errs = xsltc.getErrors();
1046             ErrorMsg err;
1047             if (errs != null) {
1048                 err = errs.get(errs.size()-1);
1049             } else {
1050                 err = new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR);
1051             }
1052             Throwable cause = err.getCause();
1053             TransformerConfigurationException exc;
1054             if (cause != null) {
1055                 exc =  new TransformerConfigurationException(cause.getMessage(), cause);
1056             } else {
1057                 exc =  new TransformerConfigurationException(err.toString());
1058             }
1059 
1060             // Pass compiler errors to the error listener
1061             if (_errorListener != null) {
1062                 passErrorsToListener(xsltc.getErrors());
1063 
1064                 // As required by TCK 1.2, send a fatalError to the
1065                 // error listener because compilation of the stylesheet
1066                 // failed and no further processing will be possible.
1067                 try {
1068                     _errorListener.fatalError(exc);
1069                 } catch (TransformerException te) {
1070                     // well, we tried.
1071                 }
1072             }
1073             else {
1074                 xsltc.printErrors();
1075             }
1076             throw exc;
1077         }
1078 
1079         TemplatesImpl templates = new TemplatesImpl(bytecodes, transletName,
1080                 xsltc.getOutputProperties(), _indentNumber, this);
1081         if (_uriResolver != null) {
1082             templates.setURIResolver(_uriResolver);
1083         }
1084         return templates;
1085     }
1086 
1087     /**
1088      * javax.xml.transform.sax.SAXTransformerFactory implementation.
1089      * Get a TemplatesHandler object that can process SAX ContentHandler
1090      * events into a Templates object.
1091      *
1092      * @return A TemplatesHandler object that can handle SAX events
1093      * @throws TransformerConfigurationException
1094      */
1095     @Override
1096     public TemplatesHandler newTemplatesHandler()
1097         throws TransformerConfigurationException
1098     {
1099         // create CatalogFeatures that is accessible by the Handler
1100         // through the factory instance
1101         buildCatalogFeatures();
1102         final TemplatesHandlerImpl handler =
1103             new TemplatesHandlerImpl(_indentNumber, this);
1104         if (_uriResolver != null) {
1105             handler.setURIResolver(_uriResolver);
1106         }
1107         return handler;
1108     }
1109 
1110     /**
1111      * javax.xml.transform.sax.SAXTransformerFactory implementation.
1112      * Get a TransformerHandler object that can process SAX ContentHandler
1113      * events into a Result. This method will return a pure copy transformer.
1114      *
1115      * @return A TransformerHandler object that can handle SAX events
1116      * @throws TransformerConfigurationException
1117      */
1118     @Override
1119     public TransformerHandler newTransformerHandler()
1120         throws TransformerConfigurationException
1121     {
1122         final Transformer transformer = newTransformer();
1123         if (_uriResolver != null) {
1124             transformer.setURIResolver(_uriResolver);
1125         }
1126         return new TransformerHandlerImpl((TransformerImpl) transformer);
1127     }
1128 
1129     /**
1130      * javax.xml.transform.sax.SAXTransformerFactory implementation.
1131      * Get a TransformerHandler object that can process SAX ContentHandler
1132      * events into a Result, based on the transformation instructions
1133      * specified by the argument.
1134      *
1135      * @param src The source of the transformation instructions.
1136      * @return A TransformerHandler object that can handle SAX events
1137      * @throws TransformerConfigurationException
1138      */
1139     @Override
1140     public TransformerHandler newTransformerHandler(Source src)
1141         throws TransformerConfigurationException
1142     {
1143         final Transformer transformer = newTransformer(src);
1144         if (_uriResolver != null) {
1145             transformer.setURIResolver(_uriResolver);
1146         }
1147         return new TransformerHandlerImpl((TransformerImpl) transformer);
1148     }
1149 
1150     /**
1151      * javax.xml.transform.sax.SAXTransformerFactory implementation.
1152      * Get a TransformerHandler object that can process SAX ContentHandler
1153      * events into a Result, based on the transformation instructions
1154      * specified by the argument.
1155      *
1156      * @param templates Represents a pre-processed stylesheet
1157      * @return A TransformerHandler object that can handle SAX events
1158      * @throws TransformerConfigurationException
1159      */
1160     @Override
1161     public TransformerHandler newTransformerHandler(Templates templates)
1162         throws TransformerConfigurationException
1163     {
1164         final Transformer transformer = templates.newTransformer();
1165         final TransformerImpl internal = (TransformerImpl)transformer;
1166         return new TransformerHandlerImpl(internal);
1167     }
1168 
1169     /**
1170      * javax.xml.transform.sax.SAXTransformerFactory implementation.
1171      * Create an XMLFilter that uses the given source as the
1172      * transformation instructions.
1173      *
1174      * @param src The source of the transformation instructions.
1175      * @return An XMLFilter object, or null if this feature is not supported.
1176      * @throws TransformerConfigurationException
1177      */
1178     @Override
1179     public XMLFilter newXMLFilter(Source src)
1180         throws TransformerConfigurationException
1181     {
1182         Templates templates = newTemplates(src);
1183         if (templates == null) return null;
1184         return newXMLFilter(templates);
1185     }
1186 
1187     /**
1188      * javax.xml.transform.sax.SAXTransformerFactory implementation.
1189      * Create an XMLFilter that uses the given source as the
1190      * transformation instructions.
1191      *
1192      * @param templates The source of the transformation instructions.
1193      * @return An XMLFilter object, or null if this feature is not supported.
1194      * @throws TransformerConfigurationException
1195      */
1196     @Override
1197     public XMLFilter newXMLFilter(Templates templates)
1198         throws TransformerConfigurationException
1199     {
1200         try {
1201             return new com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter(templates);
1202         }
1203         catch (TransformerConfigurationException e1) {
1204             if (_errorListener != null) {
1205                 try {
1206                     _errorListener.fatalError(e1);
1207                     return null;
1208                 }
1209                 catch (TransformerException e2) {
1210                     new TransformerConfigurationException(e2);
1211                 }
1212             }
1213             throw e1;
1214         }
1215     }
1216 
1217     /**
1218      * Receive notification of a recoverable error.
1219      * The transformer must continue to provide normal parsing events after
1220      * invoking this method. It should still be possible for the application
1221      * to process the document through to the end.
1222      *
1223      * @param e The warning information encapsulated in a transformer
1224      * exception.
1225      * @throws TransformerException if the application chooses to discontinue
1226      * the transformation (always does in our case).
1227      */
1228     @Override
1229     public void error(TransformerException e)
1230         throws TransformerException
1231     {
1232         Throwable wrapped = e.getException();
1233         if (wrapped != null) {
1234             System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG,
1235                                             e.getMessageAndLocation(),
1236                                             wrapped.getMessage()));
1237         } else {
1238             System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG,
1239                                             e.getMessageAndLocation()));
1240         }
1241         throw e;
1242     }
1243 
1244     /**
1245      * Receive notification of a non-recoverable error.
1246      * The application must assume that the transformation cannot continue
1247      * after the Transformer has invoked this method, and should continue
1248      * (if at all) only to collect addition error messages. In fact,
1249      * Transformers are free to stop reporting events once this method has
1250      * been invoked.
1251      *
1252      * @param e warning information encapsulated in a transformer
1253      * exception.
1254      * @throws TransformerException if the application chooses to discontinue
1255      * the transformation (always does in our case).
1256      */
1257     @Override
1258     public void fatalError(TransformerException e)
1259         throws TransformerException
1260     {
1261         Throwable wrapped = e.getException();
1262         if (wrapped != null) {
1263             System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG,
1264                                             e.getMessageAndLocation(),
1265                                             wrapped.getMessage()));
1266         } else {
1267             System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG,
1268                                             e.getMessageAndLocation()));
1269         }
1270         throw e;
1271     }
1272 
1273     /**
1274      * Receive notification of a warning.
1275      * Transformers can use this method to report conditions that are not
1276      * errors or fatal errors. The default behaviour is to take no action.
1277      * After invoking this method, the Transformer must continue with the
1278      * transformation. It should still be possible for the application to
1279      * process the document through to the end.
1280      *
1281      * @param e The warning information encapsulated in a transformer
1282      * exception.
1283      * @throws TransformerException if the application chooses to discontinue
1284      * the transformation (never does in our case).
1285      */
1286     @Override
1287     public void warning(TransformerException e)
1288         throws TransformerException
1289     {
1290         Throwable wrapped = e.getException();
1291         if (wrapped != null) {
1292             System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG,
1293                                             e.getMessageAndLocation(),
1294                                             wrapped.getMessage()));
1295         } else {
1296             System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG,
1297                                             e.getMessageAndLocation()));
1298         }
1299     }
1300 
1301     /**
1302      * This method implements XSLTC's SourceLoader interface. It is used to
1303      * glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes.
1304      *
1305      * @param href The URI of the document to load
1306      * @param context The URI of the currently loaded document
1307      * @param xsltc The compiler that resuests the document
1308      * @return An InputSource with the loaded document
1309      */
1310     @Override
1311     public InputSource loadSource(String href, String context, XSLTC xsltc) {
1312         try {
1313             Source source = null;
1314             if (_uriResolver != null) {
1315                 source = _uriResolver.resolve(href, context);
1316             }
1317             if (source == null && _catalogFiles != null &&
1318                     _xmlFeatures.getFeature(JdkXmlFeatures.XmlFeature.USE_CATALOG)) {
1319                 if (_catalogUriResolver == null) {
1320                     _catalogUriResolver = CatalogManager.catalogUriResolver(_catalogFeatures);
1321                 }
1322                 source = _catalogUriResolver.resolve(href, context);
1323             }
1324             if (source != null) {
1325                 return Util.getInputSource(xsltc, source);
1326             }
1327         }
1328         catch (TransformerException e) {
1329             // should catch it when the resolver explicitly throws the exception
1330             final ErrorMsg msg = new ErrorMsg(ErrorMsg.INVALID_URI_ERR, href + "\n" + e.getMessage(), this);
1331             xsltc.getParser().reportError(Constants.FATAL, msg);
1332         }
1333 
1334         return null;
1335     }
1336 
1337     /**
1338      * Build the CatalogFeatures object when a newTemplates or newTransformer is
1339      * created. This will read any System Properties for the CatalogFeatures that
1340      * may have been set.
1341      */
1342     private CatalogFeatures buildCatalogFeatures() {
1343         // build will cause the CatalogFeatures to read SPs for those not set through the API
1344         if (_catalogFeatures == null) {
1345             _catalogFeatures = cfBuilder.build();
1346         }
1347 
1348         // update fields
1349         _catalogFiles = _catalogFeatures.get(Feature.FILES);
1350         _catalogDefer = _catalogFeatures.get(Feature.DEFER);
1351         _catalogPrefer = _catalogFeatures.get(Feature.PREFER);
1352         _catalogResolve = _catalogFeatures.get(Feature.RESOLVE);
1353 
1354         return _catalogFeatures;
1355     }
1356 
1357     /**
1358      * Reset the per-session attributes to their default values
1359      */
1360     private void resetTransientAttributes() {
1361         _transletName = DEFAULT_TRANSLET_NAME;
1362         _destinationDirectory = null;
1363         _packageName = DEFAULT_TRANSLATE_PACKAGE;
1364         _jarFileName = null;
1365     }
1366 
1367     /**
1368      * Load the translet classes from local .class files and return
1369      * the bytecode array.
1370      *
1371      * @param source The xsl source
1372      * @param fullClassName The full name of the translet
1373      * @return The bytecode array
1374      */
1375     private byte[][] getBytecodesFromClasses(Source source, String fullClassName)
1376     {
1377         if (fullClassName == null)
1378             return null;
1379 
1380         String xslFileName = getStylesheetFileName(source);
1381         File xslFile = null;
1382         if (xslFileName != null)
1383             xslFile = new File(xslFileName);
1384 
1385         // Find the base name of the translet
1386         final String transletName;
1387         int lastDotIndex = fullClassName.lastIndexOf('.');
1388         if (lastDotIndex > 0)
1389             transletName = fullClassName.substring(lastDotIndex+1);
1390         else
1391             transletName = fullClassName;
1392 
1393         // Construct the path name for the translet class file
1394         String transletPath = fullClassName.replace('.', '/');
1395         if (_destinationDirectory != null) {
1396             transletPath = _destinationDirectory + "/" + transletPath + ".class";
1397         }
1398         else {
1399             if (xslFile != null && xslFile.getParent() != null)
1400                 transletPath = xslFile.getParent() + "/" + transletPath + ".class";
1401             else
1402                 transletPath = transletPath + ".class";
1403         }
1404 
1405         // Return null if the translet class file does not exist.
1406         File transletFile = new File(transletPath);
1407         if (!transletFile.exists())
1408             return null;
1409 
1410         // Compare the timestamps of the translet and the xsl file.
1411         // If the translet is older than the xsl file, return null
1412         // so that the xsl file is used for the transformation and
1413         // the translet is regenerated.
1414         if (xslFile != null && xslFile.exists()) {
1415             long xslTimestamp = xslFile.lastModified();
1416             long transletTimestamp = transletFile.lastModified();
1417             if (transletTimestamp < xslTimestamp)
1418                 return null;
1419         }
1420 
1421         // Load the translet into a bytecode array.
1422         Vector bytecodes = new Vector();
1423         int fileLength = (int)transletFile.length();
1424         if (fileLength > 0) {
1425             FileInputStream input;
1426             try {
1427                 input = new FileInputStream(transletFile);
1428             }
1429             catch (FileNotFoundException e) {
1430                 return null;
1431             }
1432 
1433             byte[] bytes = new byte[fileLength];
1434             try {
1435                 readFromInputStream(bytes, input, fileLength);
1436                 input.close();
1437             }
1438             catch (IOException e) {
1439                 return null;
1440             }
1441 
1442             bytecodes.addElement(bytes);
1443         }
1444         else
1445             return null;
1446 
1447         // Find the parent directory of the translet.
1448         String transletParentDir = transletFile.getParent();
1449         if (transletParentDir == null)
1450             transletParentDir = SecuritySupport.getSystemProperty("user.dir");
1451 
1452         File transletParentFile = new File(transletParentDir);
1453 
1454         // Find all the auxiliary files which have a name pattern of "transletClass$nnn.class".
1455         final String transletAuxPrefix = transletName + "$";
1456         File[] auxfiles = transletParentFile.listFiles(new FilenameFilter() {
1457                 @Override
1458                 public boolean accept(File dir, String name)
1459                 {
1460                     return (name.endsWith(".class") && name.startsWith(transletAuxPrefix));
1461                 }
1462               });
1463 
1464         // Load the auxiliary class files and add them to the bytecode array.
1465         for (int i = 0; i < auxfiles.length; i++)
1466         {
1467             File auxfile = auxfiles[i];
1468             int auxlength = (int)auxfile.length();
1469             if (auxlength > 0) {
1470                 FileInputStream auxinput = null;
1471                 try {
1472                     auxinput = new FileInputStream(auxfile);
1473                 }
1474                 catch (FileNotFoundException e) {
1475                     continue;
1476                 }
1477 
1478                 byte[] bytes = new byte[auxlength];
1479 
1480                 try {
1481                     readFromInputStream(bytes, auxinput, auxlength);
1482                     auxinput.close();
1483                 }
1484                 catch (IOException e) {
1485                     continue;
1486                 }
1487 
1488                 bytecodes.addElement(bytes);
1489             }
1490         }
1491 
1492         // Convert the Vector of byte[] to byte[][].
1493         final int count = bytecodes.size();
1494         if ( count > 0) {
1495             final byte[][] result = new byte[count][1];
1496             for (int i = 0; i < count; i++) {
1497                 result[i] = (byte[])bytecodes.elementAt(i);
1498             }
1499 
1500             return result;
1501         }
1502         else
1503             return null;
1504     }
1505 
1506     /**
1507      * Load the translet classes from the jar file and return the bytecode.
1508      *
1509      * @param source The xsl source
1510      * @param fullClassName The full name of the translet
1511      * @return The bytecode array
1512      */
1513     private byte[][] getBytecodesFromJar(Source source, String fullClassName)
1514     {
1515         String xslFileName = getStylesheetFileName(source);
1516         File xslFile = null;
1517         if (xslFileName != null)
1518             xslFile = new File(xslFileName);
1519 
1520         // Construct the path for the jar file
1521         String jarPath;
1522         if (_destinationDirectory != null)
1523             jarPath = _destinationDirectory + "/" + _jarFileName;
1524         else {
1525             if (xslFile != null && xslFile.getParent() != null)
1526                 jarPath = xslFile.getParent() + "/" + _jarFileName;
1527             else
1528                 jarPath = _jarFileName;
1529         }
1530 
1531         // Return null if the jar file does not exist.
1532         File file = new File(jarPath);
1533         if (!file.exists())
1534             return null;
1535 
1536         // Compare the timestamps of the jar file and the xsl file. Return null
1537         // if the xsl file is newer than the jar file.
1538         if (xslFile != null && xslFile.exists()) {
1539             long xslTimestamp = xslFile.lastModified();
1540             long transletTimestamp = file.lastModified();
1541             if (transletTimestamp < xslTimestamp)
1542                 return null;
1543         }
1544 
1545         // Create a ZipFile object for the jar file
1546         ZipFile jarFile;
1547         try {
1548             jarFile = new ZipFile(file);
1549         }
1550         catch (IOException e) {
1551             return null;
1552         }
1553 
1554         String transletPath = fullClassName.replace('.', '/');
1555         String transletAuxPrefix = transletPath + "$";
1556         String transletFullName = transletPath + ".class";
1557 
1558         Vector bytecodes = new Vector();
1559 
1560         // Iterate through all entries in the jar file to find the
1561         // translet and auxiliary classes.
1562         Enumeration entries = jarFile.entries();
1563         while (entries.hasMoreElements())
1564         {
1565             ZipEntry entry = (ZipEntry)entries.nextElement();
1566             String entryName = entry.getName();
1567             if (entry.getSize() > 0 &&
1568                   (entryName.equals(transletFullName) ||
1569                   (entryName.endsWith(".class") &&
1570                       entryName.startsWith(transletAuxPrefix))))
1571             {
1572                 try {
1573                     InputStream input = jarFile.getInputStream(entry);
1574                     int size = (int)entry.getSize();
1575                     byte[] bytes = new byte[size];
1576                     readFromInputStream(bytes, input, size);
1577                     input.close();
1578                     bytecodes.addElement(bytes);
1579                 }
1580                 catch (IOException e) {
1581                     return null;
1582                 }
1583             }
1584         }
1585 
1586         // Convert the Vector of byte[] to byte[][].
1587         final int count = bytecodes.size();
1588         if (count > 0) {
1589             final byte[][] result = new byte[count][1];
1590             for (int i = 0; i < count; i++) {
1591                 result[i] = (byte[])bytecodes.elementAt(i);
1592             }
1593 
1594             return result;
1595         }
1596         else
1597             return null;
1598     }
1599 
1600     /**
1601      * Read a given number of bytes from the InputStream into a byte array.
1602      *
1603      * @param bytes The byte array to store the input content.
1604      * @param input The input stream.
1605      * @param size The number of bytes to read.
1606      */
1607     private void readFromInputStream(byte[] bytes, InputStream input, int size)
1608         throws IOException
1609     {
1610       int n = 0;
1611       int offset = 0;
1612       int length = size;
1613       while (length > 0 && (n = input.read(bytes, offset, length)) > 0) {
1614           offset = offset + n;
1615           length = length - n;
1616       }
1617     }
1618 
1619     /**
1620      * Return the base class name of the translet.
1621      * The translet name is resolved using the following rules:
1622      * 1. if the _transletName attribute is set and its value is not "GregorSamsa",
1623      *    then _transletName is returned.
1624      * 2. otherwise get the translet name from the base name of the system ID
1625      * 3. return "GregorSamsa" if the result from step 2 is null.
1626      *
1627      * @param source The input Source
1628      * @return The name of the translet class
1629      */
1630     private String getTransletBaseName(Source source)
1631     {
1632         String transletBaseName = null;
1633         if (!_transletName.equals(DEFAULT_TRANSLET_NAME))
1634             return _transletName;
1635         else {
1636             String systemId = source.getSystemId();
1637             if (systemId != null) {
1638                 String baseName = Util.baseName(systemId);
1639                 if (baseName != null) {
1640                     baseName = Util.noExtName(baseName);
1641                     transletBaseName = Util.toJavaName(baseName);
1642                 }
1643             }
1644         }
1645 
1646         return (transletBaseName != null) ? transletBaseName : DEFAULT_TRANSLET_NAME;
1647     }
1648 
1649     /**
1650      *  Return the local file name from the systemId of the Source object
1651      *
1652      * @param source The Source
1653      * @return The file name in the local filesystem, or null if the
1654      * systemId does not represent a local file.
1655      */
1656     private String getStylesheetFileName(Source source)
1657     {
1658         String systemId = source.getSystemId();
1659         if (systemId != null) {
1660             File file = new File(systemId);
1661             if (file.exists())
1662                 return systemId;
1663             else {
1664                 URL url;
1665                 try {
1666                     url = new URL(systemId);
1667                 }
1668                 catch (MalformedURLException e) {
1669                     return null;
1670                 }
1671 
1672                 if ("file".equals(url.getProtocol()))
1673                     return url.getFile();
1674                 else
1675                     return null;
1676             }
1677         }
1678         else
1679             return null;
1680     }
1681 
1682     /**
1683      * Returns a new instance of the XSLTC DTM Manager service.
1684      */
1685     protected final XSLTCDTMManager createNewDTMManagerInstance() {
1686         return XSLTCDTMManager.createNewDTMManagerInstance();
1687     }
1688 }