diff -r 054a597b18f8 -r aba3efbf4ec5 jaxp/src/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/com/sun/org/apache/xml/internal/serializer/dom3/LSSerializerImpl.java Tue Jul 29 20:52:36 2014 -0700
@@ -0,0 +1,1405 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * $Id: $
+ */
+
+package com.sun.org.apache.xml.internal.serializer.dom3;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Properties;
+
+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;
+import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory;
+import com.sun.org.apache.xml.internal.serializer.SerializerFactory;
+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.SystemIDResolver;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMError;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMStringList;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ls.LSException;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
+import org.w3c.dom.ls.LSSerializerFilter;
+
+
+/**
+ * Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer and
+ * org.w3c.dom.ls.DOMConfiguration. Serialization is achieved by delegating
+ * serialization calls to org.apache.xml.serializer.ToStream
or
+ * one of its derived classes depending on the serialization method, while walking
+ * the DOM in DOM3TreeWalker.
+ * @see org.w3c.dom.ls.LSSerializer
+ * @see org.w3c.dom.DOMConfiguration
+ *
+ * @version $Id:
+ *
+ * @xsl.usage internal
+ */
+final public class LSSerializerImpl implements DOMConfiguration, LSSerializer {
+
+ /** private data members */
+ private Serializer fXMLSerializer = null;
+
+ // Tracks DOMConfiguration features.
+ protected int fFeatures = 0;
+
+ // Common DOM serializer
+ private DOM3Serializer fDOMSerializer = null;
+
+ // A filter set on the LSSerializer
+ private LSSerializerFilter fSerializerFilter = null;
+
+ // Stores the nodeArg parameter to speed up multiple writes of the same node.
+ private Node fVisitedNode = null;
+
+ // The end-of-line character sequence used in serialization. "\n" is whats used on the web.
+ private String fEndOfLine = "\n";
+
+ // The DOMErrorhandler.
+ private DOMErrorHandler fDOMErrorHandler = null;
+
+ // The Configuration parameter to pass to the Underlying serilaizer.
+ private Properties fDOMConfigProperties = null;
+
+ // The encoding to use during serialization.
+ private String fEncoding;
+
+ // ************************************************************************
+ // DOM Level 3 DOM Configuration parameter names
+ // ************************************************************************
+ // Parameter canonical-form, true [optional] - NOT SUPPORTED
+ private final static int CANONICAL = 0x1 << 0;
+
+ // Parameter cdata-sections, true [required] (default)
+ private final static int CDATA = 0x1 << 1;
+
+ // Parameter check-character-normalization, true [optional] - NOT SUPPORTED
+ private final static int CHARNORMALIZE = 0x1 << 2;
+
+ // Parameter comments, true [required] (default)
+ private final static int COMMENTS = 0x1 << 3;
+
+ // Parameter datatype-normalization, true [optional] - NOT SUPPORTED
+ private final static int DTNORMALIZE = 0x1 << 4;
+
+ // Parameter element-content-whitespace, true [required] (default) - value - false [optional] NOT SUPPORTED
+ private final static int ELEM_CONTENT_WHITESPACE = 0x1 << 5;
+
+ // Parameter entities, true [required] (default)
+ private final static int ENTITIES = 0x1 << 6;
+
+ // Parameter infoset, true [required] (default), false has no effect --> True has no effect for the serializer
+ private final static int INFOSET = 0x1 << 7;
+
+ // Parameter namespaces, true [required] (default)
+ private final static int NAMESPACES = 0x1 << 8;
+
+ // Parameter namespace-declarations, true [required] (default)
+ private final static int NAMESPACEDECLS = 0x1 << 9;
+
+ // Parameter normalize-characters, true [optional] - NOT SUPPORTED
+ private final static int NORMALIZECHARS = 0x1 << 10;
+
+ // Parameter split-cdata-sections, true [required] (default)
+ private final static int SPLITCDATA = 0x1 << 11;
+
+ // Parameter validate, true [optional] - NOT SUPPORTED
+ private final static int VALIDATE = 0x1 << 12;
+
+ // Parameter validate-if-schema, true [optional] - NOT SUPPORTED
+ private final static int SCHEMAVALIDATE = 0x1 << 13;
+
+ // Parameter split-cdata-sections, true [required] (default)
+ private final static int WELLFORMED = 0x1 << 14;
+
+ // Parameter discard-default-content, true [required] (default)
+ // Not sure how this will be used in level 2 Documents
+ private final static int DISCARDDEFAULT = 0x1 << 15;
+
+ // Parameter format-pretty-print, true [optional]
+ private final static int PRETTY_PRINT = 0x1 << 16;
+
+ // Parameter ignore-unknown-character-denormalizations, true [required] (default)
+ // We currently do not support XML 1.1 character normalization
+ private final static int IGNORE_CHAR_DENORMALIZE = 0x1 << 17;
+
+ // Parameter discard-default-content, true [required] (default)
+ private final static int XMLDECL = 0x1 << 18;
+ // ************************************************************************
+
+ // Recognized parameters for which atleast one value can be set
+ private String fRecognizedParameters [] = {
+ DOMConstants.DOM_CANONICAL_FORM,
+ DOMConstants.DOM_CDATA_SECTIONS,
+ DOMConstants.DOM_CHECK_CHAR_NORMALIZATION,
+ DOMConstants.DOM_COMMENTS,
+ DOMConstants.DOM_DATATYPE_NORMALIZATION,
+ DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE,
+ DOMConstants.DOM_ENTITIES,
+ DOMConstants.DOM_INFOSET,
+ DOMConstants.DOM_NAMESPACES,
+ DOMConstants.DOM_NAMESPACE_DECLARATIONS,
+ //DOMConstants.DOM_NORMALIZE_CHARACTERS,
+ DOMConstants.DOM_SPLIT_CDATA,
+ DOMConstants.DOM_VALIDATE,
+ DOMConstants.DOM_VALIDATE_IF_SCHEMA,
+ DOMConstants.DOM_WELLFORMED,
+ DOMConstants.DOM_DISCARD_DEFAULT_CONTENT,
+ DOMConstants.DOM_FORMAT_PRETTY_PRINT,
+ DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS,
+ DOMConstants.DOM_XMLDECL,
+ DOMConstants.DOM_ERROR_HANDLER
+ };
+
+
+ /**
+ * Constructor: Creates a LSSerializerImpl object. The underlying
+ * XML 1.0 or XML 1.1 org.apache.xml.serializer.Serializer object is
+ * created and initialized the first time any of the write methods are
+ * invoked to serialize the Node. Subsequent write methods on the same
+ * LSSerializerImpl object will use the previously created Serializer object.
+ */
+ public LSSerializerImpl () {
+ // set default parameters
+ fFeatures |= CDATA;
+ fFeatures |= COMMENTS;
+ fFeatures |= ELEM_CONTENT_WHITESPACE;
+ fFeatures |= ENTITIES;
+ fFeatures |= NAMESPACES;
+ fFeatures |= NAMESPACEDECLS;
+ fFeatures |= SPLITCDATA;
+ fFeatures |= WELLFORMED;
+ fFeatures |= DISCARDDEFAULT;
+ fFeatures |= XMLDECL;
+
+ // New OutputFormat properties
+ fDOMConfigProperties = new Properties();
+
+ // Initialize properties to be passed on the underlying serializer
+ initializeSerializerProps();
+
+ // Read output_xml.properties and System Properties to initialize properties
+ Properties configProps = OutputPropertiesFactory.getDefaultMethodProperties("xml");
+
+ // change xml version from 1.0 to 1.1
+ //configProps.setProperty("version", "1.1");
+
+ // Get a serializer that seriailizes according to the properties,
+ // which in this case is to xml
+ fXMLSerializer = SerializerFactory.getSerializer(configProps);
+
+ // Initialize Serializer
+ fXMLSerializer.setOutputFormat(fDOMConfigProperties);
+ }
+
+ /**
+ * Initializes the underlying serializer's configuration depending on the
+ * default DOMConfiguration parameters. This method must be called before a
+ * node is to be serialized.
+ *
+ * @xsl.usage internal
+ */
+ public void initializeSerializerProps () {
+ // canonical-form
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CANONICAL_FORM, DOMConstants.DOM3_DEFAULT_FALSE);
+
+ // cdata-sections
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CDATA_SECTIONS, DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // "check-character-normalization"
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CHECK_CHAR_NORMALIZATION,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+
+ // comments
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_COMMENTS, DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // datatype-normalization
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DATATYPE_NORMALIZATION,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+
+ // element-content-whitespace
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE,
+ DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // entities
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ENTITIES, DOMConstants.DOM3_DEFAULT_TRUE);
+ // preserve entities
+ fDOMConfigProperties.setProperty(
+ OutputPropertiesFactory.S_KEY_ENTITIES, DOMConstants.S_XSL_VALUE_ENTITIES);
+
+ // error-handler
+ // Should we set our default ErrorHandler
+ /*
+ * if (fDOMConfig.getParameter(Constants.DOM_ERROR_HANDLER) != null) {
+ * fDOMErrorHandler =
+ * (DOMErrorHandler)fDOMConfig.getParameter(Constants.DOM_ERROR_HANDLER); }
+ */
+
+ // infoset
+ if ((fFeatures & INFOSET) != 0) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACES, DOMConstants.DOM3_DEFAULT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACE_DECLARATIONS,
+ DOMConstants.DOM3_DEFAULT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_COMMENTS, DOMConstants.DOM3_DEFAULT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE,
+ DOMConstants.DOM3_DEFAULT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_WELLFORMED, DOMConstants.DOM3_DEFAULT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ENTITIES, DOMConstants.DOM3_DEFAULT_FALSE);
+ // preserve entities
+ fDOMConfigProperties.setProperty(
+ OutputPropertiesFactory.S_KEY_ENTITIES, "");
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CDATA_SECTIONS,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_VALIDATE_IF_SCHEMA,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DATATYPE_NORMALIZATION,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ }
+
+ // namespaces
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACES, DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // namespace-declarations
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACE_DECLARATIONS,
+ DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // normalize-characters
+ /*
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NORMALIZE_CHARACTERS,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ */
+
+ // split-cdata-sections
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_SPLIT_CDATA, DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // validate
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_VALIDATE, DOMConstants.DOM3_DEFAULT_FALSE);
+
+ // validate-if-schema
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_VALIDATE_IF_SCHEMA,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+
+ // well-formed
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_WELLFORMED, DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // pretty-print
+ fDOMConfigProperties.setProperty(
+ DOMConstants.S_XSL_OUTPUT_INDENT,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ fDOMConfigProperties.setProperty(
+ OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, Integer.toString(4));
+
+ //
+
+ // discard-default-content
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DISCARD_DEFAULT_CONTENT,
+ DOMConstants.DOM3_DEFAULT_TRUE);
+
+ // xml-declaration
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "no");
+
+ }
+
+ // ************************************************************************
+ // DOMConfiguraiton implementation
+ // ************************************************************************
+
+ /**
+ * Checks if setting a parameter to a specific value is supported.
+ *
+ * @see org.w3c.dom.DOMConfiguration#canSetParameter(java.lang.String, java.lang.Object)
+ * @since DOM Level 3
+ * @param name A String containing the DOMConfiguration parameter name.
+ * @param value An Object specifying the value of the corresponding parameter.
+ */
+ public boolean canSetParameter(String name, Object value) {
+ if (value instanceof Boolean){
+ if ( name.equalsIgnoreCase(DOMConstants.DOM_CDATA_SECTIONS)
+ || name.equalsIgnoreCase(DOMConstants.DOM_COMMENTS)
+ || name.equalsIgnoreCase(DOMConstants.DOM_ENTITIES)
+ || name.equalsIgnoreCase(DOMConstants.DOM_INFOSET)
+ || name.equalsIgnoreCase(DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE)
+ || name.equalsIgnoreCase(DOMConstants.DOM_NAMESPACES)
+ || name.equalsIgnoreCase(DOMConstants.DOM_NAMESPACE_DECLARATIONS)
+ || name.equalsIgnoreCase(DOMConstants.DOM_SPLIT_CDATA)
+ || name.equalsIgnoreCase(DOMConstants.DOM_WELLFORMED)
+ || name.equalsIgnoreCase(DOMConstants.DOM_DISCARD_DEFAULT_CONTENT)
+ || name.equalsIgnoreCase(DOMConstants.DOM_FORMAT_PRETTY_PRINT)
+ || name.equalsIgnoreCase(DOMConstants.DOM_XMLDECL)){
+ // both values supported
+ return true;
+ }
+ else if (name.equalsIgnoreCase(DOMConstants.DOM_CANONICAL_FORM)
+ || name.equalsIgnoreCase(DOMConstants.DOM_CHECK_CHAR_NORMALIZATION)
+ || name.equalsIgnoreCase(DOMConstants.DOM_DATATYPE_NORMALIZATION)
+ || name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE_IF_SCHEMA)
+ || name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE)
+ // || name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)
+ ) {
+ // true is not supported
+ return !((Boolean)value).booleanValue();
+ }
+ else if (name.equalsIgnoreCase(DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
+ // false is not supported
+ return ((Boolean)value).booleanValue();
+ }
+ }
+ else if (name.equalsIgnoreCase(DOMConstants.DOM_ERROR_HANDLER) &&
+ value == null || value instanceof DOMErrorHandler){
+ return true;
+ }
+ return false;
+ }
+ /**
+ * This method returns the value of a parameter if known.
+ *
+ * @see org.w3c.dom.DOMConfiguration#getParameter(java.lang.String)
+ *
+ * @param name A String containing the DOMConfiguration parameter name
+ * whose value is to be returned.
+ * @return Object The value of the parameter if known.
+ */
+ public Object getParameter(String name) throws DOMException {
+
+ if(name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)){
+ return null;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_COMMENTS)) {
+ return ((fFeatures & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_CDATA_SECTIONS)) {
+ return ((fFeatures & CDATA) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_ENTITIES)) {
+ return ((fFeatures & ENTITIES) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_NAMESPACES)) {
+ return ((fFeatures & NAMESPACES) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_NAMESPACE_DECLARATIONS)) {
+ return ((fFeatures & NAMESPACEDECLS) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_SPLIT_CDATA)) {
+ return ((fFeatures & SPLITCDATA) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_WELLFORMED)) {
+ return ((fFeatures & WELLFORMED) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_DISCARD_DEFAULT_CONTENT)) {
+ return ((fFeatures & DISCARDDEFAULT) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_FORMAT_PRETTY_PRINT)) {
+ 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.DOM_ELEMENT_CONTENT_WHITESPACE)) {
+ return ((fFeatures & ELEM_CONTENT_WHITESPACE) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
+ return Boolean.TRUE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_CANONICAL_FORM)
+ || name.equalsIgnoreCase(DOMConstants.DOM_CHECK_CHAR_NORMALIZATION)
+ || name.equalsIgnoreCase(DOMConstants.DOM_DATATYPE_NORMALIZATION)
+ // || name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)
+ || name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE)
+ || name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE_IF_SCHEMA)) {
+ return Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_INFOSET)){
+ if ((fFeatures & ENTITIES) == 0 &&
+ (fFeatures & CDATA) == 0 &&
+ (fFeatures & ELEM_CONTENT_WHITESPACE) != 0 &&
+ (fFeatures & NAMESPACES) != 0 &&
+ (fFeatures & NAMESPACEDECLS) != 0 &&
+ (fFeatures & WELLFORMED) != 0 &&
+ (fFeatures & COMMENTS) != 0) {
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_ERROR_HANDLER)) {
+ return fDOMErrorHandler;
+ } else if (
+ name.equalsIgnoreCase(DOMConstants.DOM_SCHEMA_LOCATION)
+ || name.equalsIgnoreCase(DOMConstants.DOM_SCHEMA_TYPE)) {
+ return null;
+ } else {
+ // Here we have to add the Xalan specific DOM Message Formatter
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_FEATURE_NOT_FOUND,
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ }
+
+ /**
+ * This method returns a of the parameters supported by this DOMConfiguration object
+ * and for which at least one value can be set by the application
+ *
+ * @see org.w3c.dom.DOMConfiguration#getParameterNames()
+ *
+ * @return DOMStringList A list of DOMConfiguration parameters recognized
+ * by the serializer
+ */
+ public DOMStringList getParameterNames() {
+ return new DOMStringListImpl(fRecognizedParameters);
+ }
+
+ /**
+ * This method sets the value of the named parameter.
+ *
+ * @see org.w3c.dom.DOMConfiguration#setParameter(java.lang.String, java.lang.Object)
+ *
+ * @param name A String containing the DOMConfiguration parameter name.
+ * @param value An Object contaiing the parameters value to set.
+ */
+ public void setParameter(String name, Object value) throws DOMException {
+ // If the value is a boolean
+ if (value instanceof Boolean) {
+ boolean state = ((Boolean) value).booleanValue();
+
+ if (name.equalsIgnoreCase(DOMConstants.DOM_COMMENTS)) {
+ fFeatures = state ? fFeatures | COMMENTS : fFeatures
+ & ~COMMENTS;
+ // comments
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_COMMENTS, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_COMMENTS, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_CDATA_SECTIONS)) {
+ fFeatures = state ? fFeatures | CDATA : fFeatures
+ & ~CDATA;
+ // cdata-sections
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CDATA_SECTIONS, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CDATA_SECTIONS, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_ENTITIES)) {
+ fFeatures = state ? fFeatures | ENTITIES : fFeatures
+ & ~ENTITIES;
+ // entities
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ENTITIES, DOMConstants.DOM3_EXPLICIT_TRUE);
+ fDOMConfigProperties.setProperty(
+ OutputPropertiesFactory.S_KEY_ENTITIES, DOMConstants.S_XSL_VALUE_ENTITIES);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ENTITIES, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_NAMESPACES)) {
+ fFeatures = state ? fFeatures | NAMESPACES : fFeatures
+ & ~NAMESPACES;
+ // namespaces
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACES, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACES, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name
+ .equalsIgnoreCase(DOMConstants.DOM_NAMESPACE_DECLARATIONS)) {
+ fFeatures = state ? fFeatures | NAMESPACEDECLS
+ : fFeatures & ~NAMESPACEDECLS;
+ // namespace-declarations
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACE_DECLARATIONS, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACE_DECLARATIONS, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_SPLIT_CDATA)) {
+ fFeatures = state ? fFeatures | SPLITCDATA : fFeatures
+ & ~SPLITCDATA;
+ // split-cdata-sections
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_SPLIT_CDATA, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_SPLIT_CDATA, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_WELLFORMED)) {
+ fFeatures = state ? fFeatures | WELLFORMED : fFeatures
+ & ~WELLFORMED;
+ // well-formed
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_WELLFORMED, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_WELLFORMED, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name
+ .equalsIgnoreCase(DOMConstants.DOM_DISCARD_DEFAULT_CONTENT)) {
+ fFeatures = state ? fFeatures | DISCARDDEFAULT
+ : fFeatures & ~DISCARDDEFAULT;
+ // discard-default-content
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DISCARD_DEFAULT_CONTENT, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DISCARD_DEFAULT_CONTENT, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_FORMAT_PRETTY_PRINT)) {
+ fFeatures = state ? fFeatures | PRETTY_PRINT : fFeatures
+ & ~PRETTY_PRINT;
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_INDENT,DOMConstants.DOM3_EXPLICIT_TRUE);
+ fDOMConfigProperties.setProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, Integer.toString(4));
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_INDENT,DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_XMLDECL)) {
+ fFeatures = state ? fFeatures | XMLDECL : fFeatures
+ & ~XMLDECL;
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "no");
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "yes");
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
+ fFeatures = state ? fFeatures | ELEM_CONTENT_WHITESPACE : fFeatures
+ & ~ELEM_CONTENT_WHITESPACE;
+ // element-content-whitespace
+ if (state) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE, DOMConstants.DOM3_EXPLICIT_TRUE);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE, DOMConstants.DOM3_EXPLICIT_FALSE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
+ // false is not supported
+ if (!state) {
+ // Here we have to add the Xalan specific DOM Message Formatter
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_FEATURE_NOT_SUPPORTED,
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ } else {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS, DOMConstants.DOM3_EXPLICIT_TRUE);
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_CANONICAL_FORM)
+ || name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE_IF_SCHEMA)
+ || name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE)
+ || name.equalsIgnoreCase(DOMConstants.DOM_CHECK_CHAR_NORMALIZATION)
+ || name.equalsIgnoreCase(DOMConstants.DOM_DATATYPE_NORMALIZATION)
+ // || name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)
+ ) {
+ // true is not supported
+ if (state) {
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_FEATURE_NOT_SUPPORTED,
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ } else {
+ if (name.equalsIgnoreCase(DOMConstants.DOM_CANONICAL_FORM)) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CANONICAL_FORM, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE_IF_SCHEMA)) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_VALIDATE_IF_SCHEMA, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE)) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_VALIDATE, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_VALIDATE_IF_SCHEMA)) {
+ fDOMConfigProperties.setProperty(DOMConstants.DOM_CHECK_CHAR_NORMALIZATION
+ + DOMConstants.DOM_CHECK_CHAR_NORMALIZATION, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_DATATYPE_NORMALIZATION)) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DATATYPE_NORMALIZATION, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } /* else if (name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)) {
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NORMALIZE_CHARACTERS, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } */
+ }
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_INFOSET)) {
+ if (state) {
+ fFeatures &= ~ENTITIES;
+ fFeatures &= ~CDATA;
+ fFeatures &= ~SCHEMAVALIDATE;
+ fFeatures &= ~DTNORMALIZE;
+ fFeatures |= NAMESPACES;
+ fFeatures |= NAMESPACEDECLS;
+ fFeatures |= WELLFORMED;
+ fFeatures |= ELEM_CONTENT_WHITESPACE;
+ fFeatures |= COMMENTS;
+ }
+
+ // infoset
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACES, DOMConstants.DOM3_EXPLICIT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_NAMESPACE_DECLARATIONS, DOMConstants.DOM3_EXPLICIT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_COMMENTS, DOMConstants.DOM3_EXPLICIT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE, DOMConstants.DOM3_EXPLICIT_TRUE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_WELLFORMED, DOMConstants.DOM3_EXPLICIT_TRUE);
+
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_ENTITIES, DOMConstants.DOM3_EXPLICIT_FALSE);
+ fDOMConfigProperties.setProperty(
+ OutputPropertiesFactory.S_KEY_ENTITIES, "");
+
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_CDATA_SECTIONS, DOMConstants.DOM3_EXPLICIT_FALSE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_VALIDATE_IF_SCHEMA, DOMConstants.DOM3_EXPLICIT_FALSE);
+ fDOMConfigProperties.setProperty(DOMConstants.S_DOM3_PROPERTIES_NS
+ + DOMConstants.DOM_DATATYPE_NORMALIZATION, DOMConstants.DOM3_EXPLICIT_FALSE);
+ } else if (name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)) {
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_FEATURE_NOT_SUPPORTED,
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ } else {
+ // Setting this to false has no effect
+ }
+ } // If the parameter value is not a boolean
+ else if (name.equalsIgnoreCase(DOMConstants.DOM_ERROR_HANDLER)) {
+ if (value == null || value instanceof DOMErrorHandler) {
+ fDOMErrorHandler = (DOMErrorHandler)value;
+ } else {
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_TYPE_MISMATCH_ERR,
+ new Object[] { name });
+ throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+ }
+ } else if (
+ name.equalsIgnoreCase(DOMConstants.DOM_SCHEMA_LOCATION)
+ || name.equalsIgnoreCase(DOMConstants.DOM_SCHEMA_TYPE)
+ || name.equalsIgnoreCase(DOMConstants.DOM_NORMALIZE_CHARACTERS)
+ && value != null) {
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_FEATURE_NOT_SUPPORTED,
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ } else {
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_FEATURE_NOT_FOUND,
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ }
+ // ************************************************************************
+
+
+ // ************************************************************************
+ // DOMConfiguraiton implementation
+ // ************************************************************************
+
+ /**
+ * Returns the DOMConfiguration of the LSSerializer.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#getDomConfig()
+ * @since DOM Level 3
+ * @return A DOMConfiguration object.
+ */
+ public DOMConfiguration getDomConfig() {
+ return (DOMConfiguration)this;
+ }
+
+ /**
+ * Returns the DOMConfiguration of the LSSerializer.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#getFilter()
+ * @since DOM Level 3
+ * @return A LSSerializerFilter object.
+ */
+ public LSSerializerFilter getFilter() {
+ return fSerializerFilter;
+ }
+
+ /**
+ * Returns the End-Of-Line sequence of characters to be used in the XML
+ * being serialized. If none is set a default "\n" is returned.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#getNewLine()
+ * @since DOM Level 3
+ * @return A String containing the end-of-line character sequence used in
+ * serialization.
+ */
+ public String getNewLine() {
+ return fEndOfLine;
+ }
+
+ /**
+ * Set a LSSerilizerFilter on the LSSerializer. When set, the filter is
+ * called before each node is serialized which depending on its implemention
+ * determines if the node is to be serialized or not.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#setFilter
+ * @since DOM Level 3
+ * @param filter A LSSerializerFilter to be applied to the stream to serialize.
+ */
+ public void setFilter(LSSerializerFilter filter) {
+ fSerializerFilter = filter;
+ }
+
+ /**
+ * Sets the End-Of-Line sequence of characters to be used in the XML
+ * being serialized. Setting this attribute to null will reset its
+ * value to the default value i.e. "\n".
+ *
+ * @see org.w3c.dom.ls.LSSerializer#setNewLine
+ * @since DOM Level 3
+ * @param newLine a String that is the end-of-line character sequence to be used in
+ * serialization.
+ */
+ public void setNewLine(String newLine) {
+ fEndOfLine = newLine !=null? newLine: fEndOfLine;
+ }
+
+ /**
+ * Serializes the specified node to the specified LSOutput and returns true if the Node
+ * was successfully serialized.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#write(org.w3c.dom.Node, org.w3c.dom.ls.LSOutput)
+ * @since DOM Level 3
+ * @param nodeArg The Node to serialize.
+ * @throws org.w3c.dom.ls.LSException SERIALIZE_ERR: Raised if the
+ * LSSerializer was unable to serialize the node.
+ *
+ */
+ public boolean write(Node nodeArg, LSOutput destination) throws LSException {
+ // If the destination is null
+ if (destination == null) {
+ String msg = Utils.messages
+ .createMessage(
+ MsgKey.ER_NO_OUTPUT_SPECIFIED,
+ null);
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, msg,
+ MsgKey.ER_NO_OUTPUT_SPECIFIED));
+ }
+ throw new LSException(LSException.SERIALIZE_ERR, msg);
+ }
+
+ // If nodeArg is null, return false. Should we throw and LSException instead?
+ if (nodeArg == null ) {
+ return false;
+ }
+
+ // Obtain a reference to the serializer to use
+ // Serializer serializer = getXMLSerializer(xmlVersion);
+ Serializer serializer = fXMLSerializer;
+ serializer.reset();
+
+ // If the node has not been seen
+ if ( nodeArg != fVisitedNode) {
+ // Determine the XML Document version of the Node
+ String xmlVersion = getXMLVersion(nodeArg);
+
+ // Determine the encoding: 1.LSOutput.encoding, 2.Document.inputEncoding, 3.Document.xmlEncoding.
+ fEncoding = destination.getEncoding();
+ if (fEncoding == null ) {
+ fEncoding = getInputEncoding(nodeArg);
+ fEncoding = fEncoding != null ? fEncoding : getXMLEncoding(nodeArg) == null? "UTF-8": getXMLEncoding(nodeArg);
+ }
+
+ // If the encoding is not recognized throw an exception.
+ // Note: The serializer defaults to UTF-8 when created
+ if (!Encodings.isRecognizedEncoding(fEncoding)) {
+ String msg = Utils.messages
+ .createMessage(
+ MsgKey.ER_UNSUPPORTED_ENCODING,
+ null);
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, msg,
+ MsgKey.ER_UNSUPPORTED_ENCODING));
+ }
+ throw new LSException(LSException.SERIALIZE_ERR, msg);
+ }
+
+ serializer.getOutputFormat().setProperty("version", xmlVersion);
+
+ // Set the output encoding and xml version properties
+ fDOMConfigProperties.setProperty(DOMConstants.S_XERCES_PROPERTIES_NS + DOMConstants.S_XML_VERSION, xmlVersion);
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_ENCODING, fEncoding);
+
+ // If the node to be serialized is not a Document, Element, or Entity
+ // node
+ // then the XML declaration, or text declaration, should be never be
+ // serialized.
+ if ( (nodeArg.getNodeType() != Node.DOCUMENT_NODE
+ || nodeArg.getNodeType() != Node.ELEMENT_NODE
+ || nodeArg.getNodeType() != Node.ENTITY_NODE)
+ && ((fFeatures & XMLDECL) != 0)) {
+ fDOMConfigProperties.setProperty(
+ DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ }
+
+ fVisitedNode = nodeArg;
+ }
+
+ // Update the serializer properties
+ fXMLSerializer.setOutputFormat(fDOMConfigProperties);
+
+ //
+ try {
+
+ // The LSSerializer will use the LSOutput object to determine
+ // where to serialize the output to in the following order the
+ // first one that is not null and not an empty string will be
+ // used: 1.LSOutput.characterStream, 2.LSOutput.byteStream,
+ // 3. LSOutput.systemId
+ // 1.LSOutput.characterStream
+ Writer writer = destination.getCharacterStream();
+ if (writer == null ) {
+
+ // 2.LSOutput.byteStream
+ OutputStream outputStream = destination.getByteStream();
+ if ( outputStream == null) {
+
+ // 3. LSOutput.systemId
+ String uri = destination.getSystemId();
+ if (uri == null) {
+ String msg = Utils.messages
+ .createMessage(
+ MsgKey.ER_NO_OUTPUT_SPECIFIED,
+ null);
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, msg,
+ MsgKey.ER_NO_OUTPUT_SPECIFIED));
+ }
+ throw new LSException(LSException.SERIALIZE_ERR, msg);
+
+ } else {
+ // Expand the System Id and obtain an absolute URI for it.
+ String absoluteURI = SystemIDResolver.getAbsoluteURI(uri);
+
+ URL url = new URL(absoluteURI);
+ OutputStream urlOutStream = null;
+ String protocol = url.getProtocol();
+ String host = url.getHost();
+
+ // For file protocols, there is no need to use a URL to get its
+ // corresponding OutputStream
+
+ // Scheme names consist of a sequence of characters. The lower case
+ // letters "a"--"z", digits, and the characters plus ("+"), period
+ // ("."), and hyphen ("-") are allowed. For resiliency, programs
+ // interpreting URLs should treat upper case letters as equivalent to
+ // lower case in scheme names (e.g., allow "HTTP" as well as "http").
+ if (protocol.equalsIgnoreCase("file")
+ && (host == null || host.length() == 0 || host.equals("localhost"))) {
+ // do we also need to check for host.equals(hostname)
+ urlOutStream = new FileOutputStream(new File(url.getPath()));
+
+ } else {
+ // This should support URL's whose schemes are mentioned in
+ // RFC1738 other than file
+
+ URLConnection urlCon = url.openConnection();
+ urlCon.setDoInput(false);
+ urlCon.setDoOutput(true);
+ urlCon.setUseCaches(false);
+ urlCon.setAllowUserInteraction(false);
+
+ // When writing to a HTTP URI, a HTTP PUT is performed.
+ if (urlCon instanceof HttpURLConnection) {
+ HttpURLConnection httpCon = (HttpURLConnection) urlCon;
+ httpCon.setRequestMethod("PUT");
+ }
+ urlOutStream = urlCon.getOutputStream();
+ }
+ // set the OutputStream to that obtained from the systemId
+ serializer.setWriter(new OutputStreamWriter(urlOutStream));
+ }
+ } else {
+ // 2.LSOutput.byteStream
+ serializer.setWriter(new OutputStreamWriter(outputStream, fEncoding));
+ }
+ } else {
+ // 1.LSOutput.characterStream
+ serializer.setWriter(writer);
+ }
+
+ // The associated media type by default is set to text/xml on
+ // org.apache.xml.serializer.SerializerBase.
+
+ // Get a reference to the serializer then lets you serilize a DOM
+ // Use this hack till Xalan support JAXP1.3
+ if (fDOMSerializer == null) {
+ fDOMSerializer = (DOM3Serializer)serializer.asDOM3Serializer();
+ }
+
+ // Set the error handler on the DOM3Serializer interface implementation
+ if (fDOMErrorHandler != null) {
+ fDOMSerializer.setErrorHandler(fDOMErrorHandler);
+ }
+
+ // Set the filter on the DOM3Serializer interface implementation
+ if (fSerializerFilter != null) {
+ fDOMSerializer.setNodeFilter(fSerializerFilter);
+ }
+
+ // Set the NewLine character to be used
+ fDOMSerializer.setNewLine(fEndOfLine);
+
+ // Serializer your DOM, where node is an org.w3c.dom.Node
+ // Assuming that Xalan's serializer can serialize any type of DOM node
+ fDOMSerializer.serializeDOM3(nodeArg);
+
+ } catch( UnsupportedEncodingException ue) {
+
+ String msg = Utils.messages
+ .createMessage(
+ MsgKey.ER_UNSUPPORTED_ENCODING,
+ null);
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, msg,
+ MsgKey.ER_UNSUPPORTED_ENCODING, ue));
+ }
+ throw new LSException(LSException.SERIALIZE_ERR, ue.getMessage());
+ } catch (LSException lse) {
+ // Rethrow LSException.
+ throw lse;
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw new LSException(LSException.SERIALIZE_ERR, e!=null?e.getMessage():"NULL Exception") ;
+ } catch (Exception e) {
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, e.getMessage(),
+ null, e));
+ }
+ e.printStackTrace();
+ throw new LSException(LSException.SERIALIZE_ERR, e.toString());
+ }
+ return true;
+ }
+
+ /**
+ * Serializes the specified node and returns a String with the serialized
+ * data to the caller.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#writeToString(org.w3c.dom.Node)
+ * @since DOM Level 3
+ * @param nodeArg The Node to serialize.
+ * @throws org.w3c.dom.ls.LSException SERIALIZE_ERR: Raised if the
+ * LSSerializer was unable to serialize the node.
+ *
+ */
+ public String writeToString(Node nodeArg) throws DOMException, LSException {
+ // return null is nodeArg is null. Should an Exception be thrown instead?
+ if (nodeArg == null) {
+ return null;
+ }
+
+ // Should we reset the serializer configuration before each write operation?
+ // Obtain a reference to the serializer to use
+ Serializer serializer = fXMLSerializer;
+ serializer.reset();
+
+ if (nodeArg != fVisitedNode){
+ // Determine the XML Document version of the Node
+ String xmlVersion = getXMLVersion(nodeArg);
+
+ serializer.getOutputFormat().setProperty("version", xmlVersion);
+
+ // Set the output encoding and xml version properties
+ fDOMConfigProperties.setProperty(DOMConstants.S_XERCES_PROPERTIES_NS + DOMConstants.S_XML_VERSION, xmlVersion);
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_ENCODING, "UTF-16");
+
+ // If the node to be serialized is not a Document, Element, or Entity
+ // node
+ // then the XML declaration, or text declaration, should be never be
+ // serialized.
+ if ((nodeArg.getNodeType() != Node.DOCUMENT_NODE
+ || nodeArg.getNodeType() != Node.ELEMENT_NODE
+ || nodeArg.getNodeType() != Node.ENTITY_NODE)
+ && ((fFeatures & XMLDECL) != 0)) {
+ fDOMConfigProperties.setProperty(
+ DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ }
+
+ fVisitedNode = nodeArg;
+ }
+ // Update the serializer properties
+ fXMLSerializer.setOutputFormat(fDOMConfigProperties);
+
+ // StringWriter to Output to
+ StringWriter output = new StringWriter();
+
+ //
+ try {
+
+ // Set the Serializer's Writer to a StringWriter
+ serializer.setWriter(output);
+
+ // Get a reference to the serializer then lets you serilize a DOM
+ // Use this hack till Xalan support JAXP1.3
+ if (fDOMSerializer == null) {
+ fDOMSerializer = (DOM3Serializer)serializer.asDOM3Serializer();
+ }
+
+ // Set the error handler on the DOM3Serializer interface implementation
+ if (fDOMErrorHandler != null) {
+ fDOMSerializer.setErrorHandler(fDOMErrorHandler);
+ }
+
+ // Set the filter on the DOM3Serializer interface implementation
+ if (fSerializerFilter != null) {
+ fDOMSerializer.setNodeFilter(fSerializerFilter);
+ }
+
+ // Set the NewLine character to be used
+ fDOMSerializer.setNewLine(fEndOfLine);
+
+ // Serializer your DOM, where node is an org.w3c.dom.Node
+ fDOMSerializer.serializeDOM3(nodeArg);
+ } catch (LSException lse) {
+ // Rethrow LSException.
+ throw lse;
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw new LSException(LSException.SERIALIZE_ERR, e.toString());
+ } catch (Exception e) {
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, e.getMessage(),
+ null, e));
+ }
+ e.printStackTrace();
+ throw new LSException(LSException.SERIALIZE_ERR, e.toString());
+ }
+
+ // return the serialized string
+ return output.toString();
+ }
+
+ /**
+ * Serializes the specified node to the specified URI and returns true if the Node
+ * was successfully serialized.
+ *
+ * @see org.w3c.dom.ls.LSSerializer#writeToURI(org.w3c.dom.Node, String)
+ * @since DOM Level 3
+ * @param nodeArg The Node to serialize.
+ * @throws org.w3c.dom.ls.LSException SERIALIZE_ERR: Raised if the
+ * LSSerializer was unable to serialize the node.
+ *
+ */
+ public boolean writeToURI(Node nodeArg, String uri) throws LSException {
+ // If nodeArg is null, return false. Should we throw and LSException instead?
+ if (nodeArg == null ) {
+ return false;
+ }
+
+ // Obtain a reference to the serializer to use
+ Serializer serializer = fXMLSerializer;
+ serializer.reset();
+
+ if (nodeArg != fVisitedNode) {
+ // Determine the XML Document version of the Node
+ String xmlVersion = getXMLVersion(nodeArg);
+
+ // Determine the encoding: 1.LSOutput.encoding,
+ // 2.Document.inputEncoding, 3.Document.xmlEncoding.
+ fEncoding = getInputEncoding(nodeArg);
+ if (fEncoding == null ) {
+ fEncoding = fEncoding != null ? fEncoding : getXMLEncoding(nodeArg) == null? "UTF-8": getXMLEncoding(nodeArg);
+ }
+
+ serializer.getOutputFormat().setProperty("version", xmlVersion);
+
+ // Set the output encoding and xml version properties
+ fDOMConfigProperties.setProperty(DOMConstants.S_XERCES_PROPERTIES_NS + DOMConstants.S_XML_VERSION, xmlVersion);
+ fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_ENCODING, fEncoding);
+
+ // If the node to be serialized is not a Document, Element, or Entity
+ // node
+ // then the XML declaration, or text declaration, should be never be
+ // serialized.
+ if ( (nodeArg.getNodeType() != Node.DOCUMENT_NODE
+ || nodeArg.getNodeType() != Node.ELEMENT_NODE
+ || nodeArg.getNodeType() != Node.ENTITY_NODE)
+ && ((fFeatures & XMLDECL) != 0)) {
+ fDOMConfigProperties.setProperty(
+ DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL,
+ DOMConstants.DOM3_DEFAULT_FALSE);
+ }
+
+ fVisitedNode = nodeArg;
+ }
+
+ // Update the serializer properties
+ fXMLSerializer.setOutputFormat(fDOMConfigProperties);
+
+ //
+ try {
+ // If the specified encoding is not supported an
+ // "unsupported-encoding" fatal error is raised. ??
+ if (uri == null) {
+ String msg = Utils.messages.createMessage(
+ MsgKey.ER_NO_OUTPUT_SPECIFIED, null);
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, msg,
+ MsgKey.ER_NO_OUTPUT_SPECIFIED));
+ }
+ throw new LSException(LSException.SERIALIZE_ERR, msg);
+
+ } else {
+ // REVISIT: Can this be used to get an absolute expanded URI
+ String absoluteURI = SystemIDResolver.getAbsoluteURI(uri);
+
+ URL url = new URL(absoluteURI);
+ OutputStream urlOutStream = null;
+ String protocol = url.getProtocol();
+ String host = url.getHost();
+
+ // For file protocols, there is no need to use a URL to get its
+ // corresponding OutputStream
+
+ // Scheme names consist of a sequence of characters. The lower
+ // case letters "a"--"z", digits, and the characters plus ("+"),
+ // period ("."), and hyphen ("-") are allowed. For resiliency,
+ // programs interpreting URLs should treat upper case letters as
+ // equivalent to lower case in scheme names
+ // (e.g., allow "HTTP" as well as "http").
+ if (protocol.equalsIgnoreCase("file")
+ && (host == null || host.length() == 0 || host
+ .equals("localhost"))) {
+ // do we also need to check for host.equals(hostname)
+ urlOutStream = new FileOutputStream(new File(url.getPath()));
+
+ } else {
+ // This should support URL's whose schemes are mentioned in
+ // RFC1738 other than file
+
+ URLConnection urlCon = url.openConnection();
+ urlCon.setDoInput(false);
+ urlCon.setDoOutput(true);
+ urlCon.setUseCaches(false);
+ urlCon.setAllowUserInteraction(false);
+
+ // When writing to a HTTP URI, a HTTP PUT is performed.
+ if (urlCon instanceof HttpURLConnection) {
+ HttpURLConnection httpCon = (HttpURLConnection) urlCon;
+ httpCon.setRequestMethod("PUT");
+ }
+ urlOutStream = urlCon.getOutputStream();
+ }
+ // set the OutputStream to that obtained from the systemId
+ serializer.setWriter(new OutputStreamWriter(urlOutStream, fEncoding));
+ }
+
+ // Get a reference to the serializer then lets you serilize a DOM
+ // Use this hack till Xalan support JAXP1.3
+ if (fDOMSerializer == null) {
+ fDOMSerializer = (DOM3Serializer)serializer.asDOM3Serializer();
+ }
+
+ // Set the error handler on the DOM3Serializer interface implementation
+ if (fDOMErrorHandler != null) {
+ fDOMSerializer.setErrorHandler(fDOMErrorHandler);
+ }
+
+ // Set the filter on the DOM3Serializer interface implementation
+ if (fSerializerFilter != null) {
+ fDOMSerializer.setNodeFilter(fSerializerFilter);
+ }
+
+ // Set the NewLine character to be used
+ fDOMSerializer.setNewLine(fEndOfLine);
+
+ // Serializer your DOM, where node is an org.w3c.dom.Node
+ // Assuming that Xalan's serializer can serialize any type of DOM
+ // node
+ fDOMSerializer.serializeDOM3(nodeArg);
+
+ } catch (LSException lse) {
+ // Rethrow LSException.
+ throw lse;
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw new LSException(LSException.SERIALIZE_ERR, e.toString());
+ } catch (Exception e) {
+ if (fDOMErrorHandler != null) {
+ fDOMErrorHandler.handleError(new DOMErrorImpl(
+ DOMError.SEVERITY_FATAL_ERROR, e.getMessage(),
+ null, e));
+ }
+ e.printStackTrace();
+ throw new LSException(LSException.SERIALIZE_ERR, e.toString());
+ }
+
+ return true;
+ }
+ // ************************************************************************
+
+
+ // ************************************************************************
+ // Implementaion methods
+ // ************************************************************************
+
+ /**
+ * Determines the XML Version of the Document Node to serialize. If the Document Node
+ * is not a DOM Level 3 Node, then the default version returned is 1.0.
+ *
+ * @param nodeArg The Node to serialize
+ * @return A String containing the version pseudo-attribute of the XMLDecl.
+ * @throws Throwable if the DOM implementation does not implement Document.getXmlVersion()
+ */
+ //protected String getXMLVersion(Node nodeArg) throws Throwable {
+ protected String getXMLVersion(Node nodeArg) {
+ Document doc = null;
+
+ // Determine the XML Version of the document
+ if (nodeArg != null) {
+ if (nodeArg.getNodeType() == Node.DOCUMENT_NODE) {
+ // The Document node is the Node argument
+ doc = (Document)nodeArg;
+ } else {
+ // The Document node is the Node argument's ownerDocument
+ doc = nodeArg.getOwnerDocument();
+ }
+
+ // Determine the DOM Version.
+ if (doc != null && doc.getImplementation().hasFeature("Core","3.0")) {
+ try {
+ return doc.getXmlVersion();
+ } catch (AbstractMethodError e) {
+ //ignore, impl does not support the method
+ }
+ }
+ }
+ // The version will be treated as "1.0" which may result in
+ // an ill-formed document being serialized.
+ // If nodeArg does not have an ownerDocument, treat this as XML 1.0
+ return "1.0";
+ }
+
+ /**
+ * Determines the XML Encoding of the Document Node to serialize. If the Document Node
+ * is not a DOM Level 3 Node, then the default encoding "UTF-8" is returned.
+ *
+ * @param nodeArg The Node to serialize
+ * @return A String containing the encoding pseudo-attribute of the XMLDecl.
+ * @throws Throwable if the DOM implementation does not implement Document.getXmlEncoding()
+ */
+ protected String getXMLEncoding(Node nodeArg) {
+ Document doc = null;
+
+ // Determine the XML Encoding of the document
+ if (nodeArg != null) {
+ if (nodeArg.getNodeType() == Node.DOCUMENT_NODE) {
+ // The Document node is the Node argument
+ doc = (Document)nodeArg;
+ } else {
+ // The Document node is the Node argument's ownerDocument
+ doc = nodeArg.getOwnerDocument();
+ }
+
+ // Determine the XML Version.
+ if (doc != null && doc.getImplementation().hasFeature("Core","3.0")) {
+ return doc.getXmlEncoding();
+ }
+ }
+ // The default encoding is UTF-8 except for the writeToString method
+ return "UTF-8";
+ }
+
+ /**
+ * Determines the Input Encoding of the Document Node to serialize. If the Document Node
+ * is not a DOM Level 3 Node, then null is returned.
+ *
+ * @param nodeArg The Node to serialize
+ * @return A String containing the input encoding.
+ */
+ protected String getInputEncoding(Node nodeArg) {
+ Document doc = null;
+
+ // Determine the Input Encoding of the document
+ if (nodeArg != null) {
+ if (nodeArg.getNodeType() == Node.DOCUMENT_NODE) {
+ // The Document node is the Node argument
+ doc = (Document)nodeArg;
+ } else {
+ // The Document node is the Node argument's ownerDocument
+ doc = nodeArg.getOwnerDocument();
+ }
+
+ // Determine the DOM Version.
+ if (doc != null && doc.getImplementation().hasFeature("Core","3.0")) {
+ return doc.getInputEncoding();
+ }
+ }
+ // The default encoding returned is null
+ return null;
+ }
+
+ /**
+ * This method returns the LSSerializer's error handler.
+ *
+ * @return Returns the fDOMErrorHandler.
+ */
+ public DOMErrorHandler getErrorHandler() {
+ return fDOMErrorHandler;
+ }
+
+}