< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.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.xml.internal.utils;
  22 


  33 import jdk.xml.internal.JdkXmlFeatures;
  34 import jdk.xml.internal.JdkXmlUtils;
  35 import org.xml.sax.SAXException;
  36 import org.xml.sax.SAXNotRecognizedException;
  37 import org.xml.sax.SAXNotSupportedException;
  38 import org.xml.sax.XMLReader;
  39 import org.xml.sax.helpers.XMLReaderFactory;
  40 
  41 /**
  42  * Creates XMLReader objects and caches them for re-use.
  43  * This class follows the singleton pattern.
  44  */
  45 @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory
  46 public class XMLReaderManager {
  47 
  48     private static final String NAMESPACES_FEATURE =
  49                              "http://xml.org/sax/features/namespaces";
  50     private static final String NAMESPACE_PREFIXES_FEATURE =
  51                              "http://xml.org/sax/features/namespace-prefixes";
  52     private static final XMLReaderManager m_singletonManager =
  53                                                      new XMLReaderManager();
  54     private static final String property = "org.xml.sax.driver";

  55     /**
  56      * Parser factory to be used to construct XMLReader objects
  57      */
  58     private static SAXParserFactory m_parserFactory;
  59 
  60     /**
  61      * Cache of XMLReader objects
  62      */
  63     private ThreadLocal<XMLReader> m_readers;
  64 
  65     /**
  66      * Keeps track of whether an XMLReader object is in use.
  67      */
  68     private HashMap<XMLReader, Boolean> m_inUse;
  69 
  70     private boolean m_useServicesMechanism = true;
  71 
  72     private boolean _secureProcessing;
  73      /**

  74      * protocols allowed for external DTD references in source file and/or stylesheet.
  75      */
  76     private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
  77 
  78     private XMLSecurityManager _xmlSecurityManager;
  79 
  80     //Catalog Feature


  81     private boolean _useCatalog;
  82     private CatalogFeatures _catalogFeatures;
  83 
  84     private int _cdataChunkSize;
  85 
  86     /**
  87      * Hidden constructor
  88      */
  89     private XMLReaderManager() {
  90     }
  91 
  92     /**
  93      * Retrieves the singleton reader manager
  94      */
  95     public static XMLReaderManager getInstance(boolean useServicesMechanism) {
  96         m_singletonManager.setServicesMechnism(useServicesMechanism);
  97         return m_singletonManager;
  98     }
  99 
 100     /**
 101      * Retrieves a cached XMLReader for this thread, or creates a new
 102      * XMLReader, if the existing reader is in use.  When the caller no
 103      * longer needs the reader, it must release it with a call to
 104      * {@link #releaseXMLReader}.
 105      */
 106     public synchronized XMLReader getXMLReader() throws SAXException {
 107         XMLReader reader;
 108 
 109         if (m_readers == null) {
 110             // When the m_readers.get() method is called for the first time
 111             // on a thread, a new XMLReader will automatically be created.
 112             m_readers = new ThreadLocal<>();
 113         }
 114 
 115         if (m_inUse == null) {
 116             m_inUse = new HashMap<>();
 117         }
 118 
 119         // If the cached reader for this thread is in use, construct a new
 120         // one; otherwise, return the cached reader unless it isn't an
 121         // instance of the class set in the 'org.xml.sax.driver' property
 122         reader = m_readers.get();
 123         boolean threadHasReader = (reader != null);
 124         String factory = SecuritySupport.getSystemProperty(property);
 125         if (threadHasReader && m_inUse.get(reader) != Boolean.TRUE &&
 126                 ( factory == null || reader.getClass().getName().equals(factory))) {

 127             m_inUse.put(reader, Boolean.TRUE);
 128         } else {
 129             try {
 130                 try {
 131                     // According to JAXP 1.2 specification, if a SAXSource
 132                     // is created using a SAX InputSource the Transformer or
 133                     // TransformerFactory creates a reader via the
 134                     // XMLReaderFactory if setXMLReader is not used
 135                     reader = XMLReaderFactory.createXMLReader();
 136                     try {
 137                         reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _secureProcessing);
 138                     } catch (SAXNotRecognizedException e) {
 139                         XMLSecurityManager.printWarning(reader.getClass().getName(),
 140                                 XMLConstants.FEATURE_SECURE_PROCESSING, e);
 141                     }
 142                 } catch (SAXException e) {
 143                    try {
 144                         // If unable to create an instance, let's try to use
 145                         // the XMLReader from JAXP
 146                         if (m_parserFactory == null) {


 159                 } catch (SAXException se) {
 160                     // Try to carry on if we've got a parser that
 161                     // doesn't know about namespace prefixes.
 162                 }
 163             } catch (ParserConfigurationException ex) {
 164                 throw new SAXException(ex);
 165             } catch (FactoryConfigurationError ex1) {
 166                 throw new SAXException(ex1.toString());
 167             } catch (NoSuchMethodError | AbstractMethodError ex2) {
 168             }
 169 
 170             // Cache the XMLReader if this is the first time we've created
 171             // a reader for this thread.
 172             if (!threadHasReader) {
 173                 m_readers.set(reader);
 174                 m_inUse.put(reader, Boolean.TRUE);
 175             }
 176         }
 177 
 178         //reader is cached, but this property might have been reset
 179         JdkXmlUtils.setXMLReaderPropertyIfSupport(reader, XMLConstants.ACCESS_EXTERNAL_DTD,
 180                 _accessExternalDTD, true);
 181 
 182         JdkXmlUtils.setXMLReaderPropertyIfSupport(reader, JdkXmlUtils.CDATA_CHUNK_SIZE,
 183                 _cdataChunkSize, false);
 184 
 185         String lastProperty = "";
 186         try {
 187             if (_xmlSecurityManager != null) {
 188                 for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) {
 189                     lastProperty = limit.apiProperty();
 190                     reader.setProperty(lastProperty,
 191                             _xmlSecurityManager.getLimitValueAsString(limit));
 192                 }
 193                 if (_xmlSecurityManager.printEntityCountInfo()) {
 194                     lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO;
 195                     reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES);
 196                 }
 197             }
 198         } catch (SAXException se) {
 199             XMLSecurityManager.printWarning(reader.getClass().getName(), lastProperty, se);
 200         }
 201 
 202         boolean supportCatalog = true;
 203         try {
 204             reader.setFeature(JdkXmlUtils.USE_CATALOG, _useCatalog);
 205         }
 206         catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 207             supportCatalog = false;
 208         }
 209 
 210         if (supportCatalog && _useCatalog && _catalogFeatures != null) {
 211             try {
 212                 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
 213                     reader.setProperty(f.getPropertyName(), _catalogFeatures.get(f));
 214                 }
 215             } catch (SAXNotRecognizedException e) {
 216                 //shall not happen for internal settings
 217             }
 218         }
 219         return reader;
 220     }
 221 
 222     /**
 223      * Mark the cached XMLReader as available.  If the reader was not
 224      * actually in the cache, do nothing.
 225      *
 226      * @param reader The XMLReader that's being released.


 233         }
 234     }
 235     /**
 236      * Return the state of the services mechanism feature.
 237      */
 238     public boolean useServicesMechnism() {
 239         return m_useServicesMechanism;
 240     }
 241 
 242     /**
 243      * Set the state of the services mechanism feature.
 244      */
 245     public void setServicesMechnism(boolean flag) {
 246         m_useServicesMechanism = flag;
 247     }
 248 
 249     /**
 250      * Set feature
 251      */
 252     public void setFeature(String name, boolean value) {
 253         if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
 254             _secureProcessing = value;
 255         } else if (XMLConstants.USE_CATALOG.equals(name)) {
 256             _useCatalog = value;
 257         }
 258     }
 259 
 260     /**
 261      * Get property value
 262      */
 263     public Object getProperty(String name) {
 264         if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
 265             return _accessExternalDTD;
 266         } else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
 267             return _xmlSecurityManager;
 268         }
 269         return null;
 270     }
 271 
 272     /**
 273      * Set property.
   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.xml.internal.utils;
  22 


  33 import jdk.xml.internal.JdkXmlFeatures;
  34 import jdk.xml.internal.JdkXmlUtils;
  35 import org.xml.sax.SAXException;
  36 import org.xml.sax.SAXNotRecognizedException;
  37 import org.xml.sax.SAXNotSupportedException;
  38 import org.xml.sax.XMLReader;
  39 import org.xml.sax.helpers.XMLReaderFactory;
  40 
  41 /**
  42  * Creates XMLReader objects and caches them for re-use.
  43  * This class follows the singleton pattern.
  44  */
  45 @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory
  46 public class XMLReaderManager {
  47 
  48     private static final String NAMESPACES_FEATURE =
  49                              "http://xml.org/sax/features/namespaces";
  50     private static final String NAMESPACE_PREFIXES_FEATURE =
  51                              "http://xml.org/sax/features/namespace-prefixes";
  52     private static final XMLReaderManager m_singletonManager =
  53                              new XMLReaderManager();
  54     private static final String property = "org.xml.sax.driver";
  55 
  56     /**
  57      * Parser factory to be used to construct XMLReader objects
  58      */
  59     private static SAXParserFactory m_parserFactory;
  60 
  61     /**
  62      * Cache of XMLReader objects
  63      */
  64     private ThreadLocal<XMLReader> m_readers;
  65 
  66     /**
  67      * Keeps track of whether an XMLReader object is in use.
  68      */
  69     private HashMap<XMLReader, Boolean> m_inUse;
  70 
  71     private boolean m_useServicesMechanism = true;
  72 
  73     private boolean _secureProcessing;
  74 
  75     /**
  76      * protocols allowed for external DTD references in source file and/or stylesheet.
  77      */
  78     private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
  79 
  80     private XMLSecurityManager _xmlSecurityManager;
  81 
  82     /**
  83      * Catalog Feature
  84      */
  85     private boolean _useCatalog;
  86     private CatalogFeatures _catalogFeatures;
  87 
  88     private int _cdataChunkSize;
  89 
  90     /**
  91      * Hidden constructor
  92      */
  93     private XMLReaderManager() {}

  94 
  95     /**
  96      * Retrieves the singleton reader manager
  97      */
  98     public static XMLReaderManager getInstance(boolean useServicesMechanism) {
  99         m_singletonManager.setServicesMechnism(useServicesMechanism);
 100         return m_singletonManager;
 101     }
 102 
 103     /**
 104      * Retrieves a cached XMLReader for this thread, or creates a new
 105      * XMLReader, if the existing reader is in use.  When the caller no
 106      * longer needs the reader, it must release it with a call to
 107      * {@link #releaseXMLReader}.
 108      */
 109     public synchronized XMLReader getXMLReader() throws SAXException {
 110         XMLReader reader;
 111 
 112         if (m_readers == null) {
 113             // When the m_readers.get() method is called for the first time
 114             // on a thread, a new XMLReader will automatically be created.
 115             m_readers = new ThreadLocal<>();
 116         }
 117 
 118         if (m_inUse == null) {
 119             m_inUse = new HashMap<>();
 120         }
 121 
 122         // If the cached reader for this thread is in use, construct a new
 123         // one; otherwise, return the cached reader unless it isn't an
 124         // instance of the class set in the 'org.xml.sax.driver' property
 125         reader = m_readers.get();
 126         boolean threadHasReader = (reader != null);
 127         String factory = SecuritySupport.getSystemProperty(property);
 128         if (threadHasReader &&
 129             m_inUse.get(reader) != Boolean.TRUE &&
 130             (factory == null || reader.getClass().getName().equals(factory))) {
 131             m_inUse.put(reader, Boolean.TRUE);
 132         } else {
 133             try {
 134                 try {
 135                     // According to JAXP 1.2 specification, if a SAXSource
 136                     // is created using a SAX InputSource the Transformer or
 137                     // TransformerFactory creates a reader via the
 138                     // XMLReaderFactory if setXMLReader is not used
 139                     reader = XMLReaderFactory.createXMLReader();
 140                     try {
 141                         reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _secureProcessing);
 142                     } catch (SAXNotRecognizedException e) {
 143                         XMLSecurityManager.printWarning(reader.getClass().getName(),
 144                                 XMLConstants.FEATURE_SECURE_PROCESSING, e);
 145                     }
 146                 } catch (SAXException e) {
 147                    try {
 148                         // If unable to create an instance, let's try to use
 149                         // the XMLReader from JAXP
 150                         if (m_parserFactory == null) {


 163                 } catch (SAXException se) {
 164                     // Try to carry on if we've got a parser that
 165                     // doesn't know about namespace prefixes.
 166                 }
 167             } catch (ParserConfigurationException ex) {
 168                 throw new SAXException(ex);
 169             } catch (FactoryConfigurationError ex1) {
 170                 throw new SAXException(ex1.toString());
 171             } catch (NoSuchMethodError | AbstractMethodError ex2) {
 172             }
 173 
 174             // Cache the XMLReader if this is the first time we've created
 175             // a reader for this thread.
 176             if (!threadHasReader) {
 177                 m_readers.set(reader);
 178                 m_inUse.put(reader, Boolean.TRUE);
 179             }
 180         }
 181 
 182         //reader is cached, but this property might have been reset
 183         JdkXmlUtils.setXMLReaderPropertyIfSupport(reader,
 184             XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD, true);
 185 
 186         JdkXmlUtils.setXMLReaderPropertyIfSupport(reader,
 187             JdkXmlUtils.CDATA_CHUNK_SIZE, _cdataChunkSize, false);
 188 
 189         String lastProperty = "";
 190         try {
 191             if (_xmlSecurityManager != null) {
 192                 for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) {
 193                     lastProperty = limit.apiProperty();
 194                     reader.setProperty(lastProperty,
 195                         _xmlSecurityManager.getLimitValueAsString(limit));
 196                 }
 197                 if (_xmlSecurityManager.printEntityCountInfo()) {
 198                     lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO;
 199                     reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES);
 200                 }
 201             }
 202         } catch (SAXException se) {
 203             XMLSecurityManager.printWarning(reader.getClass().getName(), lastProperty, se);
 204         }
 205 
 206         boolean supportCatalog = true;
 207         try {
 208             reader.setFeature(JdkXmlUtils.USE_CATALOG, _useCatalog);
 209         } catch (SAXNotRecognizedException | SAXNotSupportedException e) {

 210             supportCatalog = false;
 211         }
 212 
 213         if (supportCatalog && _useCatalog && _catalogFeatures != null) {
 214             try {
 215                 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
 216                     reader.setProperty(f.getPropertyName(), _catalogFeatures.get(f));
 217                 }
 218             } catch (SAXNotRecognizedException e) {
 219                 //shall not happen for internal settings
 220             }
 221         }
 222         return reader;
 223     }
 224 
 225     /**
 226      * Mark the cached XMLReader as available.  If the reader was not
 227      * actually in the cache, do nothing.
 228      *
 229      * @param reader The XMLReader that's being released.


 236         }
 237     }
 238     /**
 239      * Return the state of the services mechanism feature.
 240      */
 241     public boolean useServicesMechnism() {
 242         return m_useServicesMechanism;
 243     }
 244 
 245     /**
 246      * Set the state of the services mechanism feature.
 247      */
 248     public void setServicesMechnism(boolean flag) {
 249         m_useServicesMechanism = flag;
 250     }
 251 
 252     /**
 253      * Set feature
 254      */
 255     public void setFeature(String name, boolean value) {
 256         if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name)) {
 257             _secureProcessing = value;
 258         } else if (XMLConstants.USE_CATALOG.equals(name)) {
 259             _useCatalog = value;
 260         }
 261     }
 262 
 263     /**
 264      * Get property value
 265      */
 266     public Object getProperty(String name) {
 267         if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
 268             return _accessExternalDTD;
 269         } else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
 270             return _xmlSecurityManager;
 271         }
 272         return null;
 273     }
 274 
 275     /**
 276      * Set property.
< prev index next >