< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java

Print this page
rev 1063 : 8172974: [JAXP] XALAN: Wrong result when transforming namespace unaware StAX Input
   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 


  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.CatalogException;
  55 import javax.xml.catalog.CatalogFeatures;
  56 import javax.xml.catalog.CatalogFeatures.Feature;
  57 import javax.xml.catalog.CatalogManager;
  58 import javax.xml.catalog.CatalogResolver;
  59 import javax.xml.parsers.SAXParser;
  60 import javax.xml.parsers.SAXParserFactory;
  61 import javax.xml.transform.ErrorListener;
  62 import javax.xml.transform.Source;
  63 import javax.xml.transform.Templates;
  64 import javax.xml.transform.Transformer;
  65 import javax.xml.transform.TransformerConfigurationException;
  66 import javax.xml.transform.TransformerException;
  67 import javax.xml.transform.TransformerFactory;
  68 import javax.xml.transform.URIResolver;
  69 import javax.xml.transform.dom.DOMResult;
  70 import javax.xml.transform.dom.DOMSource;


 133      */
 134     private String _transletName = DEFAULT_TRANSLET_NAME;
 135 
 136     /**
 137      * The destination directory for the translet
 138      */
 139     private String _destinationDirectory = null;
 140 
 141     /**
 142      * The package name prefix for all generated translet classes
 143      */
 144     private static final String DEFAULT_TRANSLATE_PACKAGE = "die.verwandlung";
 145     private String _packageName = DEFAULT_TRANSLATE_PACKAGE;
 146 
 147     /**
 148      * The jar file name which the translet classes are packaged into
 149      */
 150     private String _jarFileName = null;
 151 
 152     /**
 153      * This Map is used to store parameters for locating
 154      * <?xml-stylesheet ...?> processing instructions in XML docs.
 155      */
 156     private Map<Source, PIParamWrapper> _piParams = null;
 157 
 158     /**
 159      * The above Map stores objects of this class.
 160      */
 161     private static class PIParamWrapper {
 162         public String _media = null;
 163         public String _title = null;
 164         public String _charset = null;
 165 
 166         public PIParamWrapper(String media, String title, String charset) {
 167             _media = media;
 168             _title = title;
 169             _charset = charset;
 170         }
 171     }
 172 
 173     /**
 174      * Set to <code>true</code> when debugging is enabled.
 175      */
 176     private boolean _debug = false;
 177 
 178     /**
 179      * Set to <code>true</code> when templates are inlined.
 180      */
 181     private boolean _enableInlining = false;
 182 
 183     /**
 184      * Set to <code>true</code> when we want to generate
 185      * translet classes from the stylesheet.
 186      */
 187     private boolean _generateTranslet = false;
 188 
 189     /**
 190      * If this is set to <code>true</code>, we attempt to use translet classes
 191      * for transformation if possible without compiling the stylesheet. The
 192      * translet class is only used if its timestamp is newer than the timestamp
 193      * of the stylesheet.
 194      */
 195     private boolean _autoTranslet = false;
 196 
 197     /**
 198      * If this is set to <code>true</code>, we attempt to load the translet
 199      * from the CLASSPATH.
 200      */
 201     private boolean _useClasspath = false;
 202 
 203     /**
 204      * Number of indent spaces when indentation is turned on.
 205      */
 206     private int _indentNumber = -1;
 207 
 208     /**
 209      * <p>State of secure processing feature.</p>
 210      */
 211     private boolean _isNotSecureProcessing = true;

 212     /**
 213      * <p>State of secure mode.</p>
 214      */
 215     private boolean _isSecureMode = false;
 216 
 217     /**
 218      * Indicates whether implementation parts should use
 219      *   service loader (or similar).
 220      * Note the default value (false) is the safe option..
 221      */
 222     private boolean _useServicesMechanism;
 223 
 224     /**
 225      * protocols allowed for external references set by the stylesheet
 226      * processing instruction, Import and Include element.
 227      */
 228     private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
 229      /**

 230      * protocols allowed for external DTD references in source file and/or stylesheet.
 231      */
 232     private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
 233 
 234     private XMLSecurityPropertyManager _xmlSecurityPropertyMgr;
 235     private XMLSecurityManager _xmlSecurityManager;
 236 
 237     private final JdkXmlFeatures _xmlFeatures;
 238 
 239     private ClassLoader _extensionClassLoader = null;
 240 
 241     // Unmodifiable view of external extension function from xslt compiler
 242     // It will be populated by user-specified extension functions during the
 243     // type checking
 244     private Map<String, Class<?>> _xsltcExtensionFunctions;
 245 
 246     CatalogResolver _catalogUriResolver;
 247     CatalogFeatures _catalogFeatures;
 248     CatalogFeatures.Builder cfBuilder = CatalogFeatures.builder();
 249     // Catalog features


 549      * It is possible for an <code>TransformerFactory</code> to expose a feature value but be unable to change its state.
 550      * </p>
 551      *
 552      * <p>See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.</p>
 553      *
 554      * @param name Feature name.
 555      * @param value Is feature state <code>true</code> or <code>false</code>.
 556      *
 557      * @throws TransformerConfigurationException if this <code>TransformerFactory</code>
 558      *   or the <code>Transformer</code>s or <code>Template</code>s it creates cannot support this feature.
 559      * @throws NullPointerException If the <code>name</code> parameter is null.
 560      */
 561     @Override
 562     public void setFeature(String name, boolean value)
 563         throws TransformerConfigurationException {
 564 
 565         // feature name cannot be null
 566         if (name == null) {
 567             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_FEATURE_NULL_NAME);
 568             throw new NullPointerException(err.toString());
 569         }
 570         // secure processing?
 571         else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 572             if ((_isSecureMode) && (!value)) {
 573                 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SECUREPROCESSING_FEATURE);
 574                 throw new TransformerConfigurationException(err.toString());
 575             }
 576             _isNotSecureProcessing = !value;
 577             _xmlSecurityManager.setSecureProcessing(value);
 578 
 579             // set external access restriction when FSP is explicitly set
 580             if (value) {
 581                 _xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_DTD,
 582                         FeaturePropertyBase.State.FSP, XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
 583                 _xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_STYLESHEET,
 584                         FeaturePropertyBase.State.FSP, XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
 585                 _accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
 586                         Property.ACCESS_EXTERNAL_DTD);
 587                 _accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(
 588                         Property.ACCESS_EXTERNAL_STYLESHEET);
 589             }
 590 
 591             if (value && _xmlFeatures != null) {
 592                 _xmlFeatures.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION,
 593                         JdkXmlFeatures.State.FSP, false);
 594             }
 595         }
 596         else if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) {
 597             //in secure mode, let _useServicesMechanism be determined by the constructor
 598             if (!_isSecureMode)
 599                 _useServicesMechanism = value;
 600         }
 601         else {
 602             if (_xmlFeatures != null &&
 603                     _xmlFeatures.setFeature(name, JdkXmlFeatures.State.APIPROPERTY, value)) {
 604                 return;
 605             }
 606 
 607             // unknown feature
 608             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name);
 609             throw new TransformerConfigurationException(err.toString());
 610         }
 611     }
 612 
 613     /**
 614      * javax.xml.transform.sax.TransformerFactory implementation.
 615      * Look up the value of a feature (to see if it is supported).
 616      * This method must be updated as the various methods and features of this
 617      * class are implemented.
 618      *
 619      * @param name The feature name
 620      * @return 'true' if feature is supported, 'false' if not
 621      */
 622     @Override
 623     public boolean getFeature(String name) {
 624         // All supported features should be listed here
 625         String[] features = {
 626             DOMSource.FEATURE,
 627             DOMResult.FEATURE,
 628             SAXSource.FEATURE,
 629             SAXResult.FEATURE,
 630             StAXSource.FEATURE,
 631             StAXResult.FEATURE,
 632             StreamSource.FEATURE,
 633             StreamResult.FEATURE,
 634             SAXTransformerFactory.FEATURE,
 635             SAXTransformerFactory.FEATURE_XMLFILTER,
 636             XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM
 637         };
 638 
 639         // feature name cannot be null
 640         if (name == null) {
 641             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_GET_FEATURE_NULL_NAME);
 642             throw new NullPointerException(err.toString());
 643         }
 644 
 645         // Inefficient, but array is small
 646         for (int i =0; i < features.length; i++) {
 647             if (name.equals(features[i])) {
 648                 return true;
 649             }
 650         }
 651 

 652         if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 653             return !_isNotSecureProcessing;
 654         }
 655 
 656         /** Check to see if the property is managed by the JdkXmlFeatues **/
 657         int index = _xmlFeatures.getIndex(name);
 658         if (index > -1) {
 659             return _xmlFeatures.getFeature(index);
 660         }
 661 
 662         // Feature not supported
 663         return false;
 664     }

 665     /**
 666      * Return the state of the services mechanism feature.
 667      */
 668     public boolean useServicesMechnism() {
 669         return _useServicesMechanism;
 670     }
 671 
 672      /**
 673      * @return the feature manager
 674      */
 675     public JdkXmlFeatures getJdkXmlFeatures() {
 676         return _xmlFeatures;
 677     }
 678 
 679     /**
 680      * javax.xml.transform.sax.TransformerFactory implementation.
 681      * Get the object that is used by default during the transformation to
 682      * resolve URIs used in document(), xsl:import, or xsl:include.
 683      *
 684      * @return The URLResolver used for this TransformerFactory and all
 685      * Templates and Transformer objects created using this factory
 686      */
 687     @Override
 688     public URIResolver getURIResolver() {
 689         return _uriResolver;
 690     }
 691 
 692     /**


 817 
 818     /**
 819      * javax.xml.transform.sax.TransformerFactory implementation.
 820      * Process the Source into a Templates object, which is a a compiled
 821      * representation of the source. Note that this method should not be
 822      * used with XSLTC, as the time-consuming compilation is done for each
 823      * and every transformation.
 824      *
 825      * @return A Templates object that can be used to create Transformers.
 826      * @throws TransformerConfigurationException
 827      */
 828     @Override
 829     public Transformer newTransformer(Source source) throws
 830         TransformerConfigurationException
 831     {
 832         final Templates templates = newTemplates(source);
 833         final Transformer transformer = templates.newTransformer();
 834         if (_uriResolver != null) {
 835             transformer.setURIResolver(_uriResolver);
 836         }
 837         return(transformer);
 838     }
 839 
 840     /**
 841      * Pass warning messages from the compiler to the error listener
 842      */
 843     private void passWarningsToListener(ArrayList<ErrorMsg> messages)
 844         throws TransformerException
 845     {
 846         if (_errorListener == null || messages == null) {
 847             return;
 848         }
 849         // Pass messages to listener, one by one
 850         final int count = messages.size();
 851         for (int pos = 0; pos < count; pos++) {
 852             ErrorMsg msg = messages.get(pos);
 853             // Workaround for the TCK failure ErrorListener.errorTests.error001.
 854             if (msg.isWarningError())
 855                 _errorListener.error(
 856                     new TransformerConfigurationException(msg.toString()));
 857             else


 970 
 971         if (!_isNotSecureProcessing) xsltc.setSecureProcessing(true);
 972         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet);
 973         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
 974         xsltc.setProperty(XalanConstants.SECURITY_MANAGER, _xmlSecurityManager);
 975         xsltc.setProperty(XalanConstants.JDK_EXTENSION_CLASSLOADER, _extensionClassLoader);
 976 
 977         // set Catalog features
 978         buildCatalogFeatures();
 979         xsltc.setProperty(JdkXmlFeatures.CATALOG_FEATURES, _catalogFeatures);
 980 
 981         xsltc.init();
 982         if (!_isNotSecureProcessing)
 983             _xsltcExtensionFunctions = xsltc.getExternalExtensionFunctions();
 984         // Set a document loader (for xsl:include/import) if defined
 985         if (_uriResolver != null || ( _catalogFiles != null
 986                 && _xmlFeatures.getFeature(JdkXmlFeatures.XmlFeature.USE_CATALOG))) {
 987             xsltc.setSourceLoader(this);
 988         }
 989 
 990         // Pass parameters to the Parser to make sure it locates the correct
 991         // <?xml-stylesheet ...?> PI in an XML input document
 992         if ((_piParams != null) && (_piParams.get(source) != null)) {
 993             // Get the parameters for this Source object
 994             PIParamWrapper p = _piParams.get(source);
 995             // Pass them on to the compiler (which will pass then to the parser)
 996             if (p != null) {
 997                 xsltc.setPIParameters(p._media, p._title, p._charset);
 998             }
 999         }
1000 
1001         // Set the attributes for translet generation
1002         int outputType = XSLTC.BYTEARRAY_OUTPUT;
1003         if (_generateTranslet || _autoTranslet) {
1004             // Set the translet name
1005             xsltc.setClassName(getTransletBaseName(source));
1006 
1007             if (_destinationDirectory != null)
1008                 xsltc.setDestDirectory(_destinationDirectory);
1009             else {
1010                 String xslName = getStylesheetFileName(source);
1011                 if (xslName != null) {
1012                     File xslFile = new File(xslName);
1013                     String xslDir = xslFile.getParent();
1014 
1015                     if (xslDir != null)
1016                         xsltc.setDestDirectory(xslDir);
1017                 }
1018             }
1019 
1020             if (_packageName != null)


1425                 transletPath = transletPath + ".class";
1426         }
1427 
1428         // Return null if the translet class file does not exist.
1429         File transletFile = new File(transletPath);
1430         if (!transletFile.exists())
1431             return null;
1432 
1433         // Compare the timestamps of the translet and the xsl file.
1434         // If the translet is older than the xsl file, return null
1435         // so that the xsl file is used for the transformation and
1436         // the translet is regenerated.
1437         if (xslFile != null && xslFile.exists()) {
1438             long xslTimestamp = xslFile.lastModified();
1439             long transletTimestamp = transletFile.lastModified();
1440             if (transletTimestamp < xslTimestamp)
1441                 return null;
1442         }
1443 
1444         // Load the translet into a bytecode array.
1445         Vector bytecodes = new Vector();
1446         int fileLength = (int)transletFile.length();
1447         if (fileLength > 0) {
1448             FileInputStream input;
1449             try {
1450                 input = new FileInputStream(transletFile);
1451             }
1452             catch (FileNotFoundException e) {
1453                 return null;
1454             }
1455 
1456             byte[] bytes = new byte[fileLength];
1457             try {
1458                 readFromInputStream(bytes, input, fileLength);
1459                 input.close();
1460             }
1461             catch (IOException e) {
1462                 return null;
1463             }
1464 
1465             bytecodes.addElement(bytes);
1466         }
1467         else
1468             return null;

1469 
1470         // Find the parent directory of the translet.
1471         String transletParentDir = transletFile.getParent();
1472         if (transletParentDir == null)
1473             transletParentDir = SecuritySupport.getSystemProperty("user.dir");
1474 
1475         File transletParentFile = new File(transletParentDir);
1476 
1477         // Find all the auxiliary files which have a name pattern of "transletClass$nnn.class".
1478         final String transletAuxPrefix = transletName + "$";
1479         File[] auxfiles = transletParentFile.listFiles(new FilenameFilter() {
1480                 @Override
1481                 public boolean accept(File dir, String name)
1482                 {
1483                     return (name.endsWith(".class") && name.startsWith(transletAuxPrefix));
1484                 }
1485               });
1486 
1487         // Load the auxiliary class files and add them to the bytecode array.
1488         for (int i = 0; i < auxfiles.length; i++)


1491             int auxlength = (int)auxfile.length();
1492             if (auxlength > 0) {
1493                 FileInputStream auxinput = null;
1494                 try {
1495                     auxinput = new FileInputStream(auxfile);
1496                 }
1497                 catch (FileNotFoundException e) {
1498                     continue;
1499                 }
1500 
1501                 byte[] bytes = new byte[auxlength];
1502 
1503                 try {
1504                     readFromInputStream(bytes, auxinput, auxlength);
1505                     auxinput.close();
1506                 }
1507                 catch (IOException e) {
1508                     continue;
1509                 }
1510 
1511                 bytecodes.addElement(bytes);
1512             }
1513         }
1514 
1515         // Convert the Vector of byte[] to byte[][].
1516         final int count = bytecodes.size();
1517         if ( count > 0) {
1518             final byte[][] result = new byte[count][1];
1519             for (int i = 0; i < count; i++) {
1520                 result[i] = (byte[])bytecodes.elementAt(i);
1521             }
1522 
1523             return result;
1524         }
1525         else
1526             return null;
1527     }
1528 
1529     /**
1530      * Load the translet classes from the jar file and return the bytecode.
1531      *
1532      * @param source The xsl source
1533      * @param fullClassName The full name of the translet
1534      * @return The bytecode array
1535      */
1536     private byte[][] getBytecodesFromJar(Source source, String fullClassName)
1537     {
1538         String xslFileName = getStylesheetFileName(source);
1539         File xslFile = null;
1540         if (xslFileName != null)


1549                 jarPath = xslFile.getParent() + "/" + _jarFileName;
1550             else
1551                 jarPath = _jarFileName;
1552         }
1553 
1554         // Return null if the jar file does not exist.
1555         File file = new File(jarPath);
1556         if (!file.exists())
1557             return null;
1558 
1559         // Compare the timestamps of the jar file and the xsl file. Return null
1560         // if the xsl file is newer than the jar file.
1561         if (xslFile != null && xslFile.exists()) {
1562             long xslTimestamp = xslFile.lastModified();
1563             long transletTimestamp = file.lastModified();
1564             if (transletTimestamp < xslTimestamp)
1565                 return null;
1566         }
1567 
1568         // Create a ZipFile object for the jar file
1569         ZipFile jarFile;
1570         try {
1571             jarFile = new ZipFile(file);
1572         }
1573         catch (IOException e) {
1574             return null;
1575         }
1576 
1577         String transletPath = fullClassName.replace('.', '/');
1578         String transletAuxPrefix = transletPath + "$";
1579         String transletFullName = transletPath + ".class";
1580 
1581         Vector bytecodes = new Vector();
1582 
1583         // Iterate through all entries in the jar file to find the
1584         // translet and auxiliary classes.
1585         Enumeration entries = jarFile.entries();
1586         while (entries.hasMoreElements())
1587         {
1588             ZipEntry entry = (ZipEntry)entries.nextElement();
1589             String entryName = entry.getName();
1590             if (entry.getSize() > 0 &&
1591                   (entryName.equals(transletFullName) ||
1592                   (entryName.endsWith(".class") &&
1593                       entryName.startsWith(transletAuxPrefix))))
1594             {
1595                 try {
1596                     InputStream input = jarFile.getInputStream(entry);
1597                     int size = (int)entry.getSize();
1598                     byte[] bytes = new byte[size];
1599                     readFromInputStream(bytes, input, size);
1600                     input.close();
1601                     bytecodes.addElement(bytes);
1602                 }
1603                 catch (IOException e) {
1604                     return null;
1605                 }
1606             }
1607         }
1608 
1609         // Convert the Vector of byte[] to byte[][].
1610         final int count = bytecodes.size();
1611         if (count > 0) {
1612             final byte[][] result = new byte[count][1];
1613             for (int i = 0; i < count; i++) {
1614                 result[i] = (byte[])bytecodes.elementAt(i);




1615             }
1616 
1617             return result;
1618         }
1619         else
1620             return null;

