Path: blob/master/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java
40948 views
/*1* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package jdk.xml.internal;2526import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;27import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;28import com.sun.org.apache.xerces.internal.impl.Constants;29import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;30import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;31import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;32import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;33import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;34import javax.xml.XMLConstants;35import javax.xml.catalog.CatalogFeatures;36import javax.xml.catalog.CatalogFeatures.Feature;37import javax.xml.parsers.DocumentBuilderFactory;38import javax.xml.parsers.ParserConfigurationException;39import javax.xml.parsers.SAXParserFactory;40import javax.xml.transform.TransformerConfigurationException;41import javax.xml.transform.sax.SAXTransformerFactory;42import static jdk.xml.internal.JdkConstants.OVERRIDE_PARSER;43import org.w3c.dom.Document;44import org.xml.sax.SAXException;45import org.xml.sax.SAXNotRecognizedException;46import org.xml.sax.SAXNotSupportedException;47import org.xml.sax.XMLReader;4849/**50* Constants for use across JAXP processors.51*/52public class JdkXmlUtils {53private static final String DOM_FACTORY_ID = "javax.xml.parsers.DocumentBuilderFactory";54private static final String SAX_FACTORY_ID = "javax.xml.parsers.SAXParserFactory";55private static final String SAX_DRIVER = "org.xml.sax.driver";5657/**58* Xerces features59*/60public static final String NAMESPACES_FEATURE =61Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;62public static final String NAMESPACE_PREFIXES_FEATURE =63Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;646566/**67* Catalog features68*/69public final static String USE_CATALOG = XMLConstants.USE_CATALOG;70public final static String SP_USE_CATALOG = "javax.xml.useCatalog";71public final static String CATALOG_FILES = CatalogFeatures.Feature.FILES.getPropertyName();72public final static String CATALOG_DEFER = CatalogFeatures.Feature.DEFER.getPropertyName();73public final static String CATALOG_PREFER = CatalogFeatures.Feature.PREFER.getPropertyName();74public final static String CATALOG_RESOLVE = CatalogFeatures.Feature.RESOLVE.getPropertyName();75767778/**79* Default value of USE_CATALOG. This will read the System property80*/81public static final boolean USE_CATALOG_DEFAULT82= SecuritySupport.getJAXPSystemProperty(Boolean.class, SP_USE_CATALOG, "true");838485/**86* The system-default factory87*/88private static final SAXParserFactory defaultSAXFactory = getSAXFactory(false);8990/**91* Returns the value.92*93* @param value the specified value94* @param defValue the default value95* @return the value, or the default value if the value is null96*/97public static int getValue(Object value, int defValue) {98if (value == null) {99return defValue;100}101102if (value instanceof Number) {103return ((Number) value).intValue();104} else if (value instanceof String) {105return Integer.parseInt(String.valueOf(value));106} else {107throw new IllegalArgumentException("Unexpected class: "108+ value.getClass());109}110}111112/**113* Sets the XMLReader instance with the specified property if the the114* property is supported, ignores error if not, issues a warning if so115* requested.116*117* @param reader an XMLReader instance118* @param property the name of the property119* @param value the value of the property120* @param warn a flag indicating whether a warning should be issued121*/122public static void setXMLReaderPropertyIfSupport(XMLReader reader, String property,123Object value, boolean warn) {124try {125reader.setProperty(property, value);126} catch (SAXNotRecognizedException | SAXNotSupportedException e) {127if (warn) {128XMLSecurityManager.printWarning(reader.getClass().getName(),129property, e);130}131}132}133134/**135* Returns the value of a Catalog feature by the property name.136*137* @param features a CatalogFeatures instance138* @param name the name of a Catalog feature139* @return the value of a Catalog feature, null if the name does not match140* any feature supported by the Catalog.141*/142public static String getCatalogFeature(CatalogFeatures features, String name) {143for (Feature feature : Feature.values()) {144if (feature.getPropertyName().equals(name)) {145return features.get(feature);146}147}148return null;149}150151/**152* Creates an instance of a CatalogFeatures.153*154* @param defer the defer property defined in CatalogFeatures155* @param file the file path to a catalog156* @param prefer the prefer property defined in CatalogFeatures157* @param resolve the resolve property defined in CatalogFeatures158* @return a {@link javax.xml.transform.Source} object159*/160public static CatalogFeatures getCatalogFeatures(String defer, String file,161String prefer, String resolve) {162163CatalogFeatures.Builder builder = CatalogFeatures.builder();164if (file != null) {165builder = builder.with(CatalogFeatures.Feature.FILES, file);166}167if (prefer != null) {168builder = builder.with(CatalogFeatures.Feature.PREFER, prefer);169}170if (defer != null) {171builder = builder.with(CatalogFeatures.Feature.DEFER, defer);172}173if (resolve != null) {174builder = builder.with(CatalogFeatures.Feature.RESOLVE, resolve);175}176177return builder.build();178}179180/**181* Passing on the CatalogFeatures settings from one Xerces configuration182* object to another.183*184* @param config1 a Xerces configuration object185* @param config2 a Xerces configuration object186*/187public static void catalogFeaturesConfig2Config(XMLComponentManager config1,188ParserConfigurationSettings config2) {189boolean supportCatalog = true;190boolean useCatalog = config1.getFeature(XMLConstants.USE_CATALOG);191try {192config2.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);193} catch (XMLConfigurationException e) {194supportCatalog = false;195}196197if (supportCatalog && useCatalog) {198try {199for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {200config2.setProperty(f.getPropertyName(), config1.getProperty(f.getPropertyName()));201}202} catch (XMLConfigurationException e) {203//shall not happen for internal settings204}205}206}207208/**209* Passing on the CatalogFeatures settings from a Xerces configuration210* object to an XMLReader.211*212* @param config a Xerces configuration object213* @param reader an XMLReader214*/215public static void catalogFeaturesConfig2Reader(XMLComponentManager config, XMLReader reader) {216boolean supportCatalog = true;217boolean useCatalog = config.getFeature(XMLConstants.USE_CATALOG);218try {219reader.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);220} catch (SAXNotRecognizedException | SAXNotSupportedException e) {221supportCatalog = false;222}223224if (supportCatalog && useCatalog) {225try {226for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {227reader.setProperty(f.getPropertyName(), config.getProperty(f.getPropertyName()));228}229} catch (SAXNotRecognizedException | SAXNotSupportedException e) {230//shall not happen for internal settings231}232}233}234235/**236* Returns an XMLReader instance. If overrideDefaultParser is requested, use237* SAXParserFactory or XMLReaderFactory, otherwise use the system-default238* SAXParserFactory to locate an XMLReader.239*240* @param overrideDefaultParser a flag indicating whether a 3rd party's241* parser implementation may be used to override the system-default one242* @param secureProcessing a flag indicating whether secure processing is243* requested244* @param useXMLReaderFactory a flag indicating when the XMLReader should be245* created using XMLReaderFactory. True is a compatibility mode that honors246* the property org.xml.sax.driver (see JDK-6490921).247* @return an XMLReader instance248*/249public static XMLReader getXMLReader(boolean overrideDefaultParser,250boolean secureProcessing) {251SAXParserFactory saxFactory;252XMLReader reader = null;253String spSAXDriver = SecuritySupport.getSystemProperty(SAX_DRIVER);254if (spSAXDriver != null) {255reader = getXMLReaderWXMLReaderFactory();256} else if (overrideDefaultParser) {257reader = getXMLReaderWSAXFactory(overrideDefaultParser);258}259260if (reader != null) {261if (secureProcessing) {262try {263reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secureProcessing);264} catch (SAXException e) {265XMLSecurityManager.printWarning(reader.getClass().getName(),266XMLConstants.FEATURE_SECURE_PROCESSING, e);267}268}269try {270reader.setFeature(NAMESPACES_FEATURE, true);271reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false);272} catch (SAXException se) {273// older version of a parser274}275return reader;276}277278// use the system-default279saxFactory = defaultSAXFactory;280281try {282reader = saxFactory.newSAXParser().getXMLReader();283} catch (ParserConfigurationException | SAXException ex) {284// shall not happen with the system-default reader285}286return reader;287}288289/**290* Creates a system-default DOM Document.291*292* @return a DOM Document instance293*/294public static Document getDOMDocument() {295try {296DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(false);297return dbf.newDocumentBuilder().newDocument();298} catch (ParserConfigurationException pce) {299// can never happen with the system-default configuration300}301return null;302}303304/**305* Returns a DocumentBuilderFactory instance.306*307* @param overrideDefaultParser a flag indicating whether the system-default308* implementation may be overridden. If the system property of the309* DOM factory ID is set, override is always allowed.310*311* @return a DocumentBuilderFactory instance.312*/313@SuppressWarnings("removal")314public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) {315boolean override = overrideDefaultParser;316String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID);317318if (spDOMFactory != null && System.getSecurityManager() == null) {319override = true;320}321DocumentBuilderFactory dbf322= !override323? new DocumentBuilderFactoryImpl()324: DocumentBuilderFactory.newInstance();325dbf.setNamespaceAware(true);326// false is the default setting. This step here is for compatibility327dbf.setValidating(false);328return dbf;329}330331/**332* Returns a SAXParserFactory instance.333*334* @param overrideDefaultParser a flag indicating whether the system-default335* implementation may be overridden. If the system property of the336* DOM factory ID is set, override is always allowed.337*338* @return a SAXParserFactory instance.339*/340@SuppressWarnings("removal")341public static SAXParserFactory getSAXFactory(boolean overrideDefaultParser) {342boolean override = overrideDefaultParser;343String spSAXFactory = SecuritySupport.getJAXPSystemProperty(SAX_FACTORY_ID);344if (spSAXFactory != null && System.getSecurityManager() == null) {345override = true;346}347348SAXParserFactory factory349= !override350? new SAXParserFactoryImpl()351: SAXParserFactory.newInstance();352factory.setNamespaceAware(true);353return factory;354}355356public static SAXTransformerFactory getSAXTransformFactory(boolean overrideDefaultParser) {357SAXTransformerFactory tf = overrideDefaultParser358? (SAXTransformerFactory) SAXTransformerFactory.newInstance()359: (SAXTransformerFactory) new TransformerFactoryImpl();360try {361tf.setFeature(OVERRIDE_PARSER, overrideDefaultParser);362} catch (TransformerConfigurationException ex) {363// ignore since it'd never happen with the JDK impl.364}365return tf;366}367368private static XMLReader getXMLReaderWSAXFactory(boolean overrideDefaultParser) {369SAXParserFactory saxFactory = getSAXFactory(overrideDefaultParser);370try {371return saxFactory.newSAXParser().getXMLReader();372} catch (ParserConfigurationException | SAXException ex) {373return getXMLReaderWXMLReaderFactory();374}375}376377@SuppressWarnings("deprecation")378private static XMLReader getXMLReaderWXMLReaderFactory() {379try {380return org.xml.sax.helpers.XMLReaderFactory.createXMLReader();381} catch (SAXException ex1) {382}383return null;384}385}386387388