--- old/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/OutputPropertiesFactory.java 2019-02-13 12:30:44.900557521 -0800 +++ new/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/OutputPropertiesFactory.java 2019-02-13 12:30:44.099484259 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,15 +20,6 @@ package com.sun.org.apache.xml.internal.serializer; -import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; -import com.sun.org.apache.xml.internal.serializer.utils.Utils; -import com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Enumeration; import java.util.Properties; import javax.xml.transform.OutputKeys; import jdk.xml.internal.SecuritySupport; @@ -68,18 +59,18 @@ * of the corresponding character, like this one:
quot=34
* *
  • S_USE_URL_ESCAPING - - * This non-standard property key is used to set a value of "yes" if the href values for HTML serialization should - * use %xx escaping. + * This non-standard property key is used to set a value of "yes" if the href values + * for HTML serialization should use %xx escaping. * *
  • S_OMIT_META_TAG - - * This non-standard property key is used to set a value of "yes" if the META tag should be omitted where it would - * otherwise be supplied. + * This non-standard property key is used to set a value of "yes" if the META tag + * should be omitted where it would otherwise be supplied. * * * @see SerializerFactory * @see Method * @see Serializer - * @LastModified: Oct 2017 + * @LastModified: Feb 2019 */ public final class OutputPropertiesFactory { @@ -147,14 +138,15 @@ S_BUILTIN_EXTENSIONS_UNIVERSAL + "entities"; /** - * This non-standard property key is used to set a value of "yes" if the href values for HTML serialization should - * use %xx escaping. */ + * This non-standard property key is used to set a value of "yes" if the href + * values for HTML serialization should use %xx escaping. + */ public static final String S_USE_URL_ESCAPING = S_BUILTIN_EXTENSIONS_UNIVERSAL + "use-url-escaping"; /** - * This non-standard property key is used to set a value of "yes" if the META tag should be omitted where it would - * otherwise be supplied. + * This non-standard property key is used to set a value of "yes" if the META + * tag should be omitted where it would otherwise be supplied. */ public static final String S_OMIT_META_TAG = S_BUILTIN_EXTENSIONS_UNIVERSAL + "omit-meta-tag"; @@ -174,53 +166,133 @@ S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL.length(); /** - * This non-standard, Oracle-impl only property key is used as if OutputKeys.STANDALONE is specified but - * without writing it out in the declaration; It can be used to reverse the change by Xalan patch 1495. - * Since Xalan patch 1495 can cause incompatible behavior, this property is add for application to neutralize - * the effect of Xalan patch 1495 - */ - /** - *

    Is Standalone

    - * - * - */ + * This non-standard, Oracle-impl only property key is used as if + * OutputKeys.STANDALONE is specified but without writing it out in the declaration; + * It can be used to reverse the change by Xalan patch 1495. + * Since Xalan patch 1495 can cause incompatible behavior, this property is + * added for application to neutralize the effect of Xalan patch 1495 + */ + /** + *

    Is Standalone

    + * + * + */ public static final String ORACLE_IS_STANDALONE = "http://www.oracle.com/xml/is-standalone"; //************************************************************ //* PRIVATE CONSTANTS //************************************************************ - private static final String S_XSLT_PREFIX = "xslt.output."; - private static final int S_XSLT_PREFIX_LEN = S_XSLT_PREFIX.length(); - private static final String S_XALAN_PREFIX = "org.apache.xslt."; - private static final int S_XALAN_PREFIX_LEN = S_XALAN_PREFIX.length(); - - /** Synchronization object for lazy initialization of the above tables. */ - private static final Object m_synch_object = new Object(); - - /** the directory in which the various method property files are located */ - private static final String PROP_DIR = "com/sun/org/apache/xml/internal/serializer/"; - /** property file for default XML properties */ - private static final String PROP_FILE_XML = "output_xml.properties"; - /** property file for default TEXT properties */ - private static final String PROP_FILE_TEXT = "output_text.properties"; - /** property file for default HTML properties */ - private static final String PROP_FILE_HTML = "output_html.properties"; - /** property file for default UNKNOWN (Either XML or HTML, to be determined later) properties */ - private static final String PROP_FILE_UNKNOWN = "output_unknown.properties"; + /* + * XSLT properties do not need namespace qualification. + * + * Xalan-specific output properties can be overridden in the stylesheet + * assigning a xalan namespace. For example: + * + * + * ... + */ + private static final String[] PROP_XML = { + "method", + "version", + "encoding", + "indent", + "omit-xml-declaration", + "standalone", + "media-type", + "{http://xml.apache.org/xalan}indent-amount", + "{http://xml.apache.org/xalan}content-handler", + "{http://xml.apache.org/xalan}entities" + }; + + private static final String[] PROP_XML_VALUE = { + "xml", + "1.0", + "UTF-8", + "no", + "no", + "no", + "text/xml", + "0", + "com.sun.org.apache.xml.internal.serializer.ToXMLStream", + "com/sun/org/apache/xml/internal/serializer/XMLEntities" + }; + + private static final String[] PROP_HTML = { + "method", + "indent", + "media", + "version", + "{http://xml.apache.org/xalan}indent-amount", + "{http://xml.apache.org/xalan}content-handler", + "{http://xml.apache.org/xalan}entities", + "{http://xml.apache.org/xalan}use-url-escaping", + "{http://xml.apache.org/xalan}omit-meta-tag" + }; + + private static final String[] PROP_HTML_VALUE = { + "html", + "yes", + "text/html", + "4.0", + "4", + "com.sun.org.apache.xml.internal.serializer.ToHTMLStream", + "com/sun/org/apache/xml/internal/serializer/HTMLEntities", + "yes", + "no" + }; + + private static final String[] PROP_TEXT = { + "method", + "media-type", + "{http://xml.apache.org/xalan}content-handler" + }; + + private static final String[] PROP_TEXT_VALUE = { + "text", + "text/plain", + "com.sun.org.apache.xml.internal.serializer.ToTextStream" + }; + + private static final String[] PROP_UNKNOWN = { + "method", + "version", + "encoding", + "indent", + "omit-xml-declaration", + "standalone", + "media-type", + "{http://xml.apache.org/xalan}indent-amount", + "{http://xml.apache.org/xalan}content-handler" + }; + + private static final String[] PROP_UNKNOWN_VALUE = { + "xml", + "1.0", + "UTF-8", + "no", + "no", + "no", + "text/xml", + "0", + "com.sun.org.apache.xml.internal.serializer.ToUnknownStream", + }; //************************************************************ //* PRIVATE STATIC FIELDS //************************************************************ - /** The default properties of all output files. */ + /** The default properties for all other than html and text. */ private static Properties m_xml_properties = null; /** The default properties when method="html". */ @@ -232,38 +304,8 @@ /** The properties when method="" for the "unknown" wrapper */ private static Properties m_unknown_properties = null; - private static final Class - ACCESS_CONTROLLER_CLASS = findAccessControllerClass(); - - private static Class findAccessControllerClass() { - try - { - // This Class was introduced in JDK 1.2. With the re-architecture of - // security mechanism ( starting in JDK 1.2 ), we have option of - // giving privileges to certain part of code using doPrivileged block. - // In JDK1.1.X applications won't be having security manager and if - // there is security manager ( in applets ), code need to be signed - // and trusted for having access to resources. - - return Class.forName("java.security.AccessController"); - } - catch (Exception e) - { - //User may be using older JDK ( JDK <1.2 ). Allow him/her to use it. - // But don't try to use doPrivileged - } - - return null; - } - /** - * Creates an empty OutputProperties with the property key/value defaults specified by - * a property file. The method argument is used to construct a string of - * the form output_[method].properties (for instance, output_html.properties). - * The output_xml.properties file is always used as the base. - * - *

    Anything other than 'text', 'xml', and 'html', will - * use the output_xml.properties file.

    + * Returns a Properties based on the specified method. The default is xml. * * @param method non-null reference to method name. * @@ -271,265 +313,71 @@ */ static public final Properties getDefaultMethodProperties(String method) { - String fileName = null; Properties defaultProperties = null; - // According to this article : Double-check locking does not work - // http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-toolbox.html - try - { - synchronized (m_synch_object) - { - if (null == m_xml_properties) // double check - { - fileName = PROP_FILE_XML; - m_xml_properties = loadPropertiesFile(fileName, null); - } - } - if (method.equals(Method.XML)) - { + if (null == m_xml_properties) { + m_xml_properties = initProperties(PROP_XML, PROP_XML_VALUE, null); + } + + + switch (method) { + case Method.XML: defaultProperties = m_xml_properties; - } - else if (method.equals(Method.HTML)) - { - if (null == m_html_properties) // double check - { - fileName = PROP_FILE_HTML; - m_html_properties = - loadPropertiesFile(fileName, m_xml_properties); + break; + case Method.HTML: + if (null == m_html_properties) { + m_html_properties = initProperties( + PROP_HTML, PROP_HTML_VALUE, m_xml_properties); } - defaultProperties = m_html_properties; - } - else if (method.equals(Method.TEXT)) - { - if (null == m_text_properties) // double check - { - fileName = PROP_FILE_TEXT; - m_text_properties = - loadPropertiesFile(fileName, m_xml_properties); - if (null - == m_text_properties.getProperty(OutputKeys.ENCODING)) + break; + case Method.TEXT: + if (null == m_text_properties) { + m_text_properties = initProperties( + PROP_TEXT, PROP_TEXT_VALUE, m_xml_properties); + + if (null == m_text_properties.getProperty(OutputKeys.ENCODING)) { String mimeEncoding = Encodings.getMimeEncoding(null); - m_text_properties.put( - OutputKeys.ENCODING, - mimeEncoding); + m_text_properties.put(OutputKeys.ENCODING, mimeEncoding); } } - defaultProperties = m_text_properties; - } - else if (method.equals(com.sun.org.apache.xml.internal.serializer.Method.UNKNOWN)) - { - if (null == m_unknown_properties) // double check - { - fileName = PROP_FILE_UNKNOWN; - m_unknown_properties = - loadPropertiesFile(fileName, m_xml_properties); + break; + case com.sun.org.apache.xml.internal.serializer.Method.UNKNOWN: + if (null == m_unknown_properties) { + m_unknown_properties = initProperties( + PROP_UNKNOWN, PROP_UNKNOWN_VALUE, m_xml_properties); } - defaultProperties = m_unknown_properties; - } - else - { - // TODO: Calculate res file from name. + break; + default: defaultProperties = m_xml_properties; - } - } - catch (IOException ioe) - { - throw new WrappedRuntimeException( - Utils.messages.createMessage( - MsgKey.ER_COULD_NOT_LOAD_METHOD_PROPERTY, - new Object[] { fileName, method }), - ioe); + break; } + // wrap these cached defaultProperties in a new Property object just so // that the caller of this method can't modify the default values return new Properties(defaultProperties); } /** - * Load the properties file from a resource stream. If a - * key name such as "org.apache.xslt.xxx", fix up the start of - * string to be a curly namespace. If a key name starts with - * "xslt.output.xxx", clip off "xslt.output.". If a key name *or* a - * key value is discovered, check for \u003a in the text, and - * fix it up to be ":", since earlier versions of the JDK do not - * handle the escape sequence (at least in key names). + * Initiates the properties * - * @param resourceName non-null reference to resource name. + * @param keys an array of keys + * @param values values corresponding to the keys * @param defaults Default properties, which may be null. */ - static private Properties loadPropertiesFile( - final String resourceName, - Properties defaults) - throws IOException + static private Properties initProperties(String[] keys, String[] values, Properties defaults) { - - // This static method should eventually be moved to a thread-specific class - // so that we can cache the ContextClassLoader and bottleneck all properties file - // loading throughout Xalan. - Properties props = new Properties(defaults); - InputStream is = null; - BufferedInputStream bis = null; - - try - { - if (ACCESS_CONTROLLER_CLASS != null) - { - is = AccessController.doPrivileged(new PrivilegedAction() { - public InputStream run() - { - return OutputPropertiesFactory.class - .getResourceAsStream(resourceName); - } - }); - } - else - { - // User may be using older JDK ( JDK < 1.2 ) - is = OutputPropertiesFactory.class - .getResourceAsStream(resourceName); - } - - bis = new BufferedInputStream(is); - props.load(bis); - } - catch (IOException ioe) - { - if (defaults == null) - { - throw ioe; - } - else - { - throw new WrappedRuntimeException( - Utils.messages.createMessage( - MsgKey.ER_COULD_NOT_LOAD_RESOURCE, - new Object[] { resourceName }), - ioe); - //"Could not load '"+resourceName+"' (check CLASSPATH), now using just the defaults ", ioe); - } - } - catch (SecurityException se) - { - // Repeat IOException handling for sandbox/applet case -sc - if (defaults == null) - { - throw se; - } - else - { - throw new WrappedRuntimeException( - Utils.messages.createMessage( - MsgKey.ER_COULD_NOT_LOAD_RESOURCE, - new Object[] { resourceName }), - se); - //"Could not load '"+resourceName+"' (check CLASSPATH, applet security), now using just the defaults ", se); - } - } - finally - { - if (bis != null) - { - bis.close(); - } - if (is != null) - { - is.close(); - } - } - - // Note that we're working at the HashTable level here, - // and not at the Properties level! This is important - // because we don't want to modify the default properties. - // NB: If fixupPropertyString ends up changing the property - // name or value, we need to remove the old key and re-add - // with the new key and value. However, then our Enumeration - // could lose its place in the HashTable. So, we first - // clone the HashTable and enumerate over that since the - // clone will not change. When we migrate to Collections, - // this code should be revisited and cleaned up to use - // an Iterator which may (or may not) alleviate the need for - // the clone. Many thanks to Padraig O'hIceadha - // for finding this problem. Bugzilla 2000. - - Enumeration keys = ((Properties) props.clone()).keys(); - while (keys.hasMoreElements()) - { - String key = (String) keys.nextElement(); - // Now check if the given key was specified as a - // System property. If so, the system property - // overides the default value in the propery file. - String value = null; - try - { - value = SecuritySupport.getSystemProperty(key); - } - catch (SecurityException se) - { - // No-op for sandbox/applet case, leave null -sc - } - if (value == null) - value = (String) props.get(key); - - String newKey = fixupPropertyString(key, true); - String newValue = null; - try - { - newValue = SecuritySupport.getSystemProperty(newKey); - } - catch (SecurityException se) - { - // No-op for sandbox/applet case, leave null -sc - } - if (newValue == null) - newValue = fixupPropertyString(value, false); - else - newValue = fixupPropertyString(newValue, false); - - if (key != newKey || value != newValue) - { - props.remove(key); - props.put(newKey, newValue); - } - + for (int i = 0; i < keys.length; i++) { + // check System Property. This is kept as is for binary compatibility + String sys = SecuritySupport.getSystemProperty(keys[i]); + props.put(keys[i], (sys == null) ? values[i] : sys); } return props; } - - /** - * Fix up a string in an output properties file according to - * the rules of {@link #loadPropertiesFile}. - * - * @param s non-null reference to string that may need to be fixed up. - * @return A new string if fixup occured, otherwise the s argument. - */ - static private String fixupPropertyString(String s, boolean doClipping) - { - int index; - if (doClipping && s.startsWith(S_XSLT_PREFIX)) - { - s = s.substring(S_XSLT_PREFIX_LEN); - } - if (s.startsWith(S_XALAN_PREFIX)) - { - s = - S_BUILTIN_EXTENSIONS_UNIVERSAL - + s.substring(S_XALAN_PREFIX_LEN); - } - if ((index = s.indexOf("\\u003a")) > 0) - { - String temp = s.substring(index + 6); - s = s.substring(0, index) + ":" + temp; - - } - return s; - } - }