1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.xml.internal.serialize;
  21 
  22 import com.sun.org.apache.xerces.internal.dom.AbortException;
  23 import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
  24 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
  25 import com.sun.org.apache.xerces.internal.dom.DOMLocatorImpl;
  26 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
  27 import com.sun.org.apache.xerces.internal.dom.DOMNormalizer;
  28 import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl;
  29 import com.sun.org.apache.xerces.internal.impl.Constants;
  30 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  31 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  32 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
  33 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  34 import com.sun.org.apache.xerces.internal.util.XML11Char;
  35 import com.sun.org.apache.xerces.internal.util.XMLChar;
  36 import java.io.IOException;
  37 import java.io.OutputStream;
  38 import java.io.StringWriter;
  39 import java.io.UnsupportedEncodingException;
  40 import java.io.Writer;
  41 import java.lang.reflect.Method;
  42 import java.util.ArrayList;
  43 import java.util.List;
  44 import org.w3c.dom.Attr;
  45 import org.w3c.dom.Comment;
  46 import org.w3c.dom.DOMConfiguration;
  47 import org.w3c.dom.DOMError;
  48 import org.w3c.dom.DOMErrorHandler;
  49 import org.w3c.dom.DOMException;
  50 import org.w3c.dom.DOMStringList;
  51 import org.w3c.dom.Document;
  52 import org.w3c.dom.DocumentFragment;
  53 import org.w3c.dom.Element;
  54 import org.w3c.dom.NamedNodeMap;
  55 import org.w3c.dom.Node;
  56 import org.w3c.dom.ProcessingInstruction;
  57 import org.w3c.dom.ls.LSException;
  58 import org.w3c.dom.ls.LSOutput;
  59 import org.w3c.dom.ls.LSSerializer;
  60 import org.w3c.dom.ls.LSSerializerFilter;
  61 
  62 /**
  63  * EXPERIMENTAL: Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer by
  64  * delegating serialization calls to <CODE>XMLSerializer</CODE>. LSSerializer
  65  * provides an API for serializing (writing) a DOM document out in an XML
  66  * document. The XML data is written to an output stream. During serialization
  67  * of XML data, namespace fixup is done when possible as defined in DOM Level 3
  68  * Core, Appendix B.
  69  *
  70  * @author Elena Litani, IBM
  71  * @author Gopal Sharma, Sun Microsystems
  72  * @author Arun Yadav, Sun Microsystems
  73  * @author Sunitha Reddy, Sun Microsystems
  74  *
  75  * @deprecated As of JDK 9, Xerces 2.9.0, replaced by
  76  * {@link com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl}
  77  *
  78  * @LastModified: Oct 2017
  79  */
  80 @Deprecated
  81 public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
  82 
  83     // TODO: When DOM Level 3 goes to REC replace method calls using
  84     // reflection for: getXmlEncoding, getInputEncoding and getXmlEncoding
  85     // with regular static calls on the Document object.
  86     // data
  87     // serializer
  88     private XMLSerializer serializer;
  89 
  90     // XML 1.1 serializer
  91     private XML11Serializer xml11Serializer;
  92 
  93     //Recognized parameters
  94     private DOMStringList fRecognizedParameters;
  95 
  96     /**
  97      * REVISIT: Currently we handle 3 different configurations, would be nice
  98      * just have one configuration that has different recognized parameters
  99      * depending if it is used in Core/LS.
 100      */
 101     protected short features = 0;
 102 
 103     protected final static short NAMESPACES = 0x1 << 0;
 104     protected final static short WELLFORMED = 0x1 << 1;
 105     protected final static short ENTITIES = 0x1 << 2;
 106     protected final static short CDATA = 0x1 << 3;
 107     protected final static short SPLITCDATA = 0x1 << 4;
 108     protected final static short COMMENTS = 0x1 << 5;
 109     protected final static short DISCARDDEFAULT = 0x1 << 6;
 110     protected final static short INFOSET = 0x1 << 7;
 111     protected final static short XMLDECL = 0x1 << 8;
 112     protected final static short NSDECL = 0x1 << 9;
 113     protected final static short DOM_ELEMENT_CONTENT_WHITESPACE = 0x1 << 10;
 114     protected final static short PRETTY_PRINT = 0x1 << 11;
 115 
 116     // well-formness checking
 117     private DOMErrorHandler fErrorHandler = null;
 118     private final DOMErrorImpl fError = new DOMErrorImpl();
 119     private final DOMLocatorImpl fLocator = new DOMLocatorImpl();
 120 
 121     /**
 122      * Constructs a new LSSerializer. The constructor turns on the namespace
 123      * support in <code>XMLSerializer</code> and initializes the following
 124      * fields: fNSBinder, fLocalNSBinder, fSymbolTable, fEmptySymbol,
 125      * fXmlSymbol, fXmlnsSymbol, fNamespaceCounter, fFeatures.
 126      */
 127     public DOMSerializerImpl() {
 128         // set default features
 129         features |= NAMESPACES;
 130         features |= ENTITIES;
 131         features |= COMMENTS;
 132         features |= CDATA;
 133         features |= SPLITCDATA;
 134         features |= WELLFORMED;
 135         features |= NSDECL;
 136         features |= DOM_ELEMENT_CONTENT_WHITESPACE;
 137         features |= DISCARDDEFAULT;
 138         features |= XMLDECL;
 139 
 140         serializer = new XMLSerializer();
 141         initSerializer(serializer);
 142     }
 143 
 144     //
 145     // LSSerializer methods
 146     //
 147     public DOMConfiguration getDomConfig() {
 148         return this;
 149     }
 150 
 151     /**
 152      * DOM L3-EXPERIMENTAL: Setter for boolean and object parameters
 153      */
 154     public void setParameter(String name, Object value) throws DOMException {
 155         if (value instanceof Boolean) {
 156             boolean state = ((Boolean) value).booleanValue();
 157             if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
 158                 if (state) {
 159                     features &= ~ENTITIES;
 160                     features &= ~CDATA;
 161                     features |= NAMESPACES;
 162                     features |= NSDECL;
 163                     features |= WELLFORMED;
 164                     features |= COMMENTS;
 165                 }
 166                 // false does not have any effect
 167             } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
 168                 features
 169                         = (short) (state ? features | XMLDECL : features & ~XMLDECL);
 170             } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
 171                 features
 172                         = (short) (state
 173                         ? features | NAMESPACES
 174                         : features & ~NAMESPACES);
 175                 serializer.fNamespaces = state;
 176             } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
 177                 features
 178                         = (short) (state
 179                         ? features | SPLITCDATA
 180                         : features & ~SPLITCDATA);
 181             } else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)) {
 182                 features
 183                         = (short) (state
 184                         ? features | DISCARDDEFAULT
 185                         : features & ~DISCARDDEFAULT);
 186             } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
 187                 features
 188                         = (short) (state
 189                         ? features | WELLFORMED
 190                         : features & ~WELLFORMED);
 191             } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
 192                 features
 193                         = (short) (state
 194                         ? features | ENTITIES
 195                         : features & ~ENTITIES);
 196             } else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 197                 features
 198                         = (short) (state
 199                         ? features | CDATA
 200                         : features & ~CDATA);
 201             } else if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
 202                 features
 203                         = (short) (state
 204                         ? features | COMMENTS
 205                         : features & ~COMMENTS);
 206             } else if (name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)) {
 207                 features
 208                         = (short) (state
 209                         ? features | PRETTY_PRINT
 210                         : features & ~PRETTY_PRINT);
 211             } else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 212                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 213                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 214                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 215                     || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 216                 //  || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
 217                 // true is not supported
 218                 if (state) {
 219                     String msg
 220                             = DOMMessageFormatter.formatMessage(
 221                                     DOMMessageFormatter.DOM_DOMAIN,
 222                                     "FEATURE_NOT_SUPPORTED",
 223                                     new Object[]{name});
 224                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 225                 }
 226             } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 227                 //namespace-declaration has effect only if namespaces is true
 228                 features
 229                         = (short) (state
 230                         ? features | NSDECL
 231                         : features & ~NSDECL);
 232                 serializer.fNamespacePrefixes = state;
 233             } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 234                     || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 235                 // false is not supported
 236                 if (!state) {
 237                     String msg
 238                             = DOMMessageFormatter.formatMessage(
 239                                     DOMMessageFormatter.DOM_DOMAIN,
 240                                     "FEATURE_NOT_SUPPORTED",
 241                                     new Object[]{name});
 242                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 243                 }
 244             } else {
 245                 String msg
 246                         = DOMMessageFormatter.formatMessage(
 247                                 DOMMessageFormatter.DOM_DOMAIN,
 248                                 "FEATURE_NOT_FOUND",
 249                                 new Object[]{name});
 250                 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 251             }
 252         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 253             if (value == null || value instanceof DOMErrorHandler) {
 254                 fErrorHandler = (DOMErrorHandler) value;
 255             } else {
 256                 String msg
 257                         = DOMMessageFormatter.formatMessage(
 258                                 DOMMessageFormatter.DOM_DOMAIN,
 259                                 "TYPE_MISMATCH_ERR",
 260                                 new Object[]{name});
 261                 throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 262             }
 263         } else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
 264                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
 265                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)
 266                 || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 267                 && value != null) {
 268             String msg
 269                     = DOMMessageFormatter.formatMessage(
 270                             DOMMessageFormatter.DOM_DOMAIN,
 271                             "FEATURE_NOT_SUPPORTED",
 272                             new Object[]{name});
 273             throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 274         } else {
 275             String msg
 276                     = DOMMessageFormatter.formatMessage(
 277                             DOMMessageFormatter.DOM_DOMAIN,
 278                             "FEATURE_NOT_FOUND",
 279                             new Object[]{name});
 280             throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 281         }
 282     }
 283 
 284     /**
 285      * DOM L3-EXPERIMENTAL: Check if parameter can be set
 286      */
 287     public boolean canSetParameter(String name, Object state) {
 288         if (state == null) {
 289             return true;
 290         }
 291 
 292         if (state instanceof Boolean) {
 293             boolean value = ((Boolean) state).booleanValue();
 294             if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)
 295                 || name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)
 296                 || name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)
 297                 || name.equalsIgnoreCase(Constants.DOM_XMLDECL)
 298                 || name.equalsIgnoreCase(Constants.DOM_WELLFORMED)
 299                 || name.equalsIgnoreCase(Constants.DOM_INFOSET)
 300                 || name.equalsIgnoreCase(Constants.DOM_ENTITIES)
 301                 || name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)
 302                 || name.equalsIgnoreCase(Constants.DOM_COMMENTS)
 303                 || name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)
 304                 || name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 305                 // both values supported
 306                 return true;
 307             } else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 308                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 309                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 310                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 311                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 312                 // || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
 313                 // true is not supported
 314                 return !value;
 315             } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 316                 || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 317                 // false is not supported
 318                 return value;
 319             }
 320         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)
 321                 && state == null || state instanceof DOMErrorHandler) {
 322             return true;
 323         }
 324 
 325         return false;
 326     }
 327 
 328     /**
 329      * DOM Level 3 Core CR - Experimental.
 330      *
 331      * The list of the parameters supported by this
 332      * <code>DOMConfiguration</code> object and for which at least one value can
 333      * be set by the application. Note that this list can also contain parameter
 334      * names defined outside this specification.
 335      */
 336     public DOMStringList getParameterNames() {
 337 
 338         if (fRecognizedParameters == null) {
 339             List<String> parameters = new ArrayList<>();
 340 
 341             //Add DOM recognized parameters
 342             //REVISIT: Would have been nice to have a list of
 343             //recognized parameters.
 344             parameters.add(Constants.DOM_NAMESPACES);
 345             parameters.add(Constants.DOM_SPLIT_CDATA);
 346             parameters.add(Constants.DOM_DISCARD_DEFAULT_CONTENT);
 347             parameters.add(Constants.DOM_XMLDECL);
 348             parameters.add(Constants.DOM_CANONICAL_FORM);
 349             parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
 350             parameters.add(Constants.DOM_VALIDATE);
 351             parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
 352             parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
 353             parameters.add(Constants.DOM_FORMAT_PRETTY_PRINT);
 354             //parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
 355             parameters.add(Constants.DOM_WELLFORMED);
 356             parameters.add(Constants.DOM_INFOSET);
 357             parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
 358             parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
 359             parameters.add(Constants.DOM_ENTITIES);
 360             parameters.add(Constants.DOM_CDATA_SECTIONS);
 361             parameters.add(Constants.DOM_COMMENTS);
 362             parameters.add(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS);
 363             parameters.add(Constants.DOM_ERROR_HANDLER);
 364             //parameters.add(Constants.DOM_SCHEMA_LOCATION);
 365             //parameters.add(Constants.DOM_SCHEMA_TYPE);
 366 
 367             //Add recognized xerces features and properties
 368             fRecognizedParameters = new DOMStringListImpl(parameters);
 369         }
 370 
 371         return fRecognizedParameters;
 372     }
 373 
 374     /**
 375      * DOM L3-EXPERIMENTAL: Getter for boolean and object parameters
 376      */
 377     public Object getParameter(String name) throws DOMException {
 378         if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
 379             return null;
 380         } else if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
 381             return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
 382         } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
 383             return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
 384         } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
 385             return (features & XMLDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
 386         } else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 387             return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
 388         } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
 389             return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
 390         } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
 391             return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
 392         } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
 393             return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
 394         } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 395             return (features & NSDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
 396         } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 397                 || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 398             return Boolean.TRUE;
 399         } else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)) {
 400             return ((features & DISCARDDEFAULT) != 0) ? Boolean.TRUE : Boolean.FALSE;
 401         } else if (name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)) {
 402             return ((features & PRETTY_PRINT) != 0) ? Boolean.TRUE : Boolean.FALSE;
 403         } else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
 404             if ((features & ENTITIES) == 0
 405                     && (features & CDATA) == 0
 406                     && (features & NAMESPACES) != 0
 407                     && (features & NSDECL) != 0
 408                     && (features & WELLFORMED) != 0
 409                     && (features & COMMENTS) != 0) {
 410                 return Boolean.TRUE;
 411             }
 412             return Boolean.FALSE;
 413         } else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 414                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 415                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 416                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 417                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 418                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 419             return Boolean.FALSE;
 420         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 421             return fErrorHandler;
 422         } else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
 423                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
 424                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
 425             String msg
 426                     = DOMMessageFormatter.formatMessage(
 427                             DOMMessageFormatter.DOM_DOMAIN,
 428                             "FEATURE_NOT_SUPPORTED",
 429                             new Object[]{name});
 430             throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 431         } else {
 432             String msg
 433                     = DOMMessageFormatter.formatMessage(
 434                             DOMMessageFormatter.DOM_DOMAIN,
 435                             "FEATURE_NOT_FOUND",
 436                             new Object[]{name});
 437             throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 438         }
 439     }
 440 
 441     /**
 442      * DOM L3 EXPERIMENTAL: Serialize the specified node as described above in
 443      * the description of <code>LSSerializer</code>. The result of serializing
 444      * the node is returned as a string. Writing a Document or Entity node
 445      * produces a serialized form that is well formed XML. Writing other node
 446      * types produces a fragment of text in a form that is not fully defined by
 447      * this document, but that should be useful to a human for debugging or
 448      * diagnostic purposes.
 449      *
 450      * @param wnode The node to be written.
 451      * @return Returns the serialized data
 452      * @exception DOMException DOMSTRING_SIZE_ERR: The resulting string is too
 453      * long to fit in a <code>DOMString</code>.
 454      * @exception LSException SERIALIZE_ERR: Unable to serialize the node. DOM
 455      * applications should attach a <code>DOMErrorHandler</code> using the
 456      * parameter &quot;<i>error-handler</i>&quot; to get details on error.
 457      */
 458     public String writeToString(Node wnode) throws DOMException, LSException {
 459         // determine which serializer to use:
 460         XMLSerializer ser = null;
 461         String ver = _getXmlVersion(wnode);
 462         if (ver != null && ver.equals("1.1")) {
 463             if (xml11Serializer == null) {
 464                 xml11Serializer = new XML11Serializer();
 465                 initSerializer(xml11Serializer);
 466             }
 467             // copy setting from "main" serializer to XML 1.1 serializer
 468             copySettings(serializer, xml11Serializer);
 469             ser = xml11Serializer;
 470         } else {
 471             ser = serializer;
 472         }
 473 
 474         StringWriter destination = new StringWriter();
 475         try {
 476             prepareForSerialization(ser, wnode);
 477             ser._format.setEncoding("UTF-16");
 478             ser.setOutputCharStream(destination);
 479             if (wnode.getNodeType() == Node.DOCUMENT_NODE) {
 480                 ser.serialize((Document) wnode);
 481             } else if (wnode.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
 482                 ser.serialize((DocumentFragment) wnode);
 483             } else if (wnode.getNodeType() == Node.ELEMENT_NODE) {
 484                 ser.serialize((Element) wnode);
 485             } else if (wnode.getNodeType() == Node.TEXT_NODE
 486                     || wnode.getNodeType() == Node.COMMENT_NODE
 487                     || wnode.getNodeType() == Node.ENTITY_REFERENCE_NODE
 488                     || wnode.getNodeType() == Node.CDATA_SECTION_NODE
 489                     || wnode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
 490                 ser.serialize(wnode);
 491             } else {
 492                 String msg = DOMMessageFormatter.formatMessage(
 493                         DOMMessageFormatter.SERIALIZER_DOMAIN,
 494                         "unable-to-serialize-node", null);
 495                 if (ser.fDOMErrorHandler != null) {
 496                     DOMErrorImpl error = new DOMErrorImpl();
 497                     error.fType = "unable-to-serialize-node";
 498                     error.fMessage = msg;
 499                     error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 500                     ser.fDOMErrorHandler.handleError(error);
 501                 }
 502                 throw new LSException(LSException.SERIALIZE_ERR, msg);
 503             }
 504         } catch (LSException lse) {
 505             // Rethrow LSException.
 506             throw lse;
 507         } catch (AbortException e) {
 508             return null;
 509         } catch (RuntimeException e) {
 510             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 511         } catch (IOException ioe) {
 512             // REVISIT: A generic IOException doesn't provide enough information
 513             // to determine that the serialized document is too large to fit
 514             // into a string. This could have thrown for some other reason. -- mrglavas
 515             String msg = DOMMessageFormatter.formatMessage(
 516                     DOMMessageFormatter.DOM_DOMAIN,
 517                     "STRING_TOO_LONG",
 518                     new Object[]{ioe.getMessage()});
 519             throw new DOMException(DOMException.DOMSTRING_SIZE_ERR, msg);
 520         } finally {
 521             ser.clearDocumentState();
 522         }
 523         return destination.toString();
 524     }
 525 
 526     /**
 527      * DOM L3 EXPERIMENTAL: The end-of-line sequence of characters to be used in
 528      * the XML being written out. The only permitted values are these:
 529      * <dl>
 530      * <dt><code>null</code></dt>
 531      * <dd>
 532      * Use a default end-of-line sequence. DOM implementations should choose the
 533      * default to match the usual convention for text files in the environment
 534      * being used. Implementations must choose a default sequence that matches
 535      * one of those allowed by 2.11 "End-of-Line Handling". </dd>
 536      * <dt>CR</dt>
 537      * <dd>The carriage-return character (#xD).</dd>
 538      * <dt>CR-LF</dt>
 539      * <dd> The carriage-return and line-feed characters (#xD #xA). </dd>
 540      * <dt>LF</dt>
 541      * <dd> The line-feed character (#xA). </dd>
 542      * </dl>
 543      * <br>The default value for this attribute is <code>null</code>.
 544      */
 545     public void setNewLine(String newLine) {
 546         serializer._format.setLineSeparator(newLine);
 547     }
 548 
 549     /**
 550      * DOM L3 EXPERIMENTAL: The end-of-line sequence of characters to be used in
 551      * the XML being written out. The only permitted values are these:
 552      * <dl>
 553      * <dt><code>null</code></dt>
 554      * <dd>
 555      * Use a default end-of-line sequence. DOM implementations should choose the
 556      * default to match the usual convention for text files in the environment
 557      * being used. Implementations must choose a default sequence that matches
 558      * one of those allowed by 2.11 "End-of-Line Handling". </dd>
 559      * <dt>CR</dt>
 560      * <dd>The carriage-return character (#xD).</dd>
 561      * <dt>CR-LF</dt>
 562      * <dd> The carriage-return and line-feed characters (#xD #xA). </dd>
 563      * <dt>LF</dt>
 564      * <dd> The line-feed character (#xA). </dd>
 565      * </dl>
 566      * <br>The default value for this attribute is <code>null</code>.
 567      */
 568     public String getNewLine() {
 569         return serializer._format.getLineSeparator();
 570     }
 571 
 572     /**
 573      * When the application provides a filter, the serializer will call out to
 574      * the filter before serializing each Node. Attribute nodes are never passed
 575      * to the filter. The filter implementation can choose to remove the node
 576      * from the stream or to terminate the serialization early.
 577      */
 578     public LSSerializerFilter getFilter() {
 579         return serializer.fDOMFilter;
 580     }
 581 
 582     /**
 583      * When the application provides a filter, the serializer will call out to
 584      * the filter before serializing each Node. Attribute nodes are never passed
 585      * to the filter. The filter implementation can choose to remove the node
 586      * from the stream or to terminate the serialization early.
 587      */
 588     public void setFilter(LSSerializerFilter filter) {
 589         serializer.fDOMFilter = filter;
 590     }
 591 
 592     // this initializes a newly-created serializer
 593     private void initSerializer(XMLSerializer ser) {
 594         ser.fNSBinder = new NamespaceSupport();
 595         ser.fLocalNSBinder = new NamespaceSupport();
 596         ser.fSymbolTable = new SymbolTable();
 597     }
 598 
 599     // copies all settings that could have been modified
 600     // by calls to LSSerializer methods from one serializer to another.
 601     // IMPORTANT:  if new methods are implemented or more settings of
 602     // the serializer are made alterable, this must be
 603     // reflected in this method!
 604     private void copySettings(XMLSerializer src, XMLSerializer dest) {
 605         dest.fDOMErrorHandler = fErrorHandler;
 606         dest._format.setEncoding(src._format.getEncoding());
 607         dest._format.setLineSeparator(src._format.getLineSeparator());
 608         dest.fDOMFilter = src.fDOMFilter;
 609     }//copysettings
 610 
 611     /**
 612      * Serialize the specified node as described above in the general
 613      * description of the <code>LSSerializer</code> interface. The output is
 614      * written to the supplied <code>LSOutput</code>.
 615      * <br> When writing to a <code>LSOutput</code>, the encoding is found by
 616      * looking at the encoding information that is reachable through the
 617      * <code>LSOutput</code> and the item to be written (or its owner document)
 618      * in this order:
 619      * <ol>
 620      * <li> <code>LSOutput.encoding</code>,
 621      * </li>
 622      * <li>
 623      * <code>Document.actualEncoding</code>,
 624      * </li>
 625      * <li>
 626      * <code>Document.xmlEncoding</code>.
 627      * </li>
 628      * </ol>
 629      * <br> If no encoding is reachable through the above properties, a default
 630      * encoding of "UTF-8" will be used.
 631      * <br> If the specified encoding is not supported an "unsupported-encoding"
 632      * error is raised.
 633      * <br> If no output is specified in the <code>LSOutput</code>, a
 634      * "no-output-specified" error is raised.
 635      *
 636      * @param node The node to serialize.
 637      * @param destination The destination for the serialized DOM.
 638      * @return Returns <code>true</code> if <code>node</code> was successfully
 639      * serialized and <code>false</code> in case the node couldn't be
 640      * serialized.
 641      */
 642     public boolean write(Node node, LSOutput destination) throws LSException {
 643 
 644         if (node == null) {
 645             return false;
 646         }
 647 
 648         XMLSerializer ser = null;
 649         String ver = _getXmlVersion(node);
 650         //determine which serializer to use:
 651         if (ver != null && ver.equals("1.1")) {
 652             if (xml11Serializer == null) {
 653                 xml11Serializer = new XML11Serializer();
 654                 initSerializer(xml11Serializer);
 655             }
 656             //copy setting from "main" serializer to XML 1.1 serializer
 657             copySettings(serializer, xml11Serializer);
 658             ser = xml11Serializer;
 659         } else {
 660             ser = serializer;
 661         }
 662 
 663         String encoding = null;
 664         if ((encoding = destination.getEncoding()) == null) {
 665             encoding = _getInputEncoding(node);
 666             if (encoding == null) {
 667                 encoding = _getXmlEncoding(node);
 668                 if (encoding == null) {
 669                     encoding = "UTF-8";
 670                 }
 671             }
 672         }
 673         try {
 674             prepareForSerialization(ser, node);
 675             ser._format.setEncoding(encoding);
 676             OutputStream outputStream = destination.getByteStream();
 677             Writer writer = destination.getCharacterStream();
 678             String uri = destination.getSystemId();
 679             if (writer == null) {
 680                 if (outputStream == null) {
 681                     if (uri == null) {
 682                         String msg = DOMMessageFormatter.formatMessage(
 683                                 DOMMessageFormatter.SERIALIZER_DOMAIN,
 684                                 "no-output-specified", null);
 685                         if (ser.fDOMErrorHandler != null) {
 686                             DOMErrorImpl error = new DOMErrorImpl();
 687                             error.fType = "no-output-specified";
 688                             error.fMessage = msg;
 689                             error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 690                             ser.fDOMErrorHandler.handleError(error);
 691                         }
 692                         throw new LSException(LSException.SERIALIZE_ERR, msg);
 693                     } else {
 694                         ser.setOutputByteStream(XMLEntityManager.createOutputStream(uri));
 695                     }
 696                 } else {
 697                     // byte stream was specified
 698                     ser.setOutputByteStream(outputStream);
 699                 }
 700             } else {
 701                 // character stream is specified
 702                 ser.setOutputCharStream(writer);
 703             }
 704 
 705             if (node.getNodeType() == Node.DOCUMENT_NODE) {
 706                 ser.serialize((Document) node);
 707             } else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
 708                 ser.serialize((DocumentFragment) node);
 709             } else if (node.getNodeType() == Node.ELEMENT_NODE) {
 710                 ser.serialize((Element) node);
 711             } else if (node.getNodeType() == Node.TEXT_NODE
 712                     || node.getNodeType() == Node.COMMENT_NODE
 713                     || node.getNodeType() == Node.ENTITY_REFERENCE_NODE
 714                     || node.getNodeType() == Node.CDATA_SECTION_NODE
 715                     || node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
 716                 ser.serialize(node);
 717             } else {
 718                 return false;
 719             }
 720         } catch (UnsupportedEncodingException ue) {
 721             if (ser.fDOMErrorHandler != null) {
 722                 DOMErrorImpl error = new DOMErrorImpl();
 723                 error.fException = ue;
 724                 error.fType = "unsupported-encoding";
 725                 error.fMessage = ue.getMessage();
 726                 error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 727                 ser.fDOMErrorHandler.handleError(error);
 728             }
 729             throw new LSException(LSException.SERIALIZE_ERR,
 730                     DOMMessageFormatter.formatMessage(
 731                             DOMMessageFormatter.SERIALIZER_DOMAIN,
 732                             "unsupported-encoding", null));
 733             //return false;
 734         } catch (LSException lse) {
 735             // Rethrow LSException.
 736             throw lse;
 737         } catch (AbortException e) {
 738             return false;
 739         } catch (RuntimeException e) {
 740             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 741         } catch (Exception e) {
 742             if (ser.fDOMErrorHandler != null) {
 743                 DOMErrorImpl error = new DOMErrorImpl();
 744                 error.fException = e;
 745                 error.fMessage = e.getMessage();
 746                 error.fSeverity = DOMError.SEVERITY_ERROR;
 747                 ser.fDOMErrorHandler.handleError(error);
 748 
 749             }
 750             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 751         } finally {
 752             ser.clearDocumentState();
 753         }
 754         return true;
 755 
 756     } //write
 757 
 758     /**
 759      * Serialize the specified node as described above in the general
 760      * description of the <code>LSSerializer</code> interface. The output is
 761      * written to the supplied URI.
 762      * <br> When writing to a URI, the encoding is found by looking at the
 763      * encoding information that is reachable through the item to be written (or
 764      * its owner document) in this order:
 765      * <ol>
 766      * <li>
 767      * <code>Document.inputEncoding</code>,
 768      * </li>
 769      * <li>
 770      * <code>Document.xmlEncoding</code>.
 771      * </li>
 772      * </ol>
 773      * <br> If no encoding is reachable through the above properties, a default
 774      * encoding of "UTF-8" will be used.
 775      * <br> If the specified encoding is not supported an "unsupported-encoding"
 776      * error is raised.
 777      *
 778      * @param node The node to serialize.
 779      * @param URI The URI to write to.
 780      * @return Returns <code>true</code> if <code>node</code> was successfully
 781      * serialized and <code>false</code> in case the node couldn't be
 782      * serialized.
 783      */
 784     public boolean writeToURI(Node node, String URI) throws LSException {
 785         if (node == null) {
 786             return false;
 787         }
 788 
 789         XMLSerializer ser = null;
 790         String ver = _getXmlVersion(node);
 791 
 792         if (ver != null && ver.equals("1.1")) {
 793             if (xml11Serializer == null) {
 794                 xml11Serializer = new XML11Serializer();
 795                 initSerializer(xml11Serializer);
 796             }
 797             // copy setting from "main" serializer to XML 1.1 serializer
 798             copySettings(serializer, xml11Serializer);
 799             ser = xml11Serializer;
 800         } else {
 801             ser = serializer;
 802         }
 803 
 804         String encoding = _getInputEncoding(node);
 805         if (encoding == null) {
 806             encoding = _getXmlEncoding(node);
 807             if (encoding == null) {
 808                 encoding = "UTF-8";
 809             }
 810         }
 811 
 812         try {
 813             prepareForSerialization(ser, node);
 814             ser._format.setEncoding(encoding);
 815             ser.setOutputByteStream(XMLEntityManager.createOutputStream(URI));
 816 
 817             if (node.getNodeType() == Node.DOCUMENT_NODE) {
 818                 ser.serialize((Document) node);
 819             } else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
 820                 ser.serialize((DocumentFragment) node);
 821             } else if (node.getNodeType() == Node.ELEMENT_NODE) {
 822                 ser.serialize((Element) node);
 823             } else if (node.getNodeType() == Node.TEXT_NODE
 824                     || node.getNodeType() == Node.COMMENT_NODE
 825                     || node.getNodeType() == Node.ENTITY_REFERENCE_NODE
 826                     || node.getNodeType() == Node.CDATA_SECTION_NODE
 827                     || node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
 828                 ser.serialize(node);
 829             } else {
 830                 return false;
 831             }
 832         } catch (LSException lse) {
 833             // Rethrow LSException.
 834             throw lse;
 835         } catch (AbortException e) {
 836             return false;
 837         } catch (RuntimeException e) {
 838             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 839         } catch (Exception e) {
 840             if (ser.fDOMErrorHandler != null) {
 841                 DOMErrorImpl error = new DOMErrorImpl();
 842                 error.fException = e;
 843                 error.fMessage = e.getMessage();
 844                 error.fSeverity = DOMError.SEVERITY_ERROR;
 845                 ser.fDOMErrorHandler.handleError(error);
 846             }
 847             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 848         } finally {
 849             ser.clearDocumentState();
 850         }
 851         return true;
 852     } //writeURI
 853 
 854     //
 855     //  Private methods
 856     //
 857     private void prepareForSerialization(XMLSerializer ser, Node node) {
 858         ser.reset();
 859         ser.features = features;
 860         ser.fDOMErrorHandler = fErrorHandler;
 861         ser.fNamespaces = (features & NAMESPACES) != 0;
 862         ser.fNamespacePrefixes = (features & NSDECL) != 0;
 863         ser._format.setIndenting((features & PRETTY_PRINT) != 0);
 864         ser._format.setOmitComments((features & COMMENTS) == 0);
 865         ser._format.setOmitXMLDeclaration((features & XMLDECL) == 0);
 866 
 867         if ((features & WELLFORMED) != 0) {
 868             // REVISIT: this is inefficient implementation of well-formness. Instead, we should check
 869             // well-formness as we serialize the tree
 870             Node next, root;
 871             root = node;
 872             Method versionChanged;
 873             boolean verifyNames = true;
 874             Document document = (node.getNodeType() == Node.DOCUMENT_NODE)
 875                     ? (Document) node
 876                     : node.getOwnerDocument();
 877             try {
 878                 versionChanged = document.getClass().getMethod("isXMLVersionChanged()", new Class<?>[]{});
 879                 if (versionChanged != null) {
 880                     verifyNames = ((Boolean) versionChanged.invoke(document, (Object[]) null)).booleanValue();
 881                 }
 882             } catch (Exception e) {
 883                 //no way to test the version...
 884                 //ignore the exception
 885             }
 886             if (node.getFirstChild() != null) {
 887                 while (node != null) {
 888                     verify(node, verifyNames, false);
 889                     // Move down to first child
 890                     next = node.getFirstChild();
 891                     // No child nodes, so walk tree
 892                     while (next == null) {
 893                         // Move to sibling if possible.
 894                         next = node.getNextSibling();
 895                         if (next == null) {
 896                             node = node.getParentNode();
 897                             if (root == node) {
 898                                 next = null;
 899                                 break;
 900                             }
 901                             next = node.getNextSibling();
 902                         }
 903                     }
 904                     node = next;
 905                 }
 906             } else {
 907                 verify(node, verifyNames, false);
 908             }
 909         }
 910     }
 911 
 912     private void verify(Node node, boolean verifyNames, boolean xml11Version) {
 913 
 914         int type = node.getNodeType();
 915         fLocator.fRelatedNode = node;
 916         boolean wellformed;
 917         switch (type) {
 918             case Node.DOCUMENT_NODE: {
 919                 break;
 920             }
 921             case Node.DOCUMENT_TYPE_NODE: {
 922                 break;
 923             }
 924             case Node.ELEMENT_NODE: {
 925                 if (verifyNames) {
 926                     if ((features & NAMESPACES) != 0) {
 927                         wellformed = CoreDocumentImpl.isValidQName(node.getPrefix(), node.getLocalName(), xml11Version);
 928                     } else {
 929                         wellformed = CoreDocumentImpl.isXMLName(node.getNodeName(), xml11Version);
 930                     }
 931                     if (!wellformed) {
 932                         if (fErrorHandler != null) {
 933                             String msg = DOMMessageFormatter.formatMessage(
 934                                     DOMMessageFormatter.DOM_DOMAIN,
 935                                     "wf-invalid-character-in-node-name",
 936                                     new Object[]{"Element", node.getNodeName()});
 937                             DOMNormalizer.reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
 938                                     "wf-invalid-character-in-node-name");
 939                         }
 940                     }
 941                 }
 942 
 943                 NamedNodeMap attributes = (node.hasAttributes()) ? node.getAttributes() : null;
 944                 if (attributes != null) {
 945                     for (int i = 0; i < attributes.getLength(); ++i) {
 946                         Attr attr = (Attr) attributes.item(i);
 947                         fLocator.fRelatedNode = attr;
 948                         DOMNormalizer.isAttrValueWF(fErrorHandler, fError, fLocator,
 949                                 attributes, attr, attr.getValue(), xml11Version);
 950                         if (verifyNames) {
 951                             wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), xml11Version);
 952                             if (!wellformed) {
 953                                 String msg
 954                                         = DOMMessageFormatter.formatMessage(
 955                                                 DOMMessageFormatter.DOM_DOMAIN,
 956                                                 "wf-invalid-character-in-node-name",
 957                                                 new Object[]{"Attr", node.getNodeName()});
 958                                 DOMNormalizer.reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
 959                                         "wf-invalid-character-in-node-name");
 960                             }
 961                         }
 962                     }
 963 
 964                 }
 965 
 966                 break;
 967             }
 968 
 969             case Node.COMMENT_NODE: {
 970                 // only verify well-formness if comments included in the tree
 971                 if ((features & COMMENTS) != 0) {
 972                     DOMNormalizer.isCommentWF(fErrorHandler, fError, fLocator, ((Comment) node).getData(), xml11Version);
 973                 }
 974                 break;
 975             }
 976             case Node.ENTITY_REFERENCE_NODE: {
 977                 // only if entity is preserved in the tree
 978                 if (verifyNames && (features & ENTITIES) != 0) {
 979                     CoreDocumentImpl.isXMLName(node.getNodeName(), xml11Version);
 980                 }
 981                 break;
 982 
 983             }
 984             case Node.CDATA_SECTION_NODE: {
 985                 // verify content
 986                 DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), xml11Version);
 987                 // the ]]> string will be checked during serialization
 988                 break;
 989             }
 990             case Node.TEXT_NODE: {
 991                 DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), xml11Version);
 992                 break;
 993             }
 994             case Node.PROCESSING_INSTRUCTION_NODE: {
 995                 ProcessingInstruction pinode = (ProcessingInstruction) node;
 996                 String target = pinode.getTarget();
 997                 if (verifyNames) {
 998                     if (xml11Version) {
 999                         wellformed = XML11Char.isXML11ValidName(target);
1000                     } else {
1001                         wellformed = XMLChar.isValidName(target);
1002                     }
1003 
1004                     if (!wellformed) {
1005                         String msg
1006                                 = DOMMessageFormatter.formatMessage(
1007                                         DOMMessageFormatter.DOM_DOMAIN,
1008                                         "wf-invalid-character-in-node-name",
1009                                         new Object[]{"Element", node.getNodeName()});
1010                         DOMNormalizer.reportDOMError(
1011                                 fErrorHandler,
1012                                 fError,
1013                                 fLocator,
1014                                 msg,
1015                                 DOMError.SEVERITY_FATAL_ERROR,
1016                                 "wf-invalid-character-in-node-name");
1017                     }
1018                 }
1019                 DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), xml11Version);
1020                 break;
1021             }
1022         }
1023         fLocator.fRelatedNode = null;
1024     }
1025 
1026     private String _getXmlVersion(Node node) {
1027         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE)
1028                 ? (Document) node : node.getOwnerDocument();
1029         if (doc != null) {
1030             try {
1031                 return doc.getXmlVersion();
1032             } // The VM ran out of memory or there was some other serious problem. Re-throw.
1033              catch (VirtualMachineError | ThreadDeath vme) {
1034                 throw vme;
1035             } // Ignore all other exceptions and errors
1036             catch (Throwable t) {
1037             }
1038         }
1039         return null;
1040     }
1041 
1042     private String _getInputEncoding(Node node) {
1043         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE)
1044                 ? (Document) node : node.getOwnerDocument();
1045         if (doc != null) {
1046             try {
1047                 return doc.getInputEncoding();
1048             } // The VM ran out of memory or there was some other serious problem. Re-throw.
1049             catch (VirtualMachineError | ThreadDeath vme) {
1050                 throw vme;
1051             } // Ignore all other exceptions and errors
1052             catch (Throwable t) {
1053             }
1054         }
1055         return null;
1056     }
1057 
1058     private String _getXmlEncoding(Node node) {
1059         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE)
1060                 ? (Document) node : node.getOwnerDocument();
1061         if (doc != null) {
1062             try {
1063                 return doc.getXmlEncoding();
1064             } // The VM ran out of memory or there was some other serious problem. Re-throw.
1065             catch (VirtualMachineError | ThreadDeath vme) {
1066                 throw vme;
1067             } // Ignore all other exceptions and errors
1068             catch (Throwable t) {
1069             }
1070         }
1071         return null;
1072     }
1073 
1074 } //DOMSerializerImpl