|
|
|
|
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
package com.sun.org.apache.xml.internal.utils; |
|
|
|
import com.sun.org.apache.xalan.internal.XalanConstants; |
|
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; |
|
import java.util.HashMap; |
|
import javax.xml.XMLConstants; |
|
import javax.xml.catalog.CatalogFeatures; |
|
import jdk.xml.internal.JdkXmlFeatures; |
|
import jdk.xml.internal.JdkXmlUtils; |
|
import jdk.xml.internal.SecuritySupport; |
|
import org.xml.sax.SAXException; |
|
import org.xml.sax.SAXNotRecognizedException; |
|
import org.xml.sax.SAXNotSupportedException; |
|
import org.xml.sax.XMLReader; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class XMLReaderManager { |
|
|
|
private static final XMLReaderManager m_singletonManager = |
|
new XMLReaderManager(); |
|
private static final String property = "org.xml.sax.driver"; |
|
|
|
|
|
|
|
*/ |
|
private ThreadLocal<ReaderWrapper> m_readers; |
|
|
|
|
|
|
|
*/ |
|
private HashMap<XMLReader, Boolean> m_inUse; |
|
|
|
private boolean m_overrideDefaultParser; |
|
|
|
private boolean _secureProcessing; |
|
|
|
|
|
*/ |
|
private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; |
|
|
|
private XMLSecurityManager _xmlSecurityManager; |
|
|
|
|
|
private boolean _useCatalog; |
|
private CatalogFeatures _catalogFeatures; |
|
|
|
private int _cdataChunkSize; |
|
|
|
|
|
|
|
*/ |
|
private XMLReaderManager() { |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static XMLReaderManager getInstance(boolean overrideDefaultParser) { |
|
m_singletonManager.setOverrideDefaultParser(overrideDefaultParser); |
|
return m_singletonManager; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public synchronized XMLReader getXMLReader() throws SAXException { |
|
XMLReader reader; |
|
|
|
if (m_readers == null) { |
|
// When the m_readers.get() method is called for the first time |
|
|
|
m_readers = new ThreadLocal<>(); |
|
} |
|
|
|
if (m_inUse == null) { |
|
m_inUse = new HashMap<>(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
ReaderWrapper rw = m_readers.get(); |
|
boolean threadHasReader = (rw != null); |
|
reader = threadHasReader ? rw.reader : null; |
|
String factory = SecuritySupport.getSystemProperty(property); |
|
if (threadHasReader && m_inUse.get(reader) != Boolean.TRUE && |
|
(rw.overrideDefaultParser == m_overrideDefaultParser) && |
|
( factory == null || reader.getClass().getName().equals(factory))) { |
|
m_inUse.put(reader, Boolean.TRUE); |
|
} else { |
|
reader = JdkXmlUtils.getXMLReader(m_overrideDefaultParser, _secureProcessing); |
|
|
|
// Cache the XMLReader if this is the first time we've created |
|
|
|
if (!threadHasReader) { |
|
m_readers.set(new ReaderWrapper(reader, m_overrideDefaultParser)); |
|
m_inUse.put(reader, Boolean.TRUE); |
|
} |
|
} |
|
|
|
|
|
JdkXmlUtils.setXMLReaderPropertyIfSupport(reader, XMLConstants.ACCESS_EXTERNAL_DTD, |
|
_accessExternalDTD, true); |
|
|
|
JdkXmlUtils.setXMLReaderPropertyIfSupport(reader, JdkXmlUtils.CDATA_CHUNK_SIZE, |
|
_cdataChunkSize, false); |
|
|
|
String lastProperty = ""; |
|
try { |
|
if (_xmlSecurityManager != null) { |
|
for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { |
|
lastProperty = limit.apiProperty(); |
|
reader.setProperty(lastProperty, |
|
_xmlSecurityManager.getLimitValueAsString(limit)); |
|
} |
|
if (_xmlSecurityManager.printEntityCountInfo()) { |
|
lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO; |
|
reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES); |
|
} |
|
} |
|
} catch (SAXException se) { |
|
XMLSecurityManager.printWarning(reader.getClass().getName(), lastProperty, se); |
|
} |
|
|
|
boolean supportCatalog = true; |
|
try { |
|
reader.setFeature(JdkXmlUtils.USE_CATALOG, _useCatalog); |
|
} |
|
catch (SAXNotRecognizedException | SAXNotSupportedException e) { |
|
supportCatalog = false; |
|
} |
|
|
|
if (supportCatalog && _useCatalog && _catalogFeatures != null) { |
|
try { |
|
for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) { |
|
reader.setProperty(f.getPropertyName(), _catalogFeatures.get(f)); |
|
} |
|
} catch (SAXNotRecognizedException e) { |
|
//shall not happen for internal settings |
|
} |
|
} |
|
return reader; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public synchronized void releaseXMLReader(XMLReader reader) { |
|
// If the reader that's being released is the cached reader |
|
|
|
ReaderWrapper rw = m_readers.get(); |
|
if (rw.reader == reader && reader != null) { |
|
m_inUse.remove(reader); |
|
} |
|
} |
|
|
|
|
|
*/ |
|
public boolean overrideDefaultParser() { |
|
return m_overrideDefaultParser; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setOverrideDefaultParser(boolean flag) { |
|
m_overrideDefaultParser = flag; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setFeature(String name, boolean value) { |
|
if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { |
|
_secureProcessing = value; |
|
} else if (XMLConstants.USE_CATALOG.equals(name)) { |
|
_useCatalog = value; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Object getProperty(String name) { |
|
if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { |
|
return _accessExternalDTD; |
|
} else if (name.equals(XalanConstants.SECURITY_MANAGER)) { |
|
return _xmlSecurityManager; |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setProperty(String name, Object value) { |
|
if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { |
|
_accessExternalDTD = (String)value; |
|
} else if (name.equals(XalanConstants.SECURITY_MANAGER)) { |
|
_xmlSecurityManager = (XMLSecurityManager)value; |
|
} else if (JdkXmlFeatures.CATALOG_FEATURES.equals(name)) { |
|
_catalogFeatures = (CatalogFeatures)value; |
|
} else if (JdkXmlUtils.CDATA_CHUNK_SIZE.equals(name)) { |
|
_cdataChunkSize = JdkXmlUtils.getValue(value, _cdataChunkSize); |
|
} |
|
} |
|
|
|
class ReaderWrapper { |
|
XMLReader reader; |
|
boolean overrideDefaultParser; |
|
|
|
public ReaderWrapper(XMLReader reader, boolean overrideDefaultParser) { |
|
this.reader = reader; |
|
this.overrideDefaultParser = overrideDefaultParser; |
|
} |
|
} |
|
} |