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      * Values for a feature
  56      */
  57     public static final String FEATURE_TRUE = "true";
  58     public static final String FEATURE_FALSE = "false";
  59 
  60     /**
  61      * Default value of USE_CATALOG. This will read the System property
  62      */
  63     public static final boolean USE_CATALOG_DEFAULT
  64             = SecuritySupport.getJAXPSystemProperty(Boolean.class, SP_USE_CATALOG, "true");
  65 
  66     /**
  67      * JDK features (will be consolidated in the next major feature revamp
  68      */
  69     public final static String CDATA_CHUNK_SIZE = "jdk.xml.cdataChunkSize";
  70     public static final int CDATA_CHUNK_SIZE_DEFAULT
  71             = SecuritySupport.getJAXPSystemProperty(Integer.class, CDATA_CHUNK_SIZE, "0");
  72 
  73     /**
  74      * Returns the value.
  75      *
  76      * @param value the specified value
  77      * @param defValue the default value
  78      * @return the value, or the default value if the value is null
  79      */
  80     public static int getValue(Object value, int defValue) {
  81         if (value == null) {
  82             return defValue;
  83         }
  84 
  85         if (value instanceof Number) {
  86             return ((Number) value).intValue();
  87         } else if (value instanceof String) {
  88             return Integer.parseInt(String.valueOf(value));
  89         } else {
  90             throw new IllegalArgumentException("Unexpected class: "
  91                     + value.getClass());
  92         }
  93     }
  94 
  95     /**
  96      * Sets the XMLReader instance with the specified property if the the
  97      * property is supported, ignores error if not, issues a warning if so
  98      * requested.
  99      *
 100      * @param reader an XMLReader instance
 101      * @param property the name of the property
 102      * @param value the value of the property
 103      * @param warn a flag indicating whether a warning should be issued
 104      */
 105     public static void setXMLReaderPropertyIfSupport(XMLReader reader, String property,
 106             Object value, boolean warn) {
 107         try {
 108             reader.setProperty(property, value);
 109         } catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 110             if (warn) {
 111                 XMLSecurityManager.printWarning(reader.getClass().getName(),
 112                         property, e);
 113             }
 114         }
 115     }
 116 
 117     /**
 118      * Returns the value of a Catalog feature by the property name.
 119      *
 120      * @param features a CatalogFeatures instance
 121      * @param name the name of a Catalog feature
 122      * @return the value of a Catalog feature, null if the name does not match
 123      * any feature supported by the Catalog.
 124      */
 125     public static String getCatalogFeature(CatalogFeatures features, String name) {
 126         for (Feature feature : Feature.values()) {
 127             if (feature.getPropertyName().equals(name)) {
 128                 return features.get(feature);
 129             }
 130         }
 131         return null;
 132     }
 133 
 134     /**
 135      * Creates an instance of a CatalogFeatures.
 136      *
 137      * @param defer the defer property defined in CatalogFeatures
 138      * @param file the file path to a catalog
 139      * @param prefer the prefer property defined in CatalogFeatures
 140      * @param resolve the resolve property defined in CatalogFeatures
 141      * @return a {@link javax.xml.transform.Source} object
 142      */
 143     public static CatalogFeatures getCatalogFeatures(String defer, String file,
 144             String prefer, String resolve) {
 145 
 146         CatalogFeatures.Builder builder = CatalogFeatures.builder();
 147         if (file != null) {
 148             builder = builder.with(CatalogFeatures.Feature.FILES, file);
 149         }
 150         if (prefer != null) {
 151             builder = builder.with(CatalogFeatures.Feature.PREFER, prefer);
 152         }
 153         if (defer != null) {
 154             builder = builder.with(CatalogFeatures.Feature.DEFER, defer);
 155         }
 156         if (resolve != null) {
 157             builder = builder.with(CatalogFeatures.Feature.RESOLVE, resolve);
 158         }
 159 
 160         return builder.build();
 161     }
 162 
 163     /**
 164      * Passing on the CatalogFeatures settings from one Xerces configuration
 165      * object to another.
 166      *
 167      * @param config1 a Xerces configuration object
 168      * @param config2 a Xerces configuration object
 169      */
 170     public static void catalogFeaturesConfig2Config(XMLComponentManager config1,
 171             ParserConfigurationSettings config2) {
 172         boolean supportCatalog = true;
 173         boolean useCatalog = config1.getFeature(XMLConstants.USE_CATALOG);
 174         try {
 175             config2.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);
 176         } catch (XMLConfigurationException e) {
 177             supportCatalog = false;
 178         }
 179 
 180         if (supportCatalog && useCatalog) {
 181             try {
 182                 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
 183                     config2.setProperty(f.getPropertyName(), config1.getProperty(f.getPropertyName()));
 184                 }
 185             } catch (XMLConfigurationException e) {
 186                 //shall not happen for internal settings
 187             }
 188         }
 189     }
 190 
 191     /**
 192      * Passing on the CatalogFeatures settings from a Xerces configuration
 193      * object to an XMLReader.
 194      *
 195      * @param config a Xerces configuration object
 196      * @param reader an XMLReader
 197      */
 198     public static void catalogFeaturesConfig2Reader(XMLComponentManager config, XMLReader reader) {
 199         boolean supportCatalog = true;
 200         boolean useCatalog = config.getFeature(XMLConstants.USE_CATALOG);
 201         try {
 202             reader.setFeature(JdkXmlUtils.USE_CATALOG, useCatalog);
 203         } catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 204             supportCatalog = false;
 205         }
 206 
 207         if (supportCatalog && useCatalog) {
 208             try {
 209                 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
 210                     reader.setProperty(f.getPropertyName(), config.getProperty(f.getPropertyName()));
 211                 }
 212             } catch (SAXNotRecognizedException | SAXNotSupportedException e) {
 213                 //shall not happen for internal settings
 214             }
 215         }
 216     }
 217 }