/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2002, International
 * Business Machines, Inc., http://www.apache.org.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */



package org.apache.xml.serialize;

import java.io.IOException;
import java.io.StringWriter;
import java.io.OutputStream;
import java.io.Writer;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.xerces.dom.DOMErrorImpl;
import org.apache.xerces.dom.DOMMessageFormatter;
import org.apache.xerces.dom3.DOMConfiguration;
import org.apache.xerces.dom3.DOMError;
import org.apache.xerces.dom3.DOMErrorHandler;
import org.apache.xerces.dom3.DOMStringList;

import org.apache.xerces.impl.Constants;
import org.apache.xerces.util.NamespaceSupport;
import org.apache.xerces.util.SymbolTable;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.ls.LSSerializerFilter;
import org.w3c.dom.ls.LSOutput;


/**
 * Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer  by delegating serialization
 * calls to <CODE>XMLSerializer</CODE>.
 * LSSerializer provides an API for serializing (writing) a DOM document out in an
 * XML document. The XML data is written to an output stream.
 * During serialization of XML data, namespace fixup is done when possible as
 * defined in DOM Level 3 Core, Appendix B.
 *
 * @author Elena Litani, IBM
 * @author Gopal Sharma, Sun Microsystems
 * @author Arun Yadav, Sun Microsystems
 * @version $Id$
 */
