1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.xml.internal;
  27 
  28 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
  29 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
  30 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  31 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  32 import javax.xml.XMLConstants;
  33 import javax.xml.catalog.CatalogFeatures;
  34 import javax.xml.catalog.CatalogFeatures.Feature;
  35 import org.xml.sax.SAXNotRecognizedException;
  36 import org.xml.sax.SAXNotSupportedException;
  37 import org.xml.sax.XMLReader;
  38 
  39 /**
  40  * Constants for use across JAXP processors.
  41  */
  42 public class JdkXmlUtils {
  43 
  44     /**
  45      * Catalog features
  46      */
  47     public final static String USE_CATALOG = XMLConstants.USE_CATALOG;
  48     public final static String SP_USE_CATALOG = "javax.xml.useCatalog";
  49     public final static String CATALOG_FILES = CatalogFeatures.Feature.FILES.getPropertyName();
  50     public final static String CATALOG_DEFER = CatalogFeatures.Feature.DEFER.getPropertyName();
  51     public final static String CATALOG_PREFER = CatalogFeatures.Feature.PREFER.getPropertyName();
  52     public final static String CATALOG_RESOLVE = CatalogFeatures.Feature.RESOLVE.getPropertyName();
  53 
  54     /**
  55      * Reset SymbolTable feature
  56      * System property name is identical to feature name
  57      */
  58     public final static String RESET_SYMBOL_TABLE = "jdk.xml.resetSymbolTable";
  59 
  60     /**
  61      * Values for a feature
  62      */
  63     public static final String FEATURE_TRUE = "true";
  64     public static final String FEATURE_FALSE = "false";
  65 
  66     /**
  67      * Default value of USE_CATALOG. This will read the System property
  68      */
  69     public static final boolean USE_CATALOG_DEFAULT
  70             = SecuritySupport.getJAXPSystemProperty(Boolean.class, SP_USE_CATALOG, "true");
  71 
  72     /**
  73      * Default value of RESET_SYMBOL_TABLE. This will read the System property
  74      */
  75     public static final boolean RESET_SYMBOL_TABLE_DEFAULT
  76             = SecuritySupport.getJAXPSystemProperty(Boolean.class, RESET_SYMBOL_TABLE, "false");
  77 
  78 
  79     /**
  80      * JDK features (will be consolidated in the next major feature revamp
  81      */
  82     public final static String CDATA_CHUNK_SIZE = "jdk.xml.cdataChunkSize";
  83     public static final int CDATA_CHUNK_SIZE_DEFAULT
  84             = SecuritySupport.getJAXPSystemProperty(Integer.class, CDATA_CHUNK_SIZE, "0");
  85 
  86     /**
  87      * Returns the value.
  88      *
  89      * @param value the specified value
  90      * @param defValue the default value
  91      * @return the value, or the default value if the value is null
  92      */
  93     public static int getValue(Object value, int defValue) {
  94         if (value == null) {
  95             return defValue;
  96         }
  97 
  98         if (value instanceof Number) {
  99             return ((Number) value).intValue();
 100         } else if (value instanceof String) {
 101             return Integer.parseInt(String.valueOf(value));
 102         } else {
 103             throw new IllegalArgumentException("Unexpected class: "
 104                     + value.getClass());
 105         }
 106     }
 107 
 108     /**
 109      * Sets the XMLReader instance with the specified property if the the
 110      * property is supported, ignores error if not, issues a warning if so
 111      * requested.
 112      *
 113      * @param reader an XMLReader instance
 114      * @param property the name of the property
 115      * @param value the value of the property
 116      * @param warn a flag indicating whether a warning should be issued
 117      */
 118     public static void setXMLReaderPropertyIfSupport(XMLReader reader, String property,
 119             Object value, boolean warn) {
 120         try {
 121             reader.setProperty(property, value);
 122         } catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 123             if (warn) {
 124                 XMLSecurityManager.printWarning(reader.getClass().getName(),
 125                         property, e);
 126             }
 127         }
 128     }
 129 
 130     /**
 131      * Returns the value of a Catalog feature by the property name.
 132      *
 133      * @param features a CatalogFeatures instance
 134      * @param name the name of a Catalog feature
 135      * @return the value of a Catalog feature, null if the name does not match
 136      * any feature supported by the Catalog.
 137      */
 138     public static String getCatalogFeature(CatalogFeatures features, String name) {
 139         for (Feature feature : Feature.values()) {
 140             if (feature.getPropertyName().equals(name)) {
 141                 return features.get(feature);
 142             }
 143         }
 144         return null;
 145     }
 146 
 147     /**
 148      * Creates an instance of a CatalogFeatures.
 149      *
 150      * @param defer the defer property defined in CatalogFeatures
 151      * @param file the file path to a catalog
 152      * @param prefer the prefer property defined in CatalogFeatures
 153      * @param resolve the resolve property defined in CatalogFeatures
 154      * @return a {@link javax.xml.transform.Source} object
 155      */
 156     public static CatalogFeatures getCatalogFeatures(String defer, String file,
 157             String prefer, String resolve) {
 158 
 159         CatalogFeatures.Builder builder = CatalogFeatures.builder();
 160         if (file != null) {
 161             builder = builder.with(CatalogFeatures.Feature.FILES, file);
 162         }
 163         if (prefer != null) {
 164             builder = builder.with(CatalogFeatures.Feature.PREFER, prefer);
 165         }
 166         if (defer != null) {
 167             builder = builder.with(CatalogFeatures.Feature.DEFER, defer);
 168         }
 169         if (resolve != null) {
 170             builder = builder.with(CatalogFeatures.Feature.RESOLVE, resolve);
 171         }
 172 
 173         return builder.build();
 174     }
 175 
 176     /**
 177      * Passing on the CatalogFeatures settings from one Xerces configuration
 178      * object to another.
 179      *
 180      * @param config1 a Xerces configuration object
 181      * @param config2 a Xerces configuration object
 182      */
 183     public static void catalogFeaturesConfig2Config(XMLComponentManager config1,
 184             ParserConfigurationSettings config2) {
 185         boolean supportCatalog = true;
 186         boolean useCatalog = config1.getFeature(XMLConstants.USE_CATALOG);
 187         try {
 188             config2.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);
 189         } catch (XMLConfigurationException e) {
 190             supportCatalog = false;
 191         }
 192 
 193         if (supportCatalog && useCatalog) {
 194             try {
 195                 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
 196                     config2.setProperty(f.getPropertyName(), config1.getProperty(f.getPropertyName()));
 197                 }
 198             } catch (XMLConfigurationException e) {
 199                 //shall not happen for internal settings
 200             }
 201         }
 202     }
 203 
 204     /**
 205      * Passing on the CatalogFeatures settings from a Xerces configuration
 206      * object to an XMLReader.
 207      *
 208      * @param config a Xerces configuration object
 209      * @param reader an XMLReader
 210      */
 211     public static void catalogFeaturesConfig2Reader(XMLComponentManager config, XMLReader reader) {
 212         boolean supportCatalog = true;
 213         boolean useCatalog = config.getFeature(XMLConstants.USE_CATALOG);
 214         try {
 215             reader.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);
 216         } catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 217             supportCatalog = false;
 218         }
 219 
 220         if (supportCatalog && useCatalog) {
 221             try {
 222                 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
 223                     reader.setProperty(f.getPropertyName(), config.getProperty(f.getPropertyName()));
 224                 }
 225             } catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 226                 //shall not happen for internal settings
 227             }
 228         }
 229     }
 230 }