diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java index 7d775337b58..da5500a6c59 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,6 +20,7 @@ package com.sun.org.apache.xml.internal.serializer; +import com.sun.org.apache.xml.internal.serializer.dom3.DOMConstants; 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; @@ -51,7 +52,7 @@ import org.xml.sax.SAXException; * serializers (xml, html, text ...) that write output to a stream. * * @xsl.usage internal - * @LastModified: June 2020 + * @LastModified: Jan 2021 */ abstract public class ToStream extends SerializerBase { @@ -492,8 +493,10 @@ abstract public class ToStream extends SerializerBase { if (OutputPropertiesFactory.S_KEY_INDENT_AMOUNT.equals(name)) { setIndentAmount(Integer.parseInt(val)); } else if (OutputKeys.INDENT.equals(name)) { - boolean b = val.endsWith("yes") ? true : false; - m_doIndent = b; + m_doIndent = val.endsWith("yes"); + } else if ((DOMConstants.S_JDK_PROPERTIES_NS + DOMConstants.S_IS_STANDALONE) + .equals(name)) { + m_isStandalone = val.endsWith("yes"); } break; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOMConstants.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOMConstants.java index c50cdf66c8d..b7c0d2ecef2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOMConstants.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/DOMConstants.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one @@ -22,12 +21,15 @@ package com.sun.org.apache.xml.internal.serializer.dom3; +import com.sun.org.apache.xerces.internal.impl.Constants; + /** * DOM Constants used by the DOM Level 3 LSSerializer implementation. * * @xsl.usage internal + * @LastModified: Jan 2021 */ -final class DOMConstants { +public final class DOMConstants { // // Constants: DOM Level 3 feature ids // @@ -35,6 +37,8 @@ final class DOMConstants { public static final String XERCES_URL = "http://xml.apache.org/xerces-2j"; + public static final String ORACLE_URL = "http://www.oracle.com/xml"; + // The namespace used to qualified DOM Level 3 DOMConfiguration parameters public static final String S_DOM3_PROPERTIES_NS = "{" + DOMConstants.DOM3_REC_URL + "}"; @@ -42,6 +46,9 @@ final class DOMConstants { public static final String S_XERCES_PROPERTIES_NS = "{" + DOMConstants.XERCES_URL + "}"; + // The namespace used for the JDK-only parameters + public static final String S_JDK_PROPERTIES_NS = "{" + ORACLE_URL + "}"; + // xmlns namespaces private static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; @@ -113,6 +120,25 @@ final class DOMConstants { // The xerces serializer specific 'omit-xml-declaration' property used in LSSerializer public static final String S_XML_VERSION = "xml-version"; + /** + * Indicates that the serializer should treat the output as a standalone document. + * The JDK specific standalone property controls whether a newline should be + * added after the XML header. + * + * @see similar property ORACLE_IS_STANDALONE in OutputPropertiesFactory. + */ + public static final String S_IS_STANDALONE = "isStandalone"; + + // Fully-qualified property name with the JDK Impl prefix + public static final String FQ_IS_STANDALONE = + Constants.ORACLE_JAXP_PROPERTY_PREFIX + S_IS_STANDALONE; + + // The property with namespace as the internal DOMConfiguration format + public static final String NS_IS_STANDALONE = S_JDK_PROPERTIES_NS + S_IS_STANDALONE; + + // Corresponding System property + public static final String SP_IS_STANDALONE = "jdk.xml.isStandalone"; + // public static final String S_XSL_VALUE_ENTITIES = "com/sun/org/apache/xml/internal/serializer/XMLEntities"; diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java index 66f12cc18fa..e4928a4f06e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one @@ -21,6 +21,7 @@ package com.sun.org.apache.xml.internal.serializer.dom3; +import com.sun.org.apache.xerces.internal.impl.Constants; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; @@ -32,7 +33,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Properties; - +import jdk.xml.internal.SecuritySupport; import com.sun.org.apache.xml.internal.serializer.DOM3Serializer; import com.sun.org.apache.xml.internal.serializer.Encodings; import com.sun.org.apache.xml.internal.serializer.Serializer; @@ -67,7 +68,7 @@ import org.w3c.dom.ls.LSSerializerFilter; * @version $Id: * * @xsl.usage internal - * @LastModified: Aug 2019 + * @LastModified: Jan 2021 */ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { @@ -159,6 +160,10 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { // Parameter discard-default-content, true [required] (default) private final static int XMLDECL = 0x1 << 18; + + // Parameter is-standalone, jdk specific, not required + private final static int IS_STANDALONE = 0x1 << 19; + // ************************************************************************ // Recognized parameters for which atleast one value can be set @@ -182,6 +187,7 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { DOMConstants.DOM_FORMAT_PRETTY_PRINT, DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS, DOMConstants.DOM_XMLDECL, + DOMConstants.FQ_IS_STANDALONE, DOMConstants.DOM_ERROR_HANDLER }; @@ -351,6 +357,20 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { // xml-declaration fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "no"); + // JDK specific property isStandalone + String p = SecuritySupport.getSystemProperty(DOMConstants.SP_IS_STANDALONE); + if (p == null || p.isEmpty()) { + p = SecuritySupport.readJAXPProperty(DOMConstants.SP_IS_STANDALONE); + } + // the system property is true only if it is "true" and false otherwise + if (p != null && p.equals("true")) { + fFeatures |= IS_STANDALONE; + fDOMConfigProperties.setProperty(DOMConstants.NS_IS_STANDALONE, + DOMConstants.DOM3_EXPLICIT_TRUE); + } else { + fDOMConfigProperties.setProperty(DOMConstants.NS_IS_STANDALONE, + DOMConstants.DOM3_DEFAULT_FALSE); + } } // ************************************************************************ @@ -378,7 +398,8 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { || name.equalsIgnoreCase(DOMConstants.DOM_WELLFORMED) || name.equalsIgnoreCase(DOMConstants.DOM_DISCARD_DEFAULT_CONTENT) || name.equalsIgnoreCase(DOMConstants.DOM_FORMAT_PRETTY_PRINT) - || name.equalsIgnoreCase(DOMConstants.DOM_XMLDECL)){ + || name.equalsIgnoreCase(DOMConstants.DOM_XMLDECL) + || name.equalsIgnoreCase(DOMConstants.FQ_IS_STANDALONE)){ // both values supported return true; } @@ -390,11 +411,11 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { // || name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS) ) { // true is not supported - return !((Boolean)value).booleanValue(); + return !((Boolean)value); } else if (name.equalsIgnoreCase(DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) { // false is not supported - return ((Boolean)value).booleanValue(); + return ((Boolean)value); } } else if (name.equalsIgnoreCase(DOMConstants.DOM_ERROR_HANDLER) && @@ -436,6 +457,8 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { return ((fFeatures & PRETTY_PRINT) != 0) ? Boolean.TRUE : Boolean.FALSE; } else if (name.equalsIgnoreCase(DOMConstants.DOM_XMLDECL)) { return ((fFeatures & XMLDECL) != 0) ? Boolean.TRUE : Boolean.FALSE; + } else if (name.equalsIgnoreCase(DOMConstants.FQ_IS_STANDALONE)) { + return ((fFeatures & IS_STANDALONE) != 0) ? Boolean.TRUE : Boolean.FALSE; } else if (name.equalsIgnoreCase(DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE)) { return ((fFeatures & ELEM_CONTENT_WHITESPACE) != 0) ? Boolean.TRUE : Boolean.FALSE; } else if (name.equalsIgnoreCase(DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) { @@ -606,6 +629,10 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer { } else { fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "yes"); } + } else if (name.equalsIgnoreCase(DOMConstants.FQ_IS_STANDALONE)) { + fFeatures = state ? fFeatures | IS_STANDALONE : fFeatures & ~IS_STANDALONE; + fDOMConfigProperties.setProperty(DOMConstants.NS_IS_STANDALONE, state ? "yes" : "no"); + } else if (name.equalsIgnoreCase(DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE)) { fFeatures = state ? fFeatures | ELEM_CONTENT_WHITESPACE : fFeatures & ~ELEM_CONTENT_WHITESPACE; diff --git a/src/java.xml/share/classes/module-info.java b/src/java.xml/share/classes/module-info.java index 53f166f8a82..cb0eaedb3fa 100644 --- a/src/java.xml/share/classes/module-info.java +++ b/src/java.xml/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,236 @@ * Defines the Java API for XML Processing (JAXP), the Streaming API for XML (StAX), * the Simple API for XML (SAX), and the W3C Document Object Model (DOM) API. * + * @implNote + *
+ *
+ * {@code http://www.oracle.com/xml/jaxp/properties/} + *+ * + * The prefix for features: + *
+ * {@code http://www.oracle.com/xml/jaxp/features/} + *+ * + * The prefix for System Properties: + *
+ * {@code jdk.xml.} + *+ *
+ *
+ * An example of a property that indicates whether an XML document is standalone + * would thus have a format: + *
+ * {@code http://www.oracle.com/xml/jaxp/properties/isStandalone} + *+ * and a corresponding System Property: + *
+ * {@systemProperty jdk.xml.isStandalone} + *+ * + *
+ * {@code jdk.xml.isStandalone=true} + *+ *
+ * For details about the JAXP configuration file {@code jaxp.properties}, refer to + * {@link javax.xml.parsers.SAXParserFactory#newInstance() SAXParserFactory#newInstance}. + * + *
+ * When the Java Security Manager is present, secure processing is set to true + * and can not be turned off. The security properties are therefore enforced. + *
+ * Properties specified in the jaxp.properties file affect all invocations of + * the JDK, and will override their default values, or those that may have been + * set by secure processing. + *
+ * System properties, when set, affect the invocation of the JDK and override + * the default settings or those that may have been set in jaxp.properties or + * by secure processing. + *
+ * JAXP properties specified through JAXP factories or processors (e.g. SAXParser) + * take preference over system properties, the jaxp.properties file, as well as + * secure processing. + *
+ * + *
+ * + *
ID | + *Name | + *How to set the property | + *
---|---|---|
DOM | + *DOM Parser | + *
+ * {@code DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();} + * {@code dbf.setAttribute(name, value);} + * |
+ *
SAX | + *SAX Parser | + *
+ * {@code SAXParserFactory spf = SAXParserFactory.newInstance();} + * {@code SAXParser parser = spf.newSAXParser();} + * {@code parser.setProperty(name, value);} + * |
+ *
StAX | + *StAX Parser | + *
+ * {@code XMLInputFactory xif = XMLInputFactory.newInstance();} + * {@code xif.setProperty(name, value);} + * |
+ *
Validation | + *XML Validation API | + *
+ * {@code SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);} + * {@code schemaFactory.setProperty(name, value);} + * |
+ *
Transform | + *XML Transform API | + *
+ * {@code TransformerFactory factory = TransformerFactory.newInstance();} + * {@code factory.setAttribute(name, value);} + * |
+ *
DOMLS | + *DOM Load and Save | + *
+ * {@code LSSerializer serializer = domImplementation.createLSSerializer();} + * {@code serializer.getDomConfig().setParameter(name, value);} + * |
+ *
+ *
+ *
Name [1] | + *Description | + *System Property [2] | + *jaxp.properties [2] | + *Value [3] | + *Security [4] | + *Supported Processor [5] | + *Since [6] | + *||
---|---|---|---|---|---|---|---|---|---|
Type | + *Value | + *Default | + *|||||||
isStandalone | + *indicates that the serializer should treat the output as a + * standalone document. The property can be used to ensure a newline is written + * after the XML declaration when the property + * {@link org.w3c.dom.ls.LSSerializer#getDomConfig() format-pretty-print} is set + * to true. Unlike the property + * {@link org.w3c.dom.ls.LSSerializer#getDomConfig() xml-declaration}, this property + * does not have an effect on whether an XML declaration should be written out. + * | + *yes | + *yes | + *boolean | + *true/false | + *false | + *No | + *DOMLS | + *17 | + *
+ * [1] The name of a property. The fully-qualified name, prefix + name, + * should be used when setting the property. + *
+ * [2] A value "yes" indicates there is a corresponding System Property + * for the property, "no" otherwise. + * + *
+ * [3] The value must be exactly as listed in this table, case-sensitive. + * The value type for the corresponding System Property is String. For boolean + * type, the system property is true only if it is "true" and false otherwise. + *
+ * [4] A value "yes" indicates the property is a Security Property. Refer + * to the Scope and Order on how secure processing + * may affect the value of a Security Property. + *
+ * [5] One or more processors that support the property. The values of the + * field are IDs described in table Processors. + *
+ * [6] Indicates the initial release the property is introduced.
+ *
+ *
+ *
* @uses javax.xml.datatype.DatatypeFactory
* @uses javax.xml.parsers.DocumentBuilderFactory
* @uses javax.xml.parsers.SAXParserFactory
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java
index 0d652f286f3..c3e1a68c059 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,9 @@
package common.prettyprint;
+import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
+import static jaxp.library.JAXPTestUtilities.setSystemProperty;
+
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@@ -30,6 +33,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -48,6 +53,7 @@ import org.testng.annotations.Test;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
@@ -60,7 +66,7 @@ import org.xml.sax.SAXException;
/*
* @test
- * @bug 6439439 8087303 8174025 8223291
+ * @bug 6439439 8087303 8174025 8223291 8249867
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true common.prettyprint.PrettyPrintTest
* @run testng/othervm common.prettyprint.PrettyPrintTest
@@ -68,6 +74,15 @@ import org.xml.sax.SAXException;
*/
@Listeners({jaxp.library.FilePolicy.class})
public class PrettyPrintTest {
+ private static final String DOM_FORMAT_PRETTY_PRINT = "format-pretty-print";
+ private static final String JDK_IS_STANDALONE =
+ "http://www.oracle.com/xml/jaxp/properties/isStandalone";
+ private static final String SP_JDK_IS_STANDALONE = "jdk.xml.isStandalone";
+ private static final String XML_LB
+ = "\n