public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {

    // data
    // serializer
    private XMLSerializer serializer;

    // XML 1.1 serializer
    private XML11Serializer xml11Serializer;

    /**
     * Constructs a new LSSerializer.
     * The constructor turns on the namespace support in <code>XMLSerializer</code> and
     * initializes the following fields: fNSBinder, fLocalNSBinder, fSymbolTable,
     * fEmptySymbol, fXmlSymbol, fXmlnsSymbol, fNamespaceCounter, fFeatures.
     */
    public DOMSerializerImpl() {
        serializer = new XMLSerializer();
        initSerializer(serializer);
    }



    //
    // LSSerializer methods
    //

    public DOMConfiguration getConfig(){
        return this;
    }

    /** DOM L3-EXPERIMENTAL:
     * Setter for boolean and object parameters
     */
	public void setParameter(String name, Object value) throws DOMException {
		if (serializer.fFeatures.containsKey(name)) {
			// This is a feature
			if (value instanceof Boolean){
				boolean state = ((Boolean)value).booleanValue();
				if (name.equals(Constants.DOM_XMLDECL)){
					serializer._format.setOmitXMLDeclaration(!state);
					serializer.fFeatures.put(name, value);
				}
				else if (name.equals(Constants.DOM_NAMESPACES)){
					serializer.fNamespaces = state;
					serializer.fFeatures.put(name, value);
				}
				else if (name.equals(Constants.DOM_SPLIT_CDATA)
				|| name.equals(Constants.DOM_DISCARD_DEFAULT_CONTENT)){
					// both values supported
					serializer.fFeatures.put(name, value);
				}
				else if (name.equals(Constants.DOM_CANONICAL_FORM)
					|| name.equals(Constants.DOM_VALIDATE_IF_SCHEMA)
					|| name.equals(Constants.DOM_VALIDATE)
					|| name.equals(Constants.DOM_CHECK_CHAR_NORMALIZATION)
					|| name.equals(Constants.DOM_DATATYPE_NORMALIZATION)
					|| name.equals(Constants.DOM_FORMAT_PRETTY_PRINT)
					|| name.equals(Constants.DOM_NORMALIZE_CHARACTERS)
					// REVISIT: these must be supported
					|| name.equals(Constants.DOM_WELLFORMED)) {
					// true is not supported
					if (state){
						String msg = DOMMessageFormatter.formatMessage(
								DOMMessageFormatter.DOM_DOMAIN,
								"FEATURE_NOT_SUPPORTED",
								new Object[] { name });
						throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
					}
				}
				else if (name.equals(Constants.DOM_INFOSET)
						|| name.equals(Constants.DOM_NAMESPACE_DECLARATIONS)
						|| name.equals(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT)
						|| name.equals(Constants.DOM_IGNORE_CHAR_DENORMALIZATION)
						// REVISIT: these must be supported
						|| name.equals(Constants.DOM_ENTITIES)
						|| name.equals(Constants.DOM_CDATA_SECTIONS)
						|| name.equals(Constants.DOM_COMMENTS)) {
					// false is not supported
					if (!state){
						String msg = DOMMessageFormatter.formatMessage(
								DOMMessageFormatter.DOM_DOMAIN,
								"FEATURE_NOT_SUPPORTED",
								new Object[] { name });
						throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
					}
				}
				else {
					String msg = DOMMessageFormatter.formatMessage(
							DOMMessageFormatter.DOM_DOMAIN,
							"FEATURE_NOT_FOUND",
							new Object[] { name });
                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
				}
			}
			else {

			 // REVISIT: modify error exception to TYPE_MISMATCH
 			String msg = DOMMessageFormatter.formatMessage(
			 DOMMessageFormatter.DOM_DOMAIN,
			 "TYPE_MISMATCH_ERR",
			 new Object[] { name });
			throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
		}
	}
	else if (name.equals(Constants.DOM_ERROR_HANDLER)) {
			if (value instanceof DOMErrorHandler) {
				serializer.fDOMErrorHandler = (DOMErrorHandler) value;
			}
			else {
				// REVISIT: modify error exception to TYPE_MISMATCH
                String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "TYPE_MISMATCH_ERR",
                            new Object[] { name });
               throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
			}
		}
		else if (name.equals(Constants.DOM_RESOURCE_RESOLVER)
				|| name.equals(Constants.DOM_SCHEMA_LOCATION)
				|| name.equals(Constants.DOM_SCHEMA_TYPE)) {
                String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "FEATURE_NOT_SUPPORTED",
                            new Object[] { name });
               throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
		}
		else {
                String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "FEATURE_NOT_FOUND",
                            new Object[] { name });
                throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
        }
	}

    /** DOM L3-EXPERIMENTAL:
     * Check if parameter can be set
     */
	public boolean canSetParameter(String name, Object state) {
		if (state instanceof Boolean){
			boolean value = ((Boolean)state).booleanValue();
			if (name.equals(Constants.DOM_NAMESPACES)
			|| name.equals(Constants.DOM_SPLIT_CDATA)
			|| name.equals(Constants.DOM_DISCARD_DEFAULT_CONTENT)
			|| name.equals(Constants.DOM_XMLDECL)){
	            // both values supported
				return true;
			}
			else if (name.equals(Constants.DOM_CANONICAL_FORM)
			    || name.equals(Constants.DOM_VALIDATE_IF_SCHEMA)
			    || name.equals(Constants.DOM_VALIDATE)
			    || name.equals(Constants.DOM_CHECK_CHAR_NORMALIZATION)
			    || name.equals(Constants.DOM_DATATYPE_NORMALIZATION)
			    || name.equals(Constants.DOM_FORMAT_PRETTY_PRINT)
			    || name.equals(Constants.DOM_NORMALIZE_CHARACTERS)
			    // REVISIT: these must be supported
			    || name.equals(Constants.DOM_WELLFORMED)) {
				// true is not supported
				return !value;
			}
			else if (name.equals(Constants.DOM_INFOSET)
					|| name.equals(Constants.DOM_NAMESPACE_DECLARATIONS)
			        || name.equals(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT)
			        || name.equals(Constants.DOM_IGNORE_CHAR_DENORMALIZATION)
			        // REVISIT: these must be supported
			        || name.equals(Constants.DOM_ENTITIES)
					|| name.equals(Constants.DOM_CDATA_SECTIONS)
					|| name.equals(Constants.DOM_COMMENTS)) {
				// false is not supported
				return value;
			        }
		}
		else if (name.equals(Constants.DOM_ERROR_HANDLER)){
			return true;
		}
	    return false;
    }

    /**
     *  DOM Level 3 Core CR - Experimental.
     * 
     *  The list of the parameters supported by this 
     * <code>DOMConfiguration</code> object and for which at least one value 
     * can be set by the application. Note that this list can also contain 
     * parameter names defined outside this specification. 
     */
    public DOMStringList getParameterNames() {
    	//REVISIT
    	return null;
    }	
    
    /** DOM L3-EXPERIMENTAL:
     * Getter for boolean and object parameters
     */
	public Object getParameter(String name) throws DOMException {
		Object state = serializer.fFeatures.get(name);
		if (state == null) {
			if (name.equals(Constants.DOM_ERROR_HANDLER)) {
				return serializer.fDOMErrorHandler;
			}
			else if (name.equals(Constants.DOM_RESOURCE_RESOLVER)
					|| name.equals(Constants.DOM_SCHEMA_LOCATION)
					|| name.equals(Constants.DOM_SCHEMA_TYPE)) {
				String msg =
					DOMMessageFormatter.formatMessage(
						DOMMessageFormatter.DOM_DOMAIN,
						"FEATURE_NOT_SUPPORTED",
						new Object[] { name });
				throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
			}
			else {
				String msg =
					DOMMessageFormatter.formatMessage(
						DOMMessageFormatter.DOM_DOMAIN,
						"FEATURE_NOT_FOUND",
						new Object[] { name });
				throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
			}
		}

		return ((Boolean) state);
	}

    /**
     * DOM L3 EXPERIMENTAL:
     *  Serialize the specified node as described above in the description of
     * <code>LSSerializer</code>. The result of serializing the node is
     * returned as a string. Writing a Document or Entity node produces a
     * serialized form that is well formed XML. Writing other node types
     * produces a fragment of text in a form that is not fully defined by
     * this document, but that should be useful to a human for debugging or
     * diagnostic purposes.
     * @param wnode  The node to be written.
     * @return  Returns the serialized data, or <code>null</code> in case a
     *   failure occured and the failure wasn't canceled by the error
     *   handler.
     * @exception DOMException
     *    DOMSTRING_SIZE_ERR: The resulting string is too long to fit in a
     *   <code>DOMString</code>.
     */
    public String writeToString(Node wnode)
    throws DOMException {
        // determine which serializer to use:
        Document doc = (wnode.getNodeType() == Node.DOCUMENT_NODE)?(Document)wnode:wnode.getOwnerDocument();
        Method getVersion = null;
        XMLSerializer ser = null;
        String ver = null;
        // this should run under JDK 1.1.8...
        try {
            getVersion = doc.getClass().getMethod("getXmlVersion", new Class[]{});
            if(getVersion != null ) {
                ver = (String)getVersion.invoke(doc, null);
            }
        } catch (Exception e) {
            // no way to test the version...
            // ignore the exception
        }
        if(ver != null && ver.equals("1.1")) {
            if(xml11Serializer == null) {
                xml11Serializer = new XML11Serializer();
                initSerializer(xml11Serializer);
            }
            // copy setting from "main" serializer to XML 1.1 serializer
            copySettings(serializer, xml11Serializer);
            ser = xml11Serializer;
        } else {
            ser = serializer;
        }
        checkAllFeatures(ser);
        StringWriter destination = new StringWriter();
        try {
            ser.reset();
            ser.setOutputCharStream(destination);
            if (wnode == null)
                return null;
            else if (wnode.getNodeType() == Node.DOCUMENT_NODE)
                ser.serialize((Document)wnode);
            else if (wnode.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE)
                ser.serialize((DocumentFragment)wnode);
            else if (wnode.getNodeType() == Node.ELEMENT_NODE)
                ser.serialize((Element)wnode);
            else
                return null;
        } catch (IOException ioe) {
	        String msg = DOMMessageFormatter.formatMessage(
			    DOMMessageFormatter.DOM_DOMAIN,
				"STRING_TOO_LONG",
				new Object[] { ioe.getMessage()});
            throw new DOMException(DOMException.DOMSTRING_SIZE_ERR,msg);
        }
        return destination.toString();
    }

    /**
     * DOM L3 EXPERIMENTAL:
     * The end-of-line sequence of characters to be used in the XML being
     * written out. The only permitted values are these:
     * <dl>
     * <dt><code>null</code></dt>
     * <dd>
     * Use a default end-of-line sequence. DOM implementations should choose
     * the default to match the usual convention for text files in the
     * environment being used. Implementations must choose a default
     * sequence that matches one of those allowed by  2.11 "End-of-Line
     * Handling". </dd>
     * <dt>CR</dt>
     * <dd>The carriage-return character (#xD).</dd>
     * <dt>CR-LF</dt>
     * <dd> The
     * carriage-return and line-feed characters (#xD #xA). </dd>
     * <dt>LF</dt>
     * <dd> The line-feed
     * character (#xA). </dd>
     * </dl>
     * <br>The default value for this attribute is <code>null</code>.
     */
    public void setNewLine(String newLine) {
        serializer._format.setLineSeparator(newLine);
    }


    /**
     * DOM L3 EXPERIMENTAL:
     * The end-of-line sequence of characters to be used in the XML being
     * written out. The only permitted values are these:
     * <dl>
     * <dt><code>null</code></dt>
     * <dd>
     * Use a default end-of-line sequence. DOM implementations should choose
     * the default to match the usual convention for text files in the
     * environment being used. Implementations must choose a default
     * sequence that matches one of those allowed by  2.11 "End-of-Line
     * Handling". </dd>
     * <dt>CR</dt>
     * <dd>The carriage-return character (#xD).</dd>
     * <dt>CR-LF</dt>
     * <dd> The
     * carriage-return and line-feed characters (#xD #xA). </dd>
     * <dt>LF</dt>
     * <dd> The line-feed
     * character (#xA). </dd>
     * </dl>
     * <br>The default value for this attribute is <code>null</code>.
     */
    public String getNewLine() {
        return serializer._format.getLineSeparator();
    }


    /**
     *  When the application provides a filter, the serializer will call out
     * to the filter before serializing each Node. Attribute nodes are never
     * passed to the filter. The filter implementation can choose to remove
     * the node from the stream or to terminate the serialization early.
     */
    public LSSerializerFilter getFilter(){
        return serializer.fDOMFilter;
    }
    /**
     *  When the application provides a filter, the serializer will call out
     * to the filter before serializing each Node. Attribute nodes are never
     * passed to the filter. The filter implementation can choose to remove
     * the node from the stream or to terminate the serialization early.
     */
    public void setFilter(LSSerializerFilter filter){
        serializer.fDOMFilter = filter;
    }


    private void checkAllFeatures(XMLSerializer ser) {
        if (getParameter(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT) == Boolean.TRUE)
            ser._format.setPreserveSpace(true);
        else
            ser._format.setPreserveSpace(false);
    }

    // this initializes a newly-created serializer
    private void initSerializer(XMLSerializer ser) {
        ser.fNamespaces = true;
        ser.fNSBinder = new NamespaceSupport();
        ser.fLocalNSBinder = new NamespaceSupport();
        ser.fSymbolTable = new SymbolTable();
        ser.fFeatures = new Hashtable();
        ser.fFeatures.put(Constants.DOM_NAMESPACES, Boolean.TRUE);
        ser.fFeatures.put(Constants.DOM_NORMALIZE_CHARACTERS, Boolean.FALSE);
		ser.fFeatures.put(Constants.DOM_VALIDATE_IF_SCHEMA, Boolean.FALSE);
        ser.fFeatures.put(Constants.DOM_VALIDATE, Boolean.FALSE);
        ser.fFeatures.put(Constants.DOM_ENTITIES, Boolean.TRUE);
		ser.fFeatures.put(Constants.DOM_SPLIT_CDATA, Boolean.TRUE);
		ser.fFeatures.put(Constants.DOM_CDATA_SECTIONS, Boolean.TRUE);
		ser.fFeatures.put(Constants.DOM_COMMENTS, Boolean.TRUE);
        ser.fFeatures.put(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT, Boolean.TRUE);
        ser.fFeatures.put(Constants.DOM_DISCARD_DEFAULT_CONTENT, Boolean.TRUE);
        ser.fFeatures.put(Constants.DOM_CANONICAL_FORM, Boolean.FALSE);
        ser.fFeatures.put(Constants.DOM_FORMAT_PRETTY_PRINT, Boolean.FALSE);
        ser.fFeatures.put(Constants.DOM_XMLDECL, Boolean.TRUE);
		ser.fFeatures.put(Constants.DOM_CHECK_CHAR_NORMALIZATION, Boolean.FALSE);
		ser.fFeatures.put(Constants.DOM_DATATYPE_NORMALIZATION, Boolean.FALSE);
		ser.fFeatures.put(Constants.DOM_NORMALIZE_CHARACTERS, Boolean.FALSE);
		ser.fFeatures.put(Constants.DOM_WELLFORMED, Boolean.FALSE);
		ser.fFeatures.put(Constants.DOM_INFOSET, Boolean.FALSE);
		ser.fFeatures.put(Constants.DOM_NAMESPACE_DECLARATIONS, Boolean.TRUE);
		ser.fFeatures.put(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT, Boolean.TRUE);
		ser.fFeatures.put(Constants.DOM_IGNORE_CHAR_DENORMALIZATION, Boolean.TRUE);
    }

    // copies all settings that could have been modified
    // by calls to LSSerializer methods from one serializer to another.
    // IMPORTANT:  if new methods are implemented or more settings of
    // the serializer are made alterable, this must be
    // reflected in this method!
    private void copySettings(XMLSerializer src, XMLSerializer dest) {
        dest._format.setOmitXMLDeclaration(src._format.getOmitXMLDeclaration());
        dest.fNamespaces = src.fNamespaces;
        dest.fDOMErrorHandler = src.fDOMErrorHandler;
        dest._format.setEncoding(src._format.getEncoding());
        dest._format.setLineSeparator(src._format.getLineSeparator());
        dest.fDOMFilter = src.fDOMFilter;
        // and copy over all the entries in fFeatures:
        Enumeration keys = src.fFeatures.keys();
        while(keys.hasMoreElements()) {
            Object key = keys.nextElement();
            Object val = src.fFeatures.get(key);
            dest.fFeatures.put(key,val);
        }
    }//copysettings

    /**
      *  Serialize the specified node as described above in the general
      * description of the <code>LSSerializer</code> interface. The output
      * is written to the supplied <code>LSOutput</code>.
      * <br> When writing to a <code>LSOutput</code>, the encoding is found by
      * looking at the encoding information that is reachable through the
      * <code>LSOutput</code> and the item to be written (or its owner
      * document) in this order:
      * <ol>
      * <li> <code>LSOutput.encoding</code>,
      * </li>
      * <li>
      * <code>Document.actualEncoding</code>,
      * </li>
      * <li>
      * <code>Document.xmlEncoding</code>.
      * </li>
      * </ol>
      * <br> If no encoding is reachable through the above properties, a
      * default encoding of "UTF-8" will be used.
      * <br> If the specified encoding is not supported an
      * "unsupported-encoding" error is raised.
      * <br> If no output is specified in the <code>LSOutput</code>, a
      * "no-output-specified" error is raised.
      * @param node  The node to serialize.
      * @param destination The destination for the serialized DOM.
      * @return  Returns <code>true</code> if <code>node</code> was
      *   successfully serialized and <code>false</code> in case the node
      *   couldn't be serialized.
      */
    public boolean write(Node node, LSOutput destination) {

        if (node == null)
            return false;
            
        Method getVersion = null;
        XMLSerializer ser = null;
        String ver = null;
        Document fDocument =(node.getNodeType() == Node.DOCUMENT_NODE)
                ? (Document) node
                : node.getOwnerDocument();
        // this should run under JDK 1.1.8...
        try {
            getVersion = fDocument.getClass().getMethod("getXmlVersion", new Class[] {});
            if (getVersion != null) {
                ver = (String) getVersion.invoke(fDocument, null);
            }
        } catch (Exception e) {
            //no way to test the version...
            //ignore the exception
        }
        //determine which serializer to use:
        if (ver != null && ver.equals("1.1")) {
            if (xml11Serializer == null) {
                xml11Serializer = new XML11Serializer();
                initSerializer(xml11Serializer);
            }
            //copy setting from "main" serializer to XML 1.1 serializer
            copySettings(serializer, xml11Serializer);
            ser = xml11Serializer;
        } else {
            ser = serializer;
        }
        checkAllFeatures(ser);

        String encoding = null;
        if ((encoding = destination.getEncoding()) == null) {
            try {
                Method getEncoding =
                    fDocument.getClass().getMethod("getActualEncoding", new Class[] {});
                if (getEncoding != null) {
                    encoding = (String) getEncoding.invoke(fDocument, null);
                }
            } catch (Exception e) {
                // ignore the exception
            }
            if (encoding == null) {
                try {
                    Method getEncoding =
                        fDocument.getClass().getMethod("getXmlEncoding", new Class[] {});
                    if (getEncoding != null) {
                        encoding = (String) getEncoding.invoke(fDocument, null);
                    }
                } catch (Exception e) {
                    // ignore the exception
                }
                if (encoding == null) {
                    encoding = "UTF-8";
                }
            }
        }
        try {
            ser.reset();
            serializer._format.setEncoding(encoding);
            OutputStream outputStream = destination.getByteStream();
            Writer writer = destination.getCharacterStream();
            String uri =  destination.getSystemId();
            if (writer == null) {
                if (outputStream == null) {
                    if (uri == null) {
                        if (ser.fDOMErrorHandler != null) {
                            DOMErrorImpl error = new DOMErrorImpl();
                            error.fType = "no-output-specified";
                            error.fMessage = "no-output-specified";
                            error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
                            ser.fDOMErrorHandler.handleError(error);
                        }
                        return false;
                    }
                    else {
                        // uri was specified
                        FileOutputStream fileOut = new FileOutputStream(new File(uri));
                        ser.setOutputCharStream( new OutputStreamWriter(fileOut, encoding));
                    }
                }
                else {
                    // byte stream was specified
                    ser.setOutputByteStream(outputStream);
                }
            }
            else {
                // character stream is specified
                ser.setOutputCharStream(writer); 
            }

            if (node.getNodeType() == Node.DOCUMENT_NODE)
                ser.serialize((Document) node);
            else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE)
                ser.serialize((DocumentFragment) node);
            else if (node.getNodeType() == Node.ELEMENT_NODE)
                ser.serialize((Element) node);
            else
                return false;
        } catch (Exception e) {
            if (ser.fDOMErrorHandler != null) {
                DOMErrorImpl error = new DOMErrorImpl();
                error.fException = e;
                error.fMessage = e.getMessage();
                error.fSeverity = DOMError.SEVERITY_ERROR;
                ser.fDOMErrorHandler.handleError(error);

            }
            return false;
        }
        return true;

    } //write

    /**
      *  Serialize the specified node as described above in the general
      * description of the <code>LSSerializer</code> interface. The output
      * is written to the supplied URI.
      * <br> When writing to a URI, the encoding is found by looking at the
      * encoding information that is reachable through the item to be written
      * (or its owner document) in this order:
      * <ol>
      * <li>
      * <code>Document.actualEncoding</code>,
      * </li>
      * <li>
      * <code>Document.xmlEncoding</code>.
      * </li>
      * </ol>
      * <br> If no encoding is reachable through the above properties, a
      * default encoding of "UTF-8" will be used.
      * <br> If the specified encoding is not supported an
      * "unsupported-encoding" error is raised.
      * @param node  The node to serialize.
      * @param URI The URI to write to.
      * @return  Returns <code>true</code> if <code>node</code> was
      *   successfully serialized and <code>false</code> in case the node
      *   couldn't be serialized.
      */
    public boolean writeToURI(Node node, String URI) {
        if (node == null){
            return false;
        }

        Method getXmlVersion = null;
        XMLSerializer ser = null;
        String ver = null;
        String encoding = null;

        Document fDocument =(node.getNodeType() == Node.DOCUMENT_NODE)
                ? (Document) node
                : node.getOwnerDocument();
        // this should run under JDK 1.1.8...
        try {
            getXmlVersion =
                fDocument.getClass().getMethod("getXmlVersion", new Class[] {});
            if (getXmlVersion != null) {
                ver = (String) getXmlVersion.invoke(fDocument, null);
            }
        } catch (Exception e) {
            // no way to test the version...
            // ignore the exception
        }
        if (ver != null && ver.equals("1.1")) {
            if (xml11Serializer == null) {
                xml11Serializer = new XML11Serializer();
                initSerializer(xml11Serializer);
            }
            // copy setting from "main" serializer to XML 1.1 serializer
            copySettings(serializer, xml11Serializer);
            ser = xml11Serializer;
        } else {
            ser = serializer;
        }
        checkAllFeatures(ser);

        try {
            Method getEncoding =
                fDocument.getClass().getMethod("getActualEncoding", new Class[] {});
            if (getEncoding != null) {
                encoding = (String) getEncoding.invoke(fDocument, null);
            }
        } catch (Exception e) {
            // ignore the exception
        }
        if (encoding == null) {
            try {
                Method getEncoding =
                    fDocument.getClass().getMethod("getXmlEncoding", new Class[] {});
                if (getEncoding != null) {
                    encoding = (String) getEncoding.invoke(fDocument, null);
                }
            } catch (Exception e) {
                // ignore the exception
            }
            if (encoding == null) {
                encoding = "UTF-8";
            }
        }

        try {
            ser.reset();
            FileOutputStream fileOut = new FileOutputStream(new File(URI));
            ser.setOutputCharStream(new OutputStreamWriter(fileOut, encoding));

            if (node.getNodeType() == Node.DOCUMENT_NODE)
                ser.serialize((Document) node);
            else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE)
                ser.serialize((DocumentFragment) node);
            else if (node.getNodeType() == Node.ELEMENT_NODE)
                ser.serialize((Element) node);
            else
                return false;
        } catch (Exception e) {
            if (ser.fDOMErrorHandler != null) {
                DOMErrorImpl error = new DOMErrorImpl();
                error.fException = e;
                error.fMessage = e.getMessage();
                error.fSeverity = DOMError.SEVERITY_ERROR;
                ser.fDOMErrorHandler.handleError(error);
            }
            return false;
        }
        return true;
    } //writeURI

}//DOMSerializerImpl




