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 }
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)) {
|
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 package com.sun.org.apache.xml.internal.utils;
21
22 import com.sun.org.apache.xalan.internal.XalanConstants;
23 import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
24 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
25 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
26 import java.util.HashMap;
27 import javax.xml.XMLConstants;
28 import javax.xml.catalog.CatalogFeatures;
29 import javax.xml.parsers.FactoryConfigurationError;
30 import javax.xml.parsers.ParserConfigurationException;
31 import javax.xml.parsers.SAXParserFactory;
32 import jdk.xml.internal.JdkXmlFeatures;
33 import jdk.xml.internal.JdkXmlUtils;
34 import org.xml.sax.SAXException;
35 import org.xml.sax.SAXNotRecognizedException;
36 import org.xml.sax.SAXNotSupportedException;
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 @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory
45 public class XMLReaderManager {
46
47 private static final String NAMESPACES_FEATURE =
48 "http://xml.org/sax/features/namespaces";
49 private static final String NAMESPACE_PREFIXES_FEATURE =
50 "http://xml.org/sax/features/namespace-prefixes";
51 private static final XMLReaderManager m_singletonManager =
52 new XMLReaderManager();
53 private static final String property = "org.xml.sax.driver";
54
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 m_NamespaceAware = true;
73
74 private boolean _secureProcessing;
75
76 /**
77 * protocols allowed for external DTD references in source file and/or stylesheet.
78 */
79 private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
80
81 private XMLSecurityManager _xmlSecurityManager;
82
83 /**
84 * Catalog Feature
85 */
86 private boolean _useCatalog;
87 private CatalogFeatures _catalogFeatures;
88
89 /**
90 * Hidden constructor
91 */
92 private XMLReaderManager() {}
93
94 /**
95 * Retrieves the singleton reader manager
96 */
97 public static XMLReaderManager getInstance(boolean useServicesMechanism) {
98 m_singletonManager.setServicesMechnism(useServicesMechanism);
99 return m_singletonManager;
100 }
101
102 /**
103 * Retrieves a cached XMLReader for this thread, or creates a new
104 * XMLReader, if the existing reader is in use. When the caller no
105 * longer needs the reader, it must release it with a call to
106 * {@link #releaseXMLReader}.
107 */
108 public synchronized XMLReader getXMLReader() throws SAXException {
109 XMLReader reader;
110
111 if (m_readers == null) {
112 // When the m_readers.get() method is called for the first time
113 // on a thread, a new XMLReader will automatically be created.
114 m_readers = new ThreadLocal<>();
115 }
116
117 if (m_inUse == null) {
118 m_inUse = new HashMap<>();
119 }
120
121 // If the cached reader for this thread is in use, construct a new
122 // one; otherwise, return the cached reader unless it isn't an
123 // instance of the class set in the 'org.xml.sax.driver' property
124 reader = m_readers.get();
125 boolean threadHasReader = (reader != null);
126 String factory = SecuritySupport.getSystemProperty(property);
127 if (threadHasReader &&
128 m_inUse.get(reader) != Boolean.TRUE &&
129 (factory == null || reader.getClass().getName().equals(factory))) {
130 m_inUse.put(reader, Boolean.TRUE);
131 } else {
132 try {
133 try {
134 // According to JAXP 1.2 specification, if a SAXSource
135 // is created using a SAX InputSource the Transformer or
136 // TransformerFactory creates a reader via the
137 // XMLReaderFactory if setXMLReader is not used
138 reader = XMLReaderFactory.createXMLReader();
139 try {
140 reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _secureProcessing);
141 } catch (SAXNotRecognizedException e) {
142 XMLSecurityManager.printWarning(reader.getClass().getName(),
143 XMLConstants.FEATURE_SECURE_PROCESSING, e);
144 }
145 } catch (SAXException e) {
146 try {
147 // If unable to create an instance, let's try to use
148 // the XMLReader from JAXP
149 if (m_parserFactory == null) {
150 m_parserFactory = FactoryImpl.getSAXFactory(m_useServicesMechanism);
151 m_parserFactory.setNamespaceAware(true);
152 }
153
154 reader = m_parserFactory.newSAXParser().getXMLReader();
155 } catch (ParserConfigurationException pce) {
156 throw pce; // pass along pce
157 }
158 }
159 } catch (ParserConfigurationException ex) {
160 throw new SAXException(ex);
161 } catch (FactoryConfigurationError ex1) {
162 throw new SAXException(ex1.toString());
163 } catch (NoSuchMethodError | AbstractMethodError ex2) {
164 }
165
166 // Cache the XMLReader if this is the first time we've created
167 // a reader for this thread.
168 if (!threadHasReader) {
169 m_readers.set(reader);
170 m_inUse.put(reader, Boolean.TRUE);
171 }
172 }
173
174 try {
175 //reader is cached, but this feature might have been reset
176 if (m_NamespaceAware) {
177 reader.setFeature(NAMESPACES_FEATURE, true);
178 reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false);
179 } else {
180 reader.setFeature(NAMESPACES_FEATURE, false);
181 reader.setFeature(NAMESPACE_PREFIXES_FEATURE, true);
182 }
183 } catch (SAXException se) {
184 // Try to carry on if we've got a parser that
185 // doesn't know about namespace prefixes.
186 }
187
188 try {
189 //reader is cached, but this property might have been reset
190 reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
191 } catch (SAXException se) {
192 XMLSecurityManager.printWarning(reader.getClass().getName(),
193 XMLConstants.ACCESS_EXTERNAL_DTD, se);
194 }
195
196 String lastProperty = "";
197 try {
198 if (_xmlSecurityManager != null) {
199 for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) {
200 lastProperty = limit.apiProperty();
201 reader.setProperty(lastProperty,
202 _xmlSecurityManager.getLimitValueAsString(limit));
203 }
204 if (_xmlSecurityManager.printEntityCountInfo()) {
205 lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO;
206 reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES);
207 }
208 }
244 }
245 }
246 /**
247 * Return the state of the services mechanism feature.
248 */
249 public boolean useServicesMechnism() {
250 return m_useServicesMechanism;
251 }
252
253 /**
254 * Set the state of the services mechanism feature.
255 */
256 public void setServicesMechnism(boolean flag) {
257 m_useServicesMechanism = flag;
258 }
259
260 /**
261 * Set feature
262 */
263 public void setFeature(String name, boolean value) {
264 if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name)) {
265 _secureProcessing = value;
266 } else if (XMLConstants.USE_CATALOG.equals(name)) {
267 _useCatalog = value;
268 } else if (NAMESPACES_FEATURE.equals(name)) {
269 m_NamespaceAware = value;
270 }
271 }
272
273 /**
274 * Get property value
275 */
276 public Object getProperty(String name) {
277 if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
278 return _accessExternalDTD;
279 } else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
280 return _xmlSecurityManager;
281 }
282 return null;
283 }
284
285 /**
286 * Set property.
287 */
288 public void setProperty(String name, Object value) {
289 if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
|