1621     }
1622 
1623     /**
1624      * Read a given number of bytes from the InputStream into a byte array.
1625      *
1626      * @param bytes The byte array to store the input content.
1627      * @param input The input stream.
1628      * @param size The number of bytes to read.
1629      */
1630     private void readFromInputStream(byte[] bytes, InputStream input, int size)
1631         throws IOException
1632     {
1633       int n = 0;
1634       int offset = 0;
1635       int length = size;
1636       while (length > 0 && (n = input.read(bytes, offset, length)) > 0) {
1637           offset = offset + n;
1638           length = length - n;
1639       }
1640     }
1641 
1642     /**
1643      * Return the base class name of the translet.
1644      * The translet name is resolved using the following rules:
1645      * 1. if the _transletName attribute is set and its value is not "GregorSamsa",
1646      *    then _transletName is returned.
1647      * 2. otherwise get the translet name from the base name of the system ID
1648      * 3. return "GregorSamsa" if the result from step 2 is null.
1649      *
1650      * @param source The input Source
1651      * @return The name of the translet class
1652      */
1653     private String getTransletBaseName(Source source)
1654     {
1655         String transletBaseName = null;
1656         if (!_transletName.equals(DEFAULT_TRANSLET_NAME))
1657             return _transletName;
1658         else {
1659             String systemId = source.getSystemId();
1660             if (systemId != null) {
1661                 String baseName = Util.baseName(systemId);
1662                 if (baseName != null) {
1663                     baseName = Util.noExtName(baseName);
1664                     transletBaseName = Util.toJavaName(baseName);
1665                 }
1666             }
1667         }
1668 
1669         return (transletBaseName != null) ? transletBaseName : DEFAULT_TRANSLET_NAME;
1670     }
1671 
1672     /**
1673      *  Return the local file name from the systemId of the Source object
1674      *
1675      * @param source The Source
1676      * @return The file name in the local filesystem, or null if the
1677      * systemId does not represent a local file.
1678      */
1679     private String getStylesheetFileName(Source source)
1680     {
1681         String systemId = source.getSystemId();
1682         if (systemId != null) {
1683             File file = new File(systemId);
1684             if (file.exists())
1685                 return systemId;
1686             else {
1687                 URL url;
1688                 try {
1689                     url = new URL(systemId);
1690                 }
1691                 catch (MalformedURLException e) {
1692                     return null;
1693                 }
1694 
1695                 if ("file".equals(url.getProtocol()))
1696                     return url.getFile();
1697                 else
1698                     return null;
1699             }
1700         }
1701         else
1702             return null;

1703     }
1704 
1705     /**
1706      * Returns a new instance of the XSLTC DTM Manager service.
1707      */
1708     protected final XSLTCDTMManager createNewDTMManagerInstance() {
1709         return XSLTCDTMManager.createNewDTMManagerInstance();
1710     }
1711 }
   1 /*
   2  * Copyright (c) 2007, 2017, 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 


  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.zip.ZipEntry;
  51 import java.util.zip.ZipFile;
  52 import javax.xml.XMLConstants;
  53 import javax.xml.catalog.CatalogException;
  54 import javax.xml.catalog.CatalogFeatures;
  55 import javax.xml.catalog.CatalogFeatures.Feature;
  56 import javax.xml.catalog.CatalogManager;
  57 import javax.xml.catalog.CatalogResolver;
  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;


 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      * Set to <code>true</code> when debugging is enabled.
 153      */
 154     private boolean _debug = false;
 155 
 156     /**
 157      * Set to <code>true</code> when templates are inlined.
 158      */
 159     private boolean _enableInlining = false;
 160 
 161     /**
 162      * Set to <code>true</code> when we want to generate
 163      * translet classes from the stylesheet.
 164      */
 165     private boolean _generateTranslet = false;
 166 
 167     /**
 168      * If this is set to <code>true</code>, we attempt to use translet classes
 169      * for transformation if possible without compiling the stylesheet. The
 170      * translet class is only used if its timestamp is newer than the timestamp
 171      * of the stylesheet.
 172      */
 173     private boolean _autoTranslet = false;
 174 
 175     /**
 176      * If this is set to <code>true</code>, we attempt to load the translet
 177      * from the CLASSPATH.
 178      */
 179     private boolean _useClasspath = false;
 180 
 181     /**
 182      * Number of indent spaces when indentation is turned on.
 183      */
 184     private int _indentNumber = -1;
 185 
 186     /**
 187      * <p>State of secure processing feature.</p>
 188      */
 189     private boolean _isNotSecureProcessing = true;
 190 
 191     /**
 192      * <p>State of secure mode.</p>
 193      */
 194     private boolean _isSecureMode = false;
 195 
 196     /**
 197      * Indicates whether implementation parts should use
 198      *   service loader (or similar).
 199      * Note the default value (false) is the safe option.
 200      */
 201     private boolean _useServicesMechanism;
 202 
 203     /**
 204      * protocols allowed for external references set by the stylesheet
 205      * processing instruction, Import and Include element.
 206      */
 207     private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
 208 
 209     /**
 210      * protocols allowed for external DTD references in source file and/or stylesheet.
 211      */
 212     private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
 213 
 214     private XMLSecurityPropertyManager _xmlSecurityPropertyMgr;
 215     private XMLSecurityManager _xmlSecurityManager;
 216 
 217     private final JdkXmlFeatures _xmlFeatures;
 218 
 219     private ClassLoader _extensionClassLoader = null;
 220 
 221     // Unmodifiable view of external extension function from xslt compiler
 222     // It will be populated by user-specified extension functions during the
 223     // type checking
 224     private Map<String, Class<?>> _xsltcExtensionFunctions;
 225 
 226     CatalogResolver _catalogUriResolver;
 227     CatalogFeatures _catalogFeatures;
 228     CatalogFeatures.Builder cfBuilder = CatalogFeatures.builder();
 229     // Catalog features


 529      * It is possible for an <code>TransformerFactory</code> to expose a feature value but be unable to change its state.
 530      * </p>
 531      *
 532      * <p>See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.</p>
 533      *
 534      * @param name Feature name.
 535      * @param value Is feature state <code>true</code> or <code>false</code>.
 536      *
 537      * @throws TransformerConfigurationException if this <code>TransformerFactory</code>
 538      *   or the <code>Transformer</code>s or <code>Template</code>s it creates cannot support this feature.
 539      * @throws NullPointerException If the <code>name</code> parameter is null.
 540      */
 541     @Override
 542     public void setFeature(String name, boolean value)
 543         throws TransformerConfigurationException {
 544 
 545         // feature name cannot be null
 546         if (name == null) {
 547             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_FEATURE_NULL_NAME);
 548             throw new NullPointerException(err.toString());

 549         // secure processing?
 550         } else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 551             if ((_isSecureMode) && (!value)) {
 552                 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SECUREPROCESSING_FEATURE);
 553                 throw new TransformerConfigurationException(err.toString());
 554             }
 555             _isNotSecureProcessing = !value;
 556             _xmlSecurityManager.setSecureProcessing(value);
 557 
 558             // set external access restriction when FSP is explicitly set
 559             if (value) {
 560                 _xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_DTD,
 561                         FeaturePropertyBase.State.FSP, XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
 562                 _xmlSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_STYLESHEET,
 563                         FeaturePropertyBase.State.FSP, XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP);
 564                 _accessExternalDTD = _xmlSecurityPropertyMgr.getValue(
 565                         Property.ACCESS_EXTERNAL_DTD);
 566                 _accessExternalStylesheet = _xmlSecurityPropertyMgr.getValue(
 567                         Property.ACCESS_EXTERNAL_STYLESHEET);
 568             }
 569 
 570             if (value && _xmlFeatures != null) {
 571                 _xmlFeatures.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION,
 572                         JdkXmlFeatures.State.FSP, false);
 573             }
 574         } else if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) {

 575             //in secure mode, let _useServicesMechanism be determined by the constructor
 576             if (!_isSecureMode)
 577                 _useServicesMechanism = value;
 578         } else {

 579             if (_xmlFeatures != null &&
 580                 _xmlFeatures.setFeature(name, JdkXmlFeatures.State.APIPROPERTY, value)) {
 581                 return;
 582             }
 583 
 584             // unknown feature
 585             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name);
 586             throw new TransformerConfigurationException(err.toString());
 587         }
 588     }
 589 
 590     /**
 591      * javax.xml.transform.sax.TransformerFactory implementation.
 592      * Look up the value of a feature (to see if it is supported).
 593      * This method must be updated as the various methods and features of this
 594      * class are implemented.
 595      *
 596      * @param name The feature name
 597      * @return 'true' if feature is supported, 'false' if not
 598      */
 599     @Override
 600     public boolean getFeature(String name) {
 601         // all supported features should be listed here
 602         String[] features = {
 603             DOMSource.FEATURE,
 604             DOMResult.FEATURE,
 605             SAXSource.FEATURE,
 606             SAXResult.FEATURE,
 607             StAXSource.FEATURE,
 608             StAXResult.FEATURE,
 609             StreamSource.FEATURE,
 610             StreamResult.FEATURE,
 611             SAXTransformerFactory.FEATURE,
 612             SAXTransformerFactory.FEATURE_XMLFILTER,
 613             XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM
 614         };
 615 
 616         // feature name cannot be null
 617         if (name == null) {
 618             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_GET_FEATURE_NULL_NAME);
 619             throw new NullPointerException(err.toString());
 620         }
 621 
 622         // Inefficient, but array is small
 623         for (int i = 0; i < features.length; i++) {
 624             if (name.equals(features[i])) {
 625                 return true;
 626             }
 627         }
 628 
 629         // secure processing?
 630         if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 631             return !_isNotSecureProcessing;
 632         }
 633 
 634         // check to see if the property is managed by the JdkXmlFeatues
 635         int index = _xmlFeatures.getIndex(name);
 636         if (index > -1) {
 637             return _xmlFeatures.getFeature(index);
 638         }
 639 
 640         // feature not supported
 641         return false;
 642     }
 643 
 644     /**
 645      * Return the state of the services mechanism feature.
 646      */
 647     public boolean useServicesMechnism() {
 648         return _useServicesMechanism;
 649     }
 650 
 651     /**
 652      * @return the feature manager
 653      */
 654     public JdkXmlFeatures getJdkXmlFeatures() {
 655         return _xmlFeatures;
 656     }
 657 
 658     /**
 659      * javax.xml.transform.sax.TransformerFactory implementation.
 660      * Get the object that is used by default during the transformation to
 661      * resolve URIs used in document(), xsl:import, or xsl:include.
 662      *
 663      * @return The URLResolver used for this TransformerFactory and all
 664      * Templates and Transformer objects created using this factory
 665      */
 666     @Override
 667     public URIResolver getURIResolver() {
 668         return _uriResolver;
 669     }
 670 
 671     /**


 796 
 797     /**
 798      * javax.xml.transform.sax.TransformerFactory implementation.
 799      * Process the Source into a Templates object, which is a a compiled
 800      * representation of the source. Note that this method should not be
 801      * used with XSLTC, as the time-consuming compilation is done for each
 802      * and every transformation.
 803      *
 804      * @return A Templates object that can be used to create Transformers.
 805      * @throws TransformerConfigurationException
 806      */
 807     @Override
 808     public Transformer newTransformer(Source source) throws
 809         TransformerConfigurationException
 810     {
 811         final Templates templates = newTemplates(source);
 812         final Transformer transformer = templates.newTransformer();
 813         if (_uriResolver != null) {
 814             transformer.setURIResolver(_uriResolver);
 815         }
 816         return transformer;
 817     }
 818 
 819     /**
 820      * Pass warning messages from the compiler to the error listener
 821      */
 822     private void passWarningsToListener(ArrayList<ErrorMsg> messages)
 823         throws TransformerException
 824     {
 825         if (_errorListener == null || messages == null) {
 826             return;
 827         }
 828         // Pass messages to listener, one by one
 829         final int count = messages.size();
 830         for (int pos = 0; pos < count; pos++) {
 831             ErrorMsg msg = messages.get(pos);
 832             // Workaround for the TCK failure ErrorListener.errorTests.error001.
 833             if (msg.isWarningError())
 834                 _errorListener.error(
 835                     new TransformerConfigurationException(msg.toString()));
 836             else


 949 
 950         if (!_isNotSecureProcessing) xsltc.setSecureProcessing(true);
 951         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet);
 952         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
 953         xsltc.setProperty(XalanConstants.SECURITY_MANAGER, _xmlSecurityManager);
 954         xsltc.setProperty(XalanConstants.JDK_EXTENSION_CLASSLOADER, _extensionClassLoader);
 955 
 956         // set Catalog features
 957         buildCatalogFeatures();
 958         xsltc.setProperty(JdkXmlFeatures.CATALOG_FEATURES, _catalogFeatures);
 959 
 960         xsltc.init();
 961         if (!_isNotSecureProcessing)
 962             _xsltcExtensionFunctions = xsltc.getExternalExtensionFunctions();
 963         // Set a document loader (for xsl:include/import) if defined
 964         if (_uriResolver != null || ( _catalogFiles != null
 965                 && _xmlFeatures.getFeature(JdkXmlFeatures.XmlFeature.USE_CATALOG))) {
 966             xsltc.setSourceLoader(this);
 967         }
 968 











 969         // Set the attributes for translet generation
 970         int outputType = XSLTC.BYTEARRAY_OUTPUT;
 971         if (_generateTranslet || _autoTranslet) {
 972             // Set the translet name
 973             xsltc.setClassName(getTransletBaseName(source));
 974 
 975             if (_destinationDirectory != null)
 976                 xsltc.setDestDirectory(_destinationDirectory);
 977             else {
 978                 String xslName = getStylesheetFileName(source);
 979                 if (xslName != null) {
 980                     File xslFile = new File(xslName);
 981                     String xslDir = xslFile.getParent();
 982 
 983                     if (xslDir != null)
 984                         xsltc.setDestDirectory(xslDir);
 985                 }
 986             }
 987 
 988             if (_packageName != null)


1393                 transletPath = transletPath + ".class";
1394         }
1395 
1396         // Return null if the translet class file does not exist.
1397         File transletFile = new File(transletPath);
1398         if (!transletFile.exists())
1399             return null;
1400 
1401         // Compare the timestamps of the translet and the xsl file.
1402         // If the translet is older than the xsl file, return null
1403         // so that the xsl file is used for the transformation and
1404         // the translet is regenerated.
1405         if (xslFile != null && xslFile.exists()) {
1406             long xslTimestamp = xslFile.lastModified();
1407             long transletTimestamp = transletFile.lastModified();
1408             if (transletTimestamp < xslTimestamp)
1409                 return null;
1410         }
1411 
1412         // Load the translet into a bytecode array.
1413         ArrayList<byte[]> bytecodes = new ArrayList<>();
1414         int fileLength = (int)transletFile.length();
1415         if (fileLength > 0) {
1416             FileInputStream input;
1417             try {
1418                 input = new FileInputStream(transletFile);
1419             }
1420             catch (FileNotFoundException e) {
1421                 return null;
1422             }
1423 
1424             byte[] bytes = new byte[fileLength];
1425             try {
1426                 readFromInputStream(bytes, input, fileLength);
1427                 input.close();
1428             }
1429             catch (IOException e) {
1430                 return null;
1431             }
1432 
1433             bytecodes.add(bytes);
1434         } else {

1435             return null;
1436         }
1437 
1438         // Find the parent directory of the translet.
1439         String transletParentDir = transletFile.getParent();
1440         if (transletParentDir == null)
1441             transletParentDir = SecuritySupport.getSystemProperty("user.dir");
1442 
1443         File transletParentFile = new File(transletParentDir);
1444 
1445         // Find all the auxiliary files which have a name pattern of "transletClass$nnn.class".
1446         final String transletAuxPrefix = transletName + "$";
1447         File[] auxfiles = transletParentFile.listFiles(new FilenameFilter() {
1448                 @Override
1449                 public boolean accept(File dir, String name)
1450                 {
1451                     return (name.endsWith(".class") && name.startsWith(transletAuxPrefix));
1452                 }
1453               });
1454 
1455         // Load the auxiliary class files and add them to the bytecode array.
1456         for (int i = 0; i < auxfiles.length; i++)


1459             int auxlength = (int)auxfile.length();
1460             if (auxlength > 0) {
1461                 FileInputStream auxinput = null;
1462                 try {
1463                     auxinput = new FileInputStream(auxfile);
1464                 }
1465                 catch (FileNotFoundException e) {
1466                     continue;
1467                 }
1468 
1469                 byte[] bytes = new byte[auxlength];
1470 
1471                 try {
1472                     readFromInputStream(bytes, auxinput, auxlength);
1473                     auxinput.close();
1474                 }
1475                 catch (IOException e) {
1476                     continue;
1477                 }
1478 
1479                 bytecodes.add(bytes);
1480             }
1481         }
1482 
1483         // Convert the Vector of byte[] to byte[][].
1484         final int count = bytecodes.size();
1485         if ( count > 0) {
1486             final byte[][] result = new byte[count][1];
1487             for (int i = 0; i < count; i++) {
1488                 result[i] = bytecodes.get(i);
1489             }
1490 
1491             return result;
1492         }
1493         else
1494             return null;
1495     }
1496 
1497     /**
1498      * Load the translet classes from the jar file and return the bytecode.
1499      *
1500      * @param source The xsl source
1501      * @param fullClassName The full name of the translet
1502      * @return The bytecode array
1503      */
1504     private byte[][] getBytecodesFromJar(Source source, String fullClassName)
1505     {
1506         String xslFileName = getStylesheetFileName(source);
1507         File xslFile = null;
1508         if (xslFileName != null)


1517                 jarPath = xslFile.getParent() + "/" + _jarFileName;
1518             else
1519                 jarPath = _jarFileName;
1520         }
1521 
1522         // Return null if the jar file does not exist.
1523         File file = new File(jarPath);
1524         if (!file.exists())
1525             return null;
1526 
1527         // Compare the timestamps of the jar file and the xsl file. Return null
1528         // if the xsl file is newer than the jar file.
1529         if (xslFile != null && xslFile.exists()) {
1530             long xslTimestamp = xslFile.lastModified();
1531             long transletTimestamp = file.lastModified();
1532             if (transletTimestamp < xslTimestamp)
1533                 return null;
1534         }
1535 
1536         // Create a ZipFile object for the jar file
1537         try (ZipFile jarFile = new ZipFile(file)) {
1538             String transletPath = fullClassName.replace('.', '/');
1539             String transletAuxPrefix = transletPath + "$";
1540             String transletFullName = transletPath + ".class";
1541 
1542             ArrayList<byte[]> bytecodes = new ArrayList<>();
1543 
1544             // Iterate through all entries in the jar file to find the
1545             // translet and auxiliary classes.
1546             Enumeration<? extends ZipEntry> entries = jarFile.entries();
1547             while (entries.hasMoreElements()) {
1548                 ZipEntry entry = entries.nextElement();
1549                 String entryName = entry.getName();
1550                 if (entry.getSize() > 0 &&
1551                     (entryName.equals(transletFullName) ||
1552                      (entryName.endsWith(".class") &&








1553                       entryName.startsWith(transletAuxPrefix))))
1554                 {

1555                     InputStream input = jarFile.getInputStream(entry);
1556                     int size = (int)entry.getSize();
1557                     byte[] bytes = new byte[size];
1558                     readFromInputStream(bytes, input, size);
1559                     input.close();
1560                     bytecodes.add(bytes);



1561                 }
1562             }

1563 
1564             // Convert the Vector of byte[] to byte[][].
1565             final int count = bytecodes.size();
1566             if (count > 0) {
1567                 final byte[][] result = new byte[count][1];
1568                 for (int i = 0; i < count; i++) {
1569                     result[i] = bytecodes.get(i);
1570                 }
1571                 return result;
1572             } else {
1573                 return null;
1574             }
1575         } catch (IOException e) {



1576             return null;
1577         }
1578     }
1579 
1580     /**
1581      * Read a given number of bytes from the InputStream into a byte array.
1582      *
1583      * @param bytes The byte array to store the input content.
1584      * @param input The input stream.
1585      * @param size The number of bytes to read.
1586      */
1587     private void readFromInputStream(byte[] bytes, InputStream input, int size)
1588         throws IOException
1589     {
1590         int n = 0;
1591         int offset = 0;
1592         int length = size;
1593         while (length > 0 && (n = input.read(bytes, offset, length)) > 0) {
1594             offset = offset + n;
1595             length = length - n;
1596         }
1597     }
1598 
1599     /**
1600      * Return the base class name of the translet.
1601      * The translet name is resolved using the following rules:
1602      * 1. if the _transletName attribute is set and its value is not "GregorSamsa",
1603      *    then _transletName is returned.
1604      * 2. otherwise get the translet name from the base name of the system ID
1605      * 3. return "GregorSamsa" if the result from step 2 is null.
1606      *
1607      * @param source The input Source
1608      * @return The name of the translet class
1609      */
1610     private String getTransletBaseName(Source source) {

1611         String transletBaseName = null;
1612         if (!_transletName.equals(DEFAULT_TRANSLET_NAME))
1613             return _transletName;
1614         else {
1615             String systemId = source.getSystemId();
1616             if (systemId != null) {
1617                 String baseName = Util.baseName(systemId);
1618                 if (baseName != null) {
1619                     baseName = Util.noExtName(baseName);
1620                     transletBaseName = Util.toJavaName(baseName);
1621                 }
1622             }
1623         }
1624 
1625         return (transletBaseName != null) ? transletBaseName : DEFAULT_TRANSLET_NAME;
1626     }
1627 
1628     /**
1629      *  Return the local file name from the systemId of the Source object
1630      *
1631      * @param source The Source
1632      * @return The file name in the local filesystem, or null if the
1633      * systemId does not represent a local file.
1634      */
1635     private String getStylesheetFileName(Source source) {

1636         String systemId = source.getSystemId();
1637         if (systemId != null) {
1638             File file = new File(systemId);
1639             if (file.exists())
1640                 return systemId;
1641             else {
1642                 URL url;
1643                 try {
1644                     url = new URL(systemId);
1645                 }
1646                 catch (MalformedURLException e) {
1647                     return null;
1648                 }
1649 
1650                 if ("file".equals(url.getProtocol()))
1651                     return url.getFile();
1652                 else
1653                     return null;
1654             }
1655         } else {

1656             return null;
1657         }
1658     }
1659 
1660     /**
1661      * Returns a new instance of the XSLTC DTM Manager service.
1662      */
1663     protected final XSLTCDTMManager createNewDTMManagerInstance() {
1664         return XSLTCDTMManager.createNewDTMManagerInstance();
1665     }
1666 }
< prev index next >