1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 1999-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: XMLReaderManager.java,v 1.2.4.1 2005/09/15 08:16:02 suresh_emailid Exp $ 22 */ 23 package com.sun.org.apache.xml.internal.utils; 24 25 import com.sun.org.apache.xalan.internal.XalanConstants; 26 import com.sun.org.apache.xalan.internal.utils.FactoryImpl; 27 import com.sun.org.apache.xalan.internal.utils.SecuritySupport; 28 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; 29 import java.util.HashMap; 30 31 import javax.xml.XMLConstants; 32 import javax.xml.parsers.FactoryConfigurationError; 33 import javax.xml.parsers.ParserConfigurationException; 34 import javax.xml.parsers.SAXParserFactory; 35 import org.xml.sax.SAXException; 36 import org.xml.sax.SAXNotRecognizedException; 37 import org.xml.sax.XMLReader; 38 import org.xml.sax.helpers.XMLReaderFactory; 39 40 /** 41 * Creates XMLReader objects and caches them for re-use. 42 * This class follows the singleton pattern. 43 */ 44 public class XMLReaderManager { 45 46 private static final String NAMESPACES_FEATURE = 47 "http://xml.org/sax/features/namespaces"; 48 private static final String NAMESPACE_PREFIXES_FEATURE = 49 "http://xml.org/sax/features/namespace-prefixes"; 50 private static final XMLReaderManager m_singletonManager = 51 new XMLReaderManager(); 52 private static final String property = "org.xml.sax.driver"; 53 /** 54 * Parser factory to be used to construct XMLReader objects 55 */ 56 private static SAXParserFactory m_parserFactory; 57 58 /** 59 * Cache of XMLReader objects 60 */ 61 private ThreadLocal m_readers; 62 63 /** 64 * Keeps track of whether an XMLReader object is in use. 65 */ 66 private HashMap m_inUse; 67 68 private boolean m_useServicesMechanism = true; 69 70 private boolean _secureProcessing; 71 /** 72 * protocols allowed for external DTD references in source file and/or stylesheet. 73 */ 74 private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 75 76 private XMLSecurityManager _xmlSecurityManager; 77 78 /** 79 * Hidden constructor 80 */ 81 private XMLReaderManager() { 82 } 83 84 /** 85 * Retrieves the singleton reader manager 86 */ 87 public static XMLReaderManager getInstance(boolean useServicesMechanism) { 88 m_singletonManager.setServicesMechnism(useServicesMechanism); 89 return m_singletonManager; 90 } 91 92 /** 93 * Retrieves a cached XMLReader for this thread, or creates a new 94 * XMLReader, if the existing reader is in use. When the caller no 95 * longer needs the reader, it must release it with a call to 96 * {@link #releaseXMLReader}. 97 */ 98 public synchronized XMLReader getXMLReader() throws SAXException { 99 XMLReader reader; 100 101 if (m_readers == null) { 102 // When the m_readers.get() method is called for the first time 103 // on a thread, a new XMLReader will automatically be created. 104 m_readers = new ThreadLocal(); 105 } 106 107 if (m_inUse == null) { 108 m_inUse = new HashMap(); 109 } 110 111 // If the cached reader for this thread is in use, construct a new 112 // one; otherwise, return the cached reader unless it isn't an 113 // instance of the class set in the 'org.xml.sax.driver' property 114 reader = (XMLReader) m_readers.get(); 115 boolean threadHasReader = (reader != null); 116 String factory = SecuritySupport.getSystemProperty(property); 117 if (threadHasReader && m_inUse.get(reader) != Boolean.TRUE && 118 ( factory == null || reader.getClass().getName().equals(factory))) { 119 m_inUse.put(reader, Boolean.TRUE); 120 } else { 121 try { 122 try { 123 // According to JAXP 1.2 specification, if a SAXSource 124 // is created using a SAX InputSource the Transformer or 125 // TransformerFactory creates a reader via the 126 // XMLReaderFactory if setXMLReader is not used 127 reader = XMLReaderFactory.createXMLReader(); 128 try { 129 reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _secureProcessing); 130 } catch (SAXNotRecognizedException e) { 131 XMLSecurityManager.printWarning(reader.getClass().getName(), 132 XMLConstants.FEATURE_SECURE_PROCESSING, e); 133 } 134 } catch (Exception e) { 135 try { 136 // If unable to create an instance, let's try to use 137 // the XMLReader from JAXP 138 if (m_parserFactory == null) { 139 m_parserFactory = FactoryImpl.getSAXFactory(m_useServicesMechanism); 140 m_parserFactory.setNamespaceAware(true); 141 } 142 143 reader = m_parserFactory.newSAXParser().getXMLReader(); 144 } catch (ParserConfigurationException pce) { 145 throw pce; // pass along pce 146 } 147 } 148 try { 149 reader.setFeature(NAMESPACES_FEATURE, true); 150 reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false); 151 } catch (SAXException se) { 152 // Try to carry on if we've got a parser that 153 // doesn't know about namespace prefixes. 154 } 155 } catch (ParserConfigurationException ex) { 156 throw new SAXException(ex); 157 } catch (FactoryConfigurationError ex1) { 158 throw new SAXException(ex1.toString()); 159 } catch (NoSuchMethodError ex2) { 160 } catch (AbstractMethodError ame) { 161 } 162 163 // Cache the XMLReader if this is the first time we've created 164 // a reader for this thread. 165 if (!threadHasReader) { 166 m_readers.set(reader); 167 m_inUse.put(reader, Boolean.TRUE); 168 } 169 } 170 171 try { 172 //reader is cached, but this property might have been reset 173 reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); 174 } catch (SAXException se) { 175 XMLSecurityManager.printWarning(reader.getClass().getName(), 176 XMLConstants.ACCESS_EXTERNAL_DTD, se); 177 } 178 179 String lastProperty = ""; 180 try { 181 if (_xmlSecurityManager != null) { 182 for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { 183 lastProperty = limit.apiProperty(); 184 reader.setProperty(lastProperty, 185 _xmlSecurityManager.getLimitValueAsString(limit)); 186 } 187 if (_xmlSecurityManager.printEntityCountInfo()) { 188 lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO; 189 reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES); 190 } 191 } 192 } catch (SAXException se) { 193 XMLSecurityManager.printWarning(reader.getClass().getName(), lastProperty, se); 194 } 195 196 return reader; 197 } 198 199 /** 200 * Mark the cached XMLReader as available. If the reader was not 201 * actually in the cache, do nothing. 202 * 203 * @param reader The XMLReader that's being released. 204 */ 205 public synchronized void releaseXMLReader(XMLReader reader) { 206 // If the reader that's being released is the cached reader 207 // for this thread, remove it from the m_isUse list. 208 if (m_readers.get() == reader && reader != null) { 209 m_inUse.remove(reader); 210 } 211 } 212 /** 213 * Return the state of the services mechanism feature. 214 */ 215 public boolean useServicesMechnism() { 216 return m_useServicesMechanism; 217 } 218 219 /** 220 * Set the state of the services mechanism feature. 221 */ 222 public void setServicesMechnism(boolean flag) { 223 m_useServicesMechanism = flag; 224 } 225 226 /** 227 * Set feature 228 */ 229 public void setFeature(String name, boolean value) { 230 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 231 _secureProcessing = value; 232 } 233 } 234 235 /** 236 * Get property value 237 */ 238 public Object getProperty(String name) { 239 if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { 240 return _accessExternalDTD; 241 } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { 242 return _xmlSecurityManager; 243 } 244 return null; 245 } 246 247 /** 248 * Set property. 249 */ 250 public void setProperty(String name, Object value) { 251 if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { 252 _accessExternalDTD = (String)value; 253 } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { 254 _xmlSecurityManager = (XMLSecurityManager)value; 255 } 256 } 257 } | 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 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.SecuritySupport; 26 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; 27 import java.util.HashMap; 28 import javax.xml.XMLConstants; 29 import javax.xml.catalog.CatalogFeatures; 30 import javax.xml.parsers.FactoryConfigurationError; 31 import javax.xml.parsers.ParserConfigurationException; 32 import javax.xml.parsers.SAXParserFactory; 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 /** 85 * Hidden constructor 86 */ 87 private XMLReaderManager() { 88 } 89 90 /** 91 * Retrieves the singleton reader manager 92 */ 93 public static XMLReaderManager getInstance(boolean useServicesMechanism) { 94 m_singletonManager.setServicesMechnism(useServicesMechanism); 95 return m_singletonManager; 96 } 97 98 /** 99 * Retrieves a cached XMLReader for this thread, or creates a new 100 * XMLReader, if the existing reader is in use. When the caller no 101 * longer needs the reader, it must release it with a call to 102 * {@link #releaseXMLReader}. 103 */ 104 public synchronized XMLReader getXMLReader() throws SAXException { 105 XMLReader reader; 106 107 if (m_readers == null) { 108 // When the m_readers.get() method is called for the first time 109 // on a thread, a new XMLReader will automatically be created. 110 m_readers = new ThreadLocal<>(); 111 } 112 113 if (m_inUse == null) { 114 m_inUse = new HashMap<>(); 115 } 116 117 // If the cached reader for this thread is in use, construct a new 118 // one; otherwise, return the cached reader unless it isn't an 119 // instance of the class set in the 'org.xml.sax.driver' property 120 reader = m_readers.get(); 121 boolean threadHasReader = (reader != null); 122 String factory = SecuritySupport.getSystemProperty(property); 123 if (threadHasReader && m_inUse.get(reader) != Boolean.TRUE && 124 ( factory == null || reader.getClass().getName().equals(factory))) { 125 m_inUse.put(reader, Boolean.TRUE); 126 } else { 127 try { 128 try { 129 // According to JAXP 1.2 specification, if a SAXSource 130 // is created using a SAX InputSource the Transformer or 131 // TransformerFactory creates a reader via the 132 // XMLReaderFactory if setXMLReader is not used 133 reader = XMLReaderFactory.createXMLReader(); 134 try { 135 reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _secureProcessing); 136 } catch (SAXNotRecognizedException e) { 137 XMLSecurityManager.printWarning(reader.getClass().getName(), 138 XMLConstants.FEATURE_SECURE_PROCESSING, e); 139 } 140 } catch (SAXException e) { 141 try { 142 // If unable to create an instance, let's try to use 143 // the XMLReader from JAXP 144 if (m_parserFactory == null) { 145 m_parserFactory = FactoryImpl.getSAXFactory(m_useServicesMechanism); 146 m_parserFactory.setNamespaceAware(true); 147 } 148 149 reader = m_parserFactory.newSAXParser().getXMLReader(); 150 } catch (ParserConfigurationException pce) { 151 throw pce; // pass along pce 152 } 153 } 154 try { 155 reader.setFeature(NAMESPACES_FEATURE, true); 156 reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false); 157 } catch (SAXException se) { 158 // Try to carry on if we've got a parser that 159 // doesn't know about namespace prefixes. 160 } 161 } catch (ParserConfigurationException ex) { 162 throw new SAXException(ex); 163 } catch (FactoryConfigurationError ex1) { 164 throw new SAXException(ex1.toString()); 165 } catch (NoSuchMethodError | AbstractMethodError ex2) { 166 } 167 168 // Cache the XMLReader if this is the first time we've created 169 // a reader for this thread. 170 if (!threadHasReader) { 171 m_readers.set(reader); 172 m_inUse.put(reader, Boolean.TRUE); 173 } 174 } 175 176 try { 177 //reader is cached, but this property might have been reset 178 reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); 179 } catch (SAXException se) { 180 XMLSecurityManager.printWarning(reader.getClass().getName(), 181 XMLConstants.ACCESS_EXTERNAL_DTD, se); 182 } 183 184 String lastProperty = ""; 185 try { 186 if (_xmlSecurityManager != null) { 187 for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { 188 lastProperty = limit.apiProperty(); 189 reader.setProperty(lastProperty, 190 _xmlSecurityManager.getLimitValueAsString(limit)); 191 } 192 if (_xmlSecurityManager.printEntityCountInfo()) { 193 lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO; 194 reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES); 195 } 196 } 197 } catch (SAXException se) { 198 XMLSecurityManager.printWarning(reader.getClass().getName(), lastProperty, se); 199 } 200 201 boolean supportCatalog = true; 202 try { 203 reader.setFeature(JdkXmlUtils.USE_CATALOG, _useCatalog); 204 } 205 catch (SAXNotRecognizedException | SAXNotSupportedException e) { 206 supportCatalog = false; 207 } 208 209 if (supportCatalog && _useCatalog && _catalogFeatures != null) { 210 try { 211 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) { 212 reader.setProperty(f.getPropertyName(), _catalogFeatures.get(f)); 213 } 214 } catch (SAXNotRecognizedException e) { 215 //shall not happen for internal settings 216 } 217 } 218 return reader; 219 } 220 221 /** 222 * Mark the cached XMLReader as available. If the reader was not 223 * actually in the cache, do nothing. 224 * 225 * @param reader The XMLReader that's being released. 226 */ 227 public synchronized void releaseXMLReader(XMLReader reader) { 228 // If the reader that's being released is the cached reader 229 // for this thread, remove it from the m_isUse list. 230 if (m_readers.get() == reader && reader != null) { 231 m_inUse.remove(reader); 232 } 233 } 234 /** 235 * Return the state of the services mechanism feature. 236 */ 237 public boolean useServicesMechnism() { 238 return m_useServicesMechanism; 239 } 240 241 /** 242 * Set the state of the services mechanism feature. 243 */ 244 public void setServicesMechnism(boolean flag) { 245 m_useServicesMechanism = flag; 246 } 247 248 /** 249 * Set feature 250 */ 251 public void setFeature(String name, boolean value) { 252 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 253 _secureProcessing = value; 254 } else if (XMLConstants.USE_CATALOG.equals(name)) { 255 _useCatalog = value; 256 } 257 } 258 259 /** 260 * Get property value 261 */ 262 public Object getProperty(String name) { 263 if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { 264 return _accessExternalDTD; 265 } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { 266 return _xmlSecurityManager; 267 } 268 return null; 269 } 270 271 /** 272 * Set property. 273 */ 274 public void setProperty(String name, Object value) { 275 if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { 276 _accessExternalDTD = (String)value; 277 } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { 278 _xmlSecurityManager = (XMLSecurityManager)value; 279 } else if (JdkXmlFeatures.CATALOG_FEATURES.equals(name)) { 280 _catalogFeatures = (CatalogFeatures)value; 281 } 282 283 } 284 } |