Path: blob/master/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java
67862 views
/*1* Copyright (c) 2016, 2022, 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.xsltc.trax.TransformerFactoryImpl;27import com.sun.org.apache.xerces.internal.impl.Constants;28import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;29import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;30import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;31import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;32import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;33import javax.xml.XMLConstants;34import javax.xml.catalog.CatalogFeatures;35import javax.xml.catalog.CatalogFeatures.Feature;36import javax.xml.parsers.DocumentBuilderFactory;37import javax.xml.parsers.ParserConfigurationException;38import javax.xml.parsers.SAXParserFactory;39import javax.xml.transform.TransformerConfigurationException;40import javax.xml.transform.sax.SAXTransformerFactory;41import static jdk.xml.internal.JdkConstants.OVERRIDE_PARSER;42import org.w3c.dom.Document;43import org.xml.sax.SAXException;44import org.xml.sax.SAXNotRecognizedException;45import org.xml.sax.SAXNotSupportedException;46import org.xml.sax.XMLReader;4748/**49* Constants for use across JAXP processors.50*/51public class JdkXmlUtils {52private static final String DOM_FACTORY_ID = "javax.xml.parsers.DocumentBuilderFactory";53private static final String SAX_FACTORY_ID = "javax.xml.parsers.SAXParserFactory";54private static final String SAX_DRIVER = "org.xml.sax.driver";5556/**57* Xerces features58*/59public static final String NAMESPACES_FEATURE =60Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;61public static final String NAMESPACE_PREFIXES_FEATURE =62Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;636465/**66* Catalog features67*/68public final static String USE_CATALOG = XMLConstants.USE_CATALOG;69public final static String SP_USE_CATALOG = "javax.xml.useCatalog";70public final static String CATALOG_FILES = CatalogFeatures.Feature.FILES.getPropertyName();71public final static String CATALOG_DEFER = CatalogFeatures.Feature.DEFER.getPropertyName();72public final static String CATALOG_PREFER = CatalogFeatures.Feature.PREFER.getPropertyName();73public final static String CATALOG_RESOLVE = CatalogFeatures.Feature.RESOLVE.getPropertyName();74757677/**78* Default value of USE_CATALOG. This will read the System property79*/80public static final boolean USE_CATALOG_DEFAULT81= SecuritySupport.getJAXPSystemProperty(Boolean.class, SP_USE_CATALOG, "true");828384/**85* The system-default factory86*/87private static final SAXParserFactory defaultSAXFactory = getSAXFactory(false);8889/**90* Returns the value.91*92* @param value the specified value93* @param defValue the default value94* @return the value, or the default value if the value is null95*/96public static int getValue(Object value, int defValue) {97if (value == null) {98return defValue;99}100101if (value instanceof Number) {102return ((Number) value).intValue();103} else if (value instanceof String) {104return Integer.parseInt(String.valueOf(value));105} else {106throw new IllegalArgumentException("Unexpected class: "107+ value.getClass());108}109}110111/**112* Sets the XMLReader instance with the specified property if the the113* property is supported, ignores error if not, issues a warning if so114* requested.115*116* @param reader an XMLReader instance117* @param property the name of the property118* @param value the value of the property119* @param warn a flag indicating whether a warning should be issued120*/121public static void setXMLReaderPropertyIfSupport(XMLReader reader, String property,122Object value, boolean warn) {123try {124reader.setProperty(property, value);125} catch (SAXNotRecognizedException | SAXNotSupportedException e) {126if (warn) {127XMLSecurityManager.printWarning(reader.getClass().getName(),128property, e);129}130}131}132133/**134* Returns the value of a Catalog feature by the property name.135*136* @param features a CatalogFeatures instance137* @param name the name of a Catalog feature138* @return the value of a Catalog feature, null if the name does not match139* any feature supported by the Catalog.140*/141public static String getCatalogFeature(CatalogFeatures features, String name) {142for (Feature feature : Feature.values()) {143if (feature.getPropertyName().equals(name)) {144return features.get(feature);145}146}147return null;148}149150/**151* Creates an instance of a CatalogFeatures.152*153* @param defer the defer property defined in CatalogFeatures154* @param file the file path to a catalog155* @param prefer the prefer property defined in CatalogFeatures156* @param resolve the resolve property defined in CatalogFeatures157* @return a {@link javax.xml.transform.Source} object158*/159public static CatalogFeatures getCatalogFeatures(String defer, String file,160String prefer, String resolve) {161162CatalogFeatures.Builder builder = CatalogFeatures.builder();163if (file != null) {164builder = builder.with(CatalogFeatures.Feature.FILES, file);165}166if (prefer != null) {167builder = builder.with(CatalogFeatures.Feature.PREFER, prefer);168}169if (defer != null) {170builder = builder.with(CatalogFeatures.Feature.DEFER, defer);171}172if (resolve != null) {173builder = builder.with(CatalogFeatures.Feature.RESOLVE, resolve);174}175176return builder.build();177}178179/**180* Passing on the CatalogFeatures settings from one Xerces configuration181* object to another.182*183* @param config1 a Xerces configuration object184* @param config2 a Xerces configuration object185*/186public static void catalogFeaturesConfig2Config(XMLComponentManager config1,187ParserConfigurationSettings config2) {188boolean supportCatalog = true;189boolean useCatalog = config1.getFeature(XMLConstants.USE_CATALOG);190try {191config2.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);192} catch (XMLConfigurationException e) {193supportCatalog = false;194}195196if (supportCatalog && useCatalog) {197try {198for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {199config2.setProperty(f.getPropertyName(), config1.getProperty(f.getPropertyName()));200}201} catch (XMLConfigurationException e) {202//shall not happen for internal settings203}204}205}206207/**208* Passing on the CatalogFeatures settings from a Xerces configuration209* object to an XMLReader.210*211* @param config a Xerces configuration object212* @param reader an XMLReader213*/214public static void catalogFeaturesConfig2Reader(XMLComponentManager config, XMLReader reader) {215boolean supportCatalog = true;216boolean useCatalog = config.getFeature(XMLConstants.USE_CATALOG);217try {218reader.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);219} catch (SAXNotRecognizedException | SAXNotSupportedException e) {220supportCatalog = false;221}222223if (supportCatalog && useCatalog) {224try {225for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {226reader.setProperty(f.getPropertyName(), config.getProperty(f.getPropertyName()));227}228} catch (SAXNotRecognizedException | SAXNotSupportedException e) {229//shall not happen for internal settings230}231}232}233234/**235* Returns an XMLReader instance. If overrideDefaultParser is requested, use236* SAXParserFactory or XMLReaderFactory, otherwise use the system-default237* SAXParserFactory to locate an XMLReader.238*239* @param overrideDefaultParser a flag indicating whether a 3rd party's240* parser implementation may be used to override the system-default one241* @param secureProcessing a flag indicating whether secure processing is242* requested243* @param useXMLReaderFactory a flag indicating when the XMLReader should be244* created using XMLReaderFactory. True is a compatibility mode that honors245* the property org.xml.sax.driver (see JDK-6490921).246* @return an XMLReader instance247*/248public static XMLReader getXMLReader(boolean overrideDefaultParser,249boolean secureProcessing) {250SAXParserFactory saxFactory;251XMLReader reader = null;252String spSAXDriver = SecuritySupport.getSystemProperty(SAX_DRIVER);253if (spSAXDriver != null) {254reader = getXMLReaderWXMLReaderFactory();255} else if (overrideDefaultParser) {256reader = getXMLReaderWSAXFactory(overrideDefaultParser);257}258259if (reader != null) {260if (secureProcessing) {261try {262reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secureProcessing);263} catch (SAXException e) {264XMLSecurityManager.printWarning(reader.getClass().getName(),265XMLConstants.FEATURE_SECURE_PROCESSING, e);266}267}268try {269reader.setFeature(NAMESPACES_FEATURE, true);270reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false);271} catch (SAXException se) {272// older version of a parser273}274return reader;275}276277// use the system-default278saxFactory = defaultSAXFactory;279280try {281reader = saxFactory.newSAXParser().getXMLReader();282} catch (ParserConfigurationException | SAXException ex) {283// shall not happen with the system-default reader284}285return reader;286}287288/**289* Creates a system-default DOM Document.290*291* @return a DOM Document instance292*/293public static Document getDOMDocument() {294try {295DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(false);296return dbf.newDocumentBuilder().newDocument();297} catch (ParserConfigurationException pce) {298// can never happen with the system-default configuration299}300return null;301}302303/**304* Returns a DocumentBuilderFactory instance.305*306* @param overrideDefaultParser a flag indicating whether the system-default307* implementation may be overridden. If the system property of the308* DOM factory ID is set, override is always allowed.309*310* @return a DocumentBuilderFactory instance.311*/312@SuppressWarnings("removal")313public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) {314boolean override = overrideDefaultParser;315String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID);316317if (spDOMFactory != null && System.getSecurityManager() == null) {318override = true;319}320DocumentBuilderFactory dbf321= !override322? new DocumentBuilderFactoryImpl()323: DocumentBuilderFactory.newInstance();324dbf.setNamespaceAware(true);325// false is the default setting. This step here is for compatibility326dbf.setValidating(false);327return dbf;328}329330/**331* Returns a SAXParserFactory instance.332*333* @param overrideDefaultParser a flag indicating whether the system-default334* implementation may be overridden. If the system property of the335* DOM factory ID is set, override is always allowed.336*337* @return a SAXParserFactory instance.338*/339@SuppressWarnings("removal")340public static SAXParserFactory getSAXFactory(boolean overrideDefaultParser) {341boolean override = overrideDefaultParser;342String spSAXFactory = SecuritySupport.getJAXPSystemProperty(SAX_FACTORY_ID);343if (spSAXFactory != null && System.getSecurityManager() == null) {344override = true;345}346347SAXParserFactory factory348= !override349? new SAXParserFactoryImpl()350: SAXParserFactory.newInstance();351factory.setNamespaceAware(true);352return factory;353}354355public static SAXTransformerFactory getSAXTransformFactory(boolean overrideDefaultParser) {356SAXTransformerFactory tf = overrideDefaultParser357? (SAXTransformerFactory) SAXTransformerFactory.newInstance()358: (SAXTransformerFactory) new TransformerFactoryImpl();359try {360tf.setFeature(OVERRIDE_PARSER, overrideDefaultParser);361} catch (TransformerConfigurationException ex) {362// ignore since it'd never happen with the JDK impl.363}364return tf;365}366367/**368* Returns the external declaration for a DTD construct.369*370* @param publicId the public identifier371* @param systemId the system identifier372* @return a DTD external declaration373*/374public static String getDTDExternalDecl(String publicId, String systemId) {375StringBuilder sb = new StringBuilder();376if (null != publicId) {377sb.append(" PUBLIC ");378sb.append(quoteString(publicId));379}380381if (null != systemId) {382if (null == publicId) {383sb.append(" SYSTEM ");384} else {385sb.append(" ");386}387388sb.append(quoteString(systemId));389}390return sb.toString();391}392393/**394* Returns the input string quoted with double quotes or single ones if395* there is a double quote in the string.396* @param s the input string, can not be null397* @return the quoted string398*/399private static String quoteString(String s) {400char c = (s.indexOf('"') > -1) ? '\'' : '"';401return c + s + c;402}403404private static XMLReader getXMLReaderWSAXFactory(boolean overrideDefaultParser) {405SAXParserFactory saxFactory = getSAXFactory(overrideDefaultParser);406try {407return saxFactory.newSAXParser().getXMLReader();408} catch (ParserConfigurationException | SAXException ex) {409return getXMLReaderWXMLReaderFactory();410}411}412413@SuppressWarnings("deprecation")414private static XMLReader getXMLReaderWXMLReaderFactory() {415try {416return org.xml.sax.helpers.XMLReaderFactory.createXMLReader();417} catch (SAXException ex1) {418}419return null;420}421}422423424