geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ke...@apache.org
Subject svn commit: r393273 [2/2] - /geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/
Date Tue, 11 Apr 2006 17:50:14 GMT
Added: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/OutputFormat.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/OutputFormat.java?rev=393273&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/OutputFormat.java (added)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/OutputFormat.java Tue Apr 11 10:50:10 2006
@@ -0,0 +1,937 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ */
+
+/*
+ * This code has been borrowed from the Apache Xerces project. We're copying the code to
+ * keep from adding a dependency on Xerces in the Geronimo kernel.
+ */
+
+package org.apache.geronimo.system.configuration;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Node;
+import org.w3c.dom.html.HTMLDocument;
+
+
+/**
+ * Specifies an output format to control the serializer. Based on the
+ * XSLT specification for output format, plus additional parameters.
+ * Used to select the suitable serializer and determine how the
+ * document should be formatted on output.
+ * <p>
+ * The two interesting constructors are:
+ * <ul>
+ * <li>{@link #OutputFormat(String,String,boolean)} creates a format
+ *  for the specified method (XML, HTML, Text, etc), encoding and indentation
+ * <li>{@link #OutputFormat(Document,String,boolean)} creates a format
+ *  compatible with the document type (XML, HTML, Text, etc), encoding and
+ *  indentation
+ * </ul>
+ *
+ *
+ * @version $Revision$ $Date$
+ * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
+ *         <a href="mailto:visco@intalio.com">Keith Visco</a>
+ * @see Serializer
+ * @see Method
+ */
+public class OutputFormat
+{
+
+
+    public static class DTD
+    {
+
+        /**
+         * Public identifier for HTML document type.
+         */
+        public static final String HTMLPublicId = "-//W3C//DTD HTML 4.0//EN";
+
+        /**
+         * System identifier for HTML document type.
+         */
+        public static final String HTMLSystemId =
+            "http://www.w3.org/TR/WD-html-in-xml/DTD/xhtml1-strict.dtd";
+
+        /**
+         * Public identifier for XHTML document type.
+         */
+        public static final String XHTMLPublicId =
+            "-//W3C//DTD XHTML 1.0 Strict//EN";
+
+        /**
+         * System identifier for XHTML document type.
+         */
+        public static final String XHTMLSystemId =
+            "http://www.w3.org/TR/WD-html-in-xml/DTD/xhtml1-strict.dtd";
+
+    }
+
+
+    public static class Defaults
+    {
+
+        /**
+         * If indentation is turned on, the default identation
+         * level is 4.
+         *
+         * @see #setIndenting(boolean)
+         */
+        public static final int Indent = 4;
+
+        /**
+         * The default encoding for Web documents it UTF-8.
+         *
+         * @see #getEncoding()
+         */
+        public static final String Encoding = "UTF-8";
+
+        /**
+         * The default line width at which to break long lines
+         * when identing. This is set to 72.
+         */
+        public static final int LineWidth = 72;
+
+    }
+
+
+    /**
+     * Holds the output method specified for this document,
+     * or null if no method was specified.
+     */
+    private String method;
+
+
+    /**
+     * Specifies the version of the output method.
+     */
+    private String version;
+
+
+    /**
+     * The indentation level, or zero if no indentation
+     * was requested.
+     */
+    private int indent = 0;
+
+
+    /**
+     * The encoding to use, if an input stream is used.
+     * The default is always UTF-8.
+     */
+    private String encoding = Defaults.Encoding;
+
+    /**
+     * The EncodingInfo instance for _encoding.
+     */
+    private EncodingInfo encodingInfo = null;
+
+    /**
+     * The specified media type or null.
+     */
+    private String mediaType;
+
+
+    /**
+     * The specified document type system identifier, or null.
+     */
+    private String doctypeSystem;
+
+
+    /**
+     * The specified document type public identifier, or null.
+     */
+    private String doctypePublic;
+
+
+    /**
+     * Ture if the XML declaration should be ommited;
+     */
+    private boolean omitXmlDeclaration = false;
+
+
+    /**
+     * Ture if the DOCTYPE declaration should be ommited;
+     */
+    private boolean omitDoctype = false;
+
+
+    /**
+     * Ture if comments should be ommited;
+     */
+    private boolean omitComments = false;
+
+
+    /**
+     * True if the document type should be marked as standalone.
+     */
+    private boolean standalone = false;
+
+
+    /**
+     * List of element tag names whose text node children must
+     * be output as CDATA.
+     */
+    private String[] cdataElements;
+
+
+    /**
+     * List of element tag names whose text node children must
+     * be output unescaped.
+     */
+    private String[] nonEscapingElements;
+
+
+    /**
+     * The selected line separator.
+     */
+    private String lineSeparator = "\n";
+
+
+    /**
+     * The line width at which to wrap long lines when indenting.
+     */
+    private int _lineWidth = Defaults.LineWidth;
+
+
+    /**
+     * True if spaces should be preserved in elements that do not
+     * specify otherwise, or specify the default behavior.
+     */
+    private boolean preserve = false;
+    
+    /** If true, an empty string valued attribute is output as "". If false and
+     * and we are using the HTMLSerializer, then only the attribute name is 
+     * serialized. Defaults to false for backwards compatibility.
+     */
+    private boolean preserveEmptyAttributes = false;
+
+    /**
+     * Constructs a new output format with the default values.
+     */
+    public OutputFormat()
+    {
+    }
+
+
+    /**
+     * Constructs a new output format with the default values for
+     * the specified method and encoding. If <tt>indent</tt>
+     * is true, the document will be pretty printed with the default
+     * indentation level and default line wrapping.
+     *
+     * @param method The specified output method
+     * @param encoding The specified encoding
+     * @param indenting True for pretty printing
+     * @see #setEncoding
+     * @see #setIndenting
+     * @see #setMethod
+     */
+    public OutputFormat( String method, String encoding, boolean indenting )
+    {
+        setMethod( method );
+        setEncoding( encoding );
+        setIndenting( indenting );
+    }
+
+
+    /**
+     * Constructs a new output format with the proper method,
+     * document type identifiers and media type for the specified
+     * document.
+     *
+     * @param doc The document to output
+     * @see #whichMethod
+     */
+    public OutputFormat( Document doc )
+    {
+        setMethod( whichMethod( doc ) );
+        setDoctype( whichDoctypePublic( doc ), whichDoctypeSystem( doc ) );
+        setMediaType( whichMediaType( getMethod() ) );
+    }
+
+
+    /**
+     * Constructs a new output format with the proper method,
+     * document type identifiers and media type for the specified
+     * document, and with the specified encoding. If <tt>indent</tt>
+     * is true, the document will be pretty printed with the default
+     * indentation level and default line wrapping.
+     *
+     * @param doc The document to output
+     * @param encoding The specified encoding
+     * @param indenting True for pretty printing
+     * @see #setEncoding
+     * @see #setIndenting
+     * @see #whichMethod
+     */
+    public OutputFormat( Document doc, String encoding, boolean indenting )
+    {
+        this( doc );
+        setEncoding( encoding );
+        setIndenting( indenting );
+    }
+
+
+    /**
+     * Returns the method specified for this output format.
+     * Typically the method will be <tt>xml</tt>, <tt>html</tt>
+     * or <tt>text</tt>, but it might be other values.
+     * If no method was specified, null will be returned
+     * and the most suitable method will be determined for
+     * the document by calling {@link #whichMethod}.
+     *
+     * @return The specified output method, or null
+     */
+    public String getMethod()
+    {
+        return method;
+    }
+
+
+    /**
+     * Sets the method for this output format.
+     *
+     * @see #getMethod
+     * @param method The output method, or null
+     */
+    public void setMethod( String method )
+    {
+        this.method = method;
+    }
+
+
+    /**
+     * Returns the version for this output method.
+     * If no version was specified, will return null
+     * and the default version number will be used.
+     * If the serializerr does not support that particular
+     * version, it should default to a supported version.
+     *
+     * @return The specified method version, or null
+     */
+    public String getVersion()
+    {
+        return version;
+    }
+
+
+    /**
+     * Sets the version for this output method.
+     * For XML the value would be "1.0", for HTML
+     * it would be "4.0".
+     *
+     * @see #getVersion
+     * @param version The output method version, or null
+     */
+    public void setVersion( String version )
+    {
+        this.version = version;
+    }
+
+
+    /**
+     * Returns the indentation specified. If no indentation
+     * was specified, zero is returned and the document
+     * should not be indented.
+     *
+     * @return The indentation or zero
+     * @see #setIndenting
+     */
+    public int getIndent()
+    {
+        return indent;
+    }
+
+
+    /**
+     * Returns true if indentation was specified.
+     */
+    public boolean getIndenting()
+    {
+        return ( indent > 0 );
+    }
+
+
+    /**
+     * Sets the indentation. The document will not be
+     * indented if the indentation is set to zero.
+     * Calling {@link #setIndenting} will reset this
+     * value to zero (off) or the default (on).
+     *
+     * @param indent The indentation, or zero
+     */
+    public void setIndent( int indent )
+    {
+        if ( indent < 0 )
+            this.indent = 0;
+        else
+            this.indent = indent;
+    }
+
+
+    /**
+     * Sets the indentation on and off. When set on, the default
+     * indentation level and default line wrapping is used
+     * (see {@link #DEFAULT_INDENT} and {@link #DEFAULT_LINE_WIDTH}).
+     * To specify a different indentation level or line wrapping,
+     * use {@link #setIndent} and {@link #setLineWidth}.
+     *
+     * @param on True if indentation should be on
+     */
+    public void setIndenting( boolean on )
+    {
+        if ( on ) {
+            indent = Defaults.Indent;
+            _lineWidth = Defaults.LineWidth;
+        } else {
+            indent = 0;
+            _lineWidth = 0;
+        }
+    }
+
+
+    /**
+     * Returns the specified encoding. If no encoding was
+     * specified, the default is always "UTF-8".
+     *
+     * @return The encoding
+     */
+    public String getEncoding()
+    {
+        return encoding;
+    }
+
+
+    /**
+     * Sets the encoding for this output method. If no
+     * encoding was specified, the default is always "UTF-8".
+     * Make sure the encoding is compatible with the one
+     * used by the {@link java.io.Writer}.
+     *
+     * @see #getEncoding
+     * @param encoding The encoding, or null
+     */
+    public void setEncoding( String encoding )
+    {
+        this.encoding = encoding;
+        encodingInfo = null;
+    }
+
+    /**
+     * Sets the encoding for this output method with an <code>EncodingInfo</code>
+     * instance.
+     */
+    public void setEncoding(EncodingInfo encInfo) {
+        encoding = encInfo.getName();
+        encodingInfo = encInfo;
+    }
+
+    /**
+     * Returns an <code>EncodingInfo<code> instance for the encoding.
+     *
+     * @see setEncoding
+     */
+    public EncodingInfo getEncodingInfo() {
+        if (encodingInfo == null)
+            encodingInfo = Encodings.getEncodingInfo(encoding);
+        return encodingInfo;
+    }
+
+    /**
+     * Returns the specified media type, or null.
+     * To determine the media type based on the
+     * document type, use {@link #whichMediaType}.
+     *
+     * @return The specified media type, or null
+     */
+    public String getMediaType()
+    {
+        return mediaType;
+    }
+
+
+    /**
+     * Sets the media type.
+     *
+     * @see #getMediaType
+     * @param mediaType The specified media type
+     */
+    public void setMediaType( String mediaType )
+    {
+        this.mediaType = mediaType;
+    }
+
+
+    /**
+     * Sets the document type public and system identifiers.
+     * Required only if the DOM Document or SAX events do not
+     * specify the document type, and one must be present in
+     * the serialized document. Any document type specified
+     * by the DOM Document or SAX events will override these
+     * values.
+     *
+     * @param publicId The public identifier, or null
+     * @param systemId The system identifier, or null
+     */
+    public void setDoctype( String publicId, String systemId )
+    {
+        doctypePublic = publicId;
+        doctypeSystem = systemId;
+    }
+
+
+    /**
+     * Returns the specified document type public identifier,
+     * or null.
+     */
+    public String getDoctypePublic()
+    {
+        return doctypePublic;
+    }
+
+
+    /**
+     * Returns the specified document type system identifier,
+     * or null.
+     */
+    public String getDoctypeSystem()
+    {
+        return doctypeSystem;
+    }
+
+
+    /**
+     * Returns true if comments should be ommited.
+     * The default is false.
+     */
+    public boolean getOmitComments()
+    {
+        return omitComments;
+    }
+
+
+    /**
+     * Sets comment omitting on and off.
+     *
+     * @param omit True if comments should be ommited
+     */
+    public void setOmitComments( boolean omit )
+    {
+        omitComments = omit;
+    }
+
+
+    /**
+     * Returns true if the DOCTYPE declaration should
+     * be ommited. The default is false.
+     */
+    public boolean getOmitDocumentType()
+    {
+        return omitDoctype;
+    }
+
+
+    /**
+     * Sets DOCTYPE declaration omitting on and off.
+     *
+     * @param omit True if DOCTYPE declaration should be ommited
+     */
+    public void setOmitDocumentType( boolean omit )
+    {
+        omitDoctype = omit;
+    }
+
+
+    /**
+     * Returns true if the XML document declaration should
+     * be ommited. The default is false.
+     */
+    public boolean getOmitXMLDeclaration()
+    {
+        return omitXmlDeclaration;
+    }
+
+
+    /**
+     * Sets XML declaration omitting on and off.
+     *
+     * @param omit True if XML declaration should be ommited
+     */
+    public void setOmitXMLDeclaration( boolean omit )
+    {
+        omitXmlDeclaration = omit;
+    }
+
+
+    /**
+     * Returns true if the document type is standalone.
+     * The default is false.
+     */
+    public boolean getStandalone()
+    {
+        return standalone;
+    }
+
+
+    /**
+     * Sets document DTD standalone. The public and system
+     * identifiers must be null for the document to be
+     * serialized as standalone.
+     *
+     * @param standalone True if document DTD is standalone
+     */
+    public void setStandalone( boolean standalone )
+    {
+        this.standalone = standalone;
+    }
+
+
+    /**
+     * Returns a list of all the elements whose text node children
+     * should be output as CDATA, or null if no such elements were
+     * specified.
+     */
+    public String[] getCDataElements()
+    {
+        return cdataElements;
+    }
+
+
+    /**
+     * Returns true if the text node children of the given elements
+     * should be output as CDATA.
+     *
+     * @param tagName The element's tag name
+     * @return True if should serialize as CDATA
+     */
+    public boolean isCDataElement( String tagName )
+    {
+        int i;
+
+        if ( cdataElements == null )
+            return false;
+        for ( i = 0 ; i < cdataElements.length ; ++i )
+            if ( cdataElements[ i ].equals( tagName ) )
+                return true;
+        return false;
+    }
+
+
+    /**
+     * Sets the list of elements for which text node children
+     * should be output as CDATA.
+     *
+     * @param cdataElements List of CDATA element tag names
+     */
+    public void setCDataElements( String[] cdataElements )
+    {
+        this.cdataElements = cdataElements;
+    }
+
+
+    /**
+     * Returns a list of all the elements whose text node children
+     * should be output unescaped (no character references), or null
+     * if no such elements were specified.
+     */
+    public String[] getNonEscapingElements()
+    {
+        return nonEscapingElements;
+    }
+
+
+    /**
+     * Returns true if the text node children of the given elements
+     * should be output unescaped.
+     *
+     * @param tagName The element's tag name
+     * @return True if should serialize unescaped
+     */
+    public boolean isNonEscapingElement( String tagName )
+    {
+        int i;
+
+        if ( nonEscapingElements == null )
+            return false;
+        for ( i = 0 ; i < nonEscapingElements.length ; ++i )
+            if ( nonEscapingElements[ i ].equals( tagName ) )
+                return true;
+        return false;
+    }
+
+
+    /**
+     * Sets the list of elements for which text node children
+     * should be output unescaped (no character references).
+     *
+     * @param nonEscapingElements List of unescaped element tag names
+     */
+    public void setNonEscapingElements( String[] nonEscapingElements )
+    {
+        this.nonEscapingElements = nonEscapingElements;
+    }
+
+
+
+    /**
+     * Returns a specific line separator to use. The default is the
+     * Web line separator (<tt>\n</tt>). A string is returned to
+     * support double codes (CR + LF).
+     *
+     * @return The specified line separator
+     */
+    public String getLineSeparator()
+    {
+        return lineSeparator;
+    }
+
+
+    /**
+     * Sets the line separator. The default is the Web line separator
+     * (<tt>\n</tt>). The machine's line separator can be obtained
+     * from the system property <tt>line.separator</tt>, but is only
+     * useful if the document is edited on machines of the same type.
+     * For general documents, use the Web line separator.
+     *
+     * @param lineSeparator The specified line separator
+     */
+    public void setLineSeparator( String lineSeparator )
+    {
+        if ( lineSeparator == null )
+            this.lineSeparator =  "\n";
+        else
+            this.lineSeparator = lineSeparator;
+    }
+
+
+    /**
+     * Returns true if the default behavior for this format is to
+     * preserve spaces. All elements that do not specify otherwise
+     * or specify the default behavior will be formatted based on
+     * this rule. All elements that specify space preserving will
+     * always preserve space.
+     */
+    public boolean getPreserveSpace()
+    {
+        return preserve;
+    }
+
+
+    /**
+     * Sets space preserving as the default behavior. The default is
+     * space stripping and all elements that do not specify otherwise
+     * or use the default value will not preserve spaces.
+     *
+     * @param preserve True if spaces should be preserved
+     */
+    public void setPreserveSpace( boolean preserve )
+    {
+        this.preserve = preserve;
+    }
+
+
+    /**
+     * Return the selected line width for breaking up long lines.
+     * When indenting, and only when indenting, long lines will be
+     * broken at space boundaries based on this line width.
+     * No line wrapping occurs if this value is zero.
+     */
+    public int getLineWidth()
+    {
+        return _lineWidth;
+    }
+
+
+    /**
+     * Sets the line width. If zero then no line wrapping will
+     * occur. Calling {@link #setIndenting} will reset this
+     * value to zero (off) or the default (on).
+     *
+     * @param lineWidth The line width to use, zero for default
+     * @see #getLineWidth
+     * @see #setIndenting
+     */
+    public void setLineWidth( int lineWidth )
+    {
+        if ( lineWidth <= 0 )
+            _lineWidth = 0;
+        else
+            _lineWidth = lineWidth;
+    }
+
+    /**
+     * Returns the preserveEmptyAttribute flag. If flag is false, then'
+     * attributes with empty string values are output as the attribute 
+     * name only (in HTML mode).
+     * @return preserve the preserve flag
+     */
+    public boolean getPreserveEmptyAttributes () {
+        return preserveEmptyAttributes;
+    }
+    /**
+     * Sets the preserveEmptyAttribute flag. If flag is false, then'
+     * attributes with empty string values are output as the attribute 
+     * name only (in HTML mode).
+     * @param preserve the preserve flag
+     */
+    public void setPreserveEmptyAttributes (boolean preserve) {
+        preserveEmptyAttributes = preserve;
+    }
+
+    /**
+     * Returns the last printable character based on the selected
+     * encoding. Control characters and non-printable characters
+     * are always printed as character references.
+     */
+    public char getLastPrintable()
+    {
+        if ( getEncoding() != null &&
+             ( getEncoding().equalsIgnoreCase( "ASCII" ) ) )
+            return 0xFF;
+        else
+            return 0xFFFF;
+    }
+
+
+    /**
+     * Determine the output method for the specified document.
+     * If the document is an instance of {@link org.w3c.dom.html.HTMLDocument}
+     * then the method is said to be <tt>html</tt>. If the root
+     * element is 'html' and all text nodes preceding the root
+     * element are all whitespace, then the method is said to be
+     * <tt>html</tt>. Otherwise the method is <tt>xml</tt>.
+     *
+     * @param doc The document to check
+     * @return The suitable method
+     */
+    public static String whichMethod( Document doc )
+    {
+        Node    node;
+        String  value;
+        int     i;
+
+        // If document is derived from HTMLDocument then the default
+        // method is html.
+        if ( doc instanceof HTMLDocument )
+            return Method.HTML;
+
+        // Lookup the root element and the text nodes preceding it.
+        // If root element is html and all text nodes contain whitespace
+        // only, the method is html.
+
+        // FIXME (SM) should we care about namespaces here?
+
+        node = doc.getFirstChild();
+        while (node != null) {
+            // If the root element is html, the method is html.
+            if ( node.getNodeType() == Node.ELEMENT_NODE ) {
+                if ( node.getNodeName().equalsIgnoreCase( "html" ) ) {
+                    return Method.HTML;
+                } else if ( node.getNodeName().equalsIgnoreCase( "root" ) ) {
+                    return Method.FOP;
+                } else {
+                    return Method.XML;
+                }
+            } else if ( node.getNodeType() == Node.TEXT_NODE ) {
+                // If a text node preceding the root element contains
+                // only whitespace, this might be html, otherwise it's
+                // definitely xml.
+                value = node.getNodeValue();
+                for ( i = 0 ; i < value.length() ; ++i )
+                    if ( value.charAt( i ) != 0x20 && value.charAt( i ) != 0x0A &&
+                         value.charAt( i ) != 0x09 && value.charAt( i ) != 0x0D )
+                        return Method.XML;
+            }
+            node = node.getNextSibling();
+        }
+        // Anything else, the method is xml.
+        return Method.XML;
+    }
+
+
+    /**
+     * Returns the document type public identifier
+     * specified for this document, or null.
+     */
+    public static String whichDoctypePublic( Document doc )
+    {
+        DocumentType doctype;
+
+           /*  DOM Level 2 was introduced into the code base*/
+           doctype = doc.getDoctype();
+           if ( doctype != null ) {
+           // Note on catch: DOM Level 1 does not specify this method
+           // and the code will throw a NoSuchMethodError
+           try {
+           return doctype.getPublicId();
+           } catch ( Error except ) {  }
+           }
+        
+        if ( doc instanceof HTMLDocument )
+            return DTD.XHTMLPublicId;
+        return null;
+    }
+
+
+    /**
+     * Returns the document type system identifier
+     * specified for this document, or null.
+     */
+    public static String whichDoctypeSystem( Document doc )
+    {
+        DocumentType doctype;
+
+        /* DOM Level 2 was introduced into the code base*/
+           doctype = doc.getDoctype();
+           if ( doctype != null ) {
+           // Note on catch: DOM Level 1 does not specify this method
+           // and the code will throw a NoSuchMethodError
+           try {
+           return doctype.getSystemId();
+           } catch ( Error except ) { }
+           }
+        
+        if ( doc instanceof HTMLDocument )
+            return DTD.XHTMLSystemId;
+        return null;
+    }
+
+
+    /**
+     * Returns the suitable media format for a document
+     * output with the specified method.
+     */
+    public static String whichMediaType( String method )
+    {
+        if ( method.equalsIgnoreCase( Method.XML ) )
+            return "text/xml";
+        if ( method.equalsIgnoreCase( Method.HTML ) )
+            return "text/html";
+        if ( method.equalsIgnoreCase( Method.XHTML ) )
+            return "text/html";
+        if ( method.equalsIgnoreCase( Method.TEXT ) )
+            return "text/plain";
+        if ( method.equalsIgnoreCase( Method.FOP ) )
+            return "application/pdf";
+        return null;
+    }
+
+
+}
+

Added: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/Printer.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/Printer.java?rev=393273&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/Printer.java (added)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/Printer.java Tue Apr 11 10:50:10 2006
@@ -0,0 +1,359 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ */
+
+/*
+ * This code has been borrowed from the Apache Xerces project. We're copying the code to
+ * keep from adding a dependency on Xerces in the Geronimo kernel.
+ */
+
+package org.apache.geronimo.system.configuration;
+
+import java.io.Writer;
+import java.io.StringWriter;
+import java.io.IOException;
+
+
+/**
+ * The printer is responsible for sending text to the output stream
+ * or writer. This class performs direct writing for efficiency.
+ * {@link IndentPrinter} supports indentation and line wrapping by
+ * extending this class.
+ *
+ * @version $Revision$ $Date$
+ * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
+ */
+public class Printer
+{
+
+
+    /**
+     * The output format associated with this serializer. This will never
+     * be a null reference. If no format was passed to the constructor,
+     * the default one for this document type will be used. The format
+     * object is never changed by the serializer.
+     */
+    protected final OutputFormat format;
+
+
+    /**
+     * The writer to which the document is written.
+     */
+    protected Writer             writer;
+
+
+    /**
+     * The DTD writer. When we switch to DTD mode, all output is
+     * accumulated in this DTD writer. When we switch out of it,
+     * the output is obtained as a string. Must not be reset to
+     * null until we're done with the document.
+     */
+    protected StringWriter       dtdWriter;
+
+
+    /**
+     * Holds a reference to the document writer while we are
+     * in DTD mode.
+     */
+    protected Writer          docWriter;
+
+
+    /**
+     * Holds the exception thrown by the serializer.  Exceptions do not cause
+     * the serializer to quit, but are held and one is thrown at the end.
+     */
+    protected IOException     exception;
+
+
+    /**
+     * The size of the output buffer.
+     */
+    private static final int BufferSize = 4096;
+
+
+    /**
+     * Output buffer.
+     */
+    private final char[]  buffer = new char[ BufferSize ];
+
+
+    /**
+     * Position within the output buffer.
+     */
+    private int           pos = 0;
+
+
+    public Printer( Writer writer, OutputFormat format)
+    {
+        this.writer = writer;
+        this.format = format;
+        exception = null;
+        dtdWriter = null;
+        docWriter = null;
+        pos = 0;
+    }
+
+
+    public IOException getException()
+    {
+        return exception;
+    }
+
+
+    /**
+     * Called by any of the DTD handlers to enter DTD mode.
+     * Once entered, all output will be accumulated in a string
+     * that can be printed as part of the document's DTD.
+     * This method may be called any number of time but will only
+     * have affect the first time it's called. To exist DTD state
+     * and get the accumulated DTD, call {@link #leaveDTD}.
+     */
+    public void enterDTD()
+        throws IOException
+    {
+        // Can only enter DTD state once. Once we're out of DTD
+        // state, can no longer re-enter it.
+        if ( dtdWriter == null ) {
+        flushLine( false );
+
+            dtdWriter = new StringWriter();
+            docWriter = writer;
+            writer = dtdWriter;
+        }
+    }
+
+
+    /**
+     * Called by the root element to leave DTD mode and if any
+     * DTD parts were printer, will return a string with their
+     * textual content.
+     */
+    public String leaveDTD()
+        throws IOException
+    {
+        // Only works if we're going out of DTD mode.
+        if ( writer == dtdWriter ) {
+        flushLine( false );
+
+            writer = docWriter;
+            return dtdWriter.toString();
+        } else
+            return null;
+    }
+
+
+    public void printText( String text )
+        throws IOException
+    {
+        try {
+            int length = text.length();
+            for ( int i = 0 ; i < length ; ++i ) {
+                if ( pos == BufferSize ) {
+                    writer.write( buffer );
+                    pos = 0;
+                }
+                buffer[ pos ] = text.charAt( i );
+                ++pos;
+            }
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+    }
+
+
+    public void printText( StringBuffer text )
+        throws IOException
+    {
+        try {
+            int length = text.length();
+            for ( int i = 0 ; i < length ; ++i ) {
+                if ( pos == BufferSize ) {
+                    writer.write( buffer );
+                    pos = 0;
+                }
+                buffer[ pos ] = text.charAt( i );
+                ++pos;
+            }
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+    }
+
+
+    public void printText( char[] chars, int start, int length )
+        throws IOException
+    {
+        try {
+            while ( length-- > 0 ) {
+                if ( pos == BufferSize ) {
+                    writer.write( buffer );
+                    pos = 0;
+                }
+                buffer[ pos ] = chars[ start ];
+                ++start;
+                ++pos;
+            }
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+    }
+
+
+    public void printText( char ch )
+        throws IOException
+    {
+        try {
+            if ( pos == BufferSize ) {
+                writer.write( buffer );
+                pos = 0;
+            }
+            buffer[ pos ] = ch;
+            ++pos;
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+    }
+
+
+    public void printSpace()
+        throws IOException
+    {
+        try {
+            if ( pos == BufferSize ) {
+                writer.write( buffer );
+                pos = 0;
+            }
+            buffer[ pos ] = ' ';
+            ++pos;
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+    }
+
+
+    public void breakLine()
+        throws IOException
+    {
+        try {
+            if ( pos == BufferSize ) {
+                writer.write( buffer );
+                pos = 0;
+            }
+            buffer[ pos ] = '\n';
+            ++pos;
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+    }
+
+
+    public void breakLine( boolean preserveSpace )
+        throws IOException
+    {
+        breakLine();
+    }
+
+
+    public void flushLine( boolean preserveSpace )
+        throws IOException
+    {
+        // Write anything left in the buffer into the writer.
+        try {
+            writer.write( buffer, 0, pos );
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+        }
+        pos = 0;
+    }
+
+
+    /**
+     * Flush the output stream. Must be called when done printing
+     * the document, otherwise some text might be buffered.
+     */
+    public void flush()
+        throws IOException
+    {
+        try {
+            writer.write( buffer, 0, pos );
+            writer.flush();
+        } catch ( IOException except ) {
+            // We don't throw an exception, but hold it
+            // until the end of the document.
+            if ( exception == null )
+                exception = except;
+            throw except;
+        }
+        pos = 0;
+    }
+
+
+    public void indent()
+    {
+        // NOOP
+    }
+
+
+    public void unindent()
+    {
+        // NOOP
+    }
+
+
+    public int getNextIndent()
+    {
+        return 0;
+    }
+
+
+    public void setNextIndent( int indent )
+    {
+    }
+
+
+    public void setThisIndent( int indent )
+    {
+    }
+
+
+}

Added: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/SieveEncodingInfo.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/SieveEncodingInfo.java?rev=393273&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/SieveEncodingInfo.java (added)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/SieveEncodingInfo.java Tue Apr 11 10:50:10 2006
@@ -0,0 +1,125 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ */
+
+/*
+ * This code has been borrowed from the Apache Xerces project. We're copying the code to
+ * keep from adding a dependency on Xerces in the Geronimo kernel.
+ */
+package org.apache.geronimo.system.configuration;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+/**
+ * This class represents an encoding.
+ *
+ * @version $Id$
+ */
+public class SieveEncodingInfo extends EncodingInfo {
+
+    BAOutputStream checkerStream = null;
+    Writer checkerWriter = null;
+    String dangerChars = null;
+
+    /**
+     * Creates new <code>SeiveEncodingInfo</code> instance.
+     *
+     * @param dangers A sorted characters that are always printed as character references.
+     */
+    public SieveEncodingInfo(String mimeName, String javaName,
+                             int lastPrintable, String dangers) {
+        super(mimeName, javaName, lastPrintable);
+        this.dangerChars = dangers;
+    }
+
+    /**
+     * Creates new <code>SeiveEncodingInfo</code> instance.
+     */
+    public SieveEncodingInfo(String mimeName, int lastPrintable) {
+        this(mimeName, mimeName, lastPrintable, null);
+    }
+
+    /**
+     * Checks whether the specified character is printable or not.
+     *
+     * @param ch a code point (0-0x10ffff)
+     */
+    public boolean isPrintable(int ch) {
+        if (this.dangerChars != null && ch <= 0xffff) {
+            /**
+             * Searches this.dangerChars for ch.
+             * TODO: Use binary search.
+             */
+            if (this.dangerChars.indexOf(ch) >= 0)
+                return false;
+        }
+
+        if (ch <= this.lastPrintable)
+            return true;
+
+        boolean printable = true;
+        synchronized (this) {
+            try {
+                if (this.checkerWriter == null) {
+                    this.checkerStream = new BAOutputStream(10);
+                    this.checkerWriter = new OutputStreamWriter(this.checkerStream, this.javaName);
+                }
+
+                if (ch > 0xffff) {
+                    this.checkerWriter.write(((ch-0x10000)>>10)+0xd800);
+                    this.checkerWriter.write(((ch-0x10000)&0x3ff)+0xdc00);
+                    byte[] result = this.checkerStream.getBuffer();
+                    if (this.checkerStream.size() == 2 && result[0] == '?' && result[1] == '?')
+                        printable = false;
+                } else {
+                    this.checkerWriter.write(ch);
+                    this.checkerWriter.flush();
+                    byte[] result = this.checkerStream.getBuffer();
+                    if (this.checkerStream.size() == 1 && result[0] == '?')
+                        printable = false;
+                }
+                this.checkerStream.reset();
+            } catch (IOException ioe) {
+                printable = false;
+            }
+        }
+
+        return printable;
+    }
+
+    /**
+     * Why don't we use the original ByteArrayOutputStream?
+     * - Because the toByteArray() method of the ByteArrayOutputStream
+     * creates new byte[] instances for each call.
+     */
+    static class BAOutputStream extends ByteArrayOutputStream {
+        BAOutputStream() {
+            super();
+        }
+
+        BAOutputStream(int size) {
+            super(size);
+        }
+
+        byte[] getBuffer() {
+            return this.buf;
+        }
+    }
+
+}

Added: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/XMLSerializer.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/XMLSerializer.java?rev=393273&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/XMLSerializer.java (added)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/XMLSerializer.java Tue Apr 11 10:50:10 2006
@@ -0,0 +1,698 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ */
+
+/*
+ * This code has been borrowed from the Apache Xerces project. We're copying the code to
+ * keep from adding a dependency on Xerces in the Geronimo kernel.
+ */
+
+package org.apache.geronimo.system.configuration;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Enumeration;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.AttributeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+
+/**
+ * Implements an XML serializer supporting both DOM and SAX pretty
+ * serializing. For usage instructions see {@link Serializer}.
+ * <p>
+ * If an output stream is used, the encoding is taken from the
+ * output format (defaults to <tt>UTF-8</tt>). If a writer is
+ * used, make sure the writer uses the same encoding (if applies)
+ * as specified in the output format.
+ * <p>
+ * The serializer supports both DOM and SAX. DOM serializing is done
+ * by calling {@link #serialize} and SAX serializing is done by firing
+ * SAX events and using the serializer as a document handler.
+ * <p>
+ * If an I/O exception occurs while serializing, the serializer
+ * will not throw an exception directly, but only throw it
+ * at the end of serializing (either DOM or SAX's {@link
+ * org.xml.sax.DocumentHandler#endDocument}.
+ * <p>
+ * For elements that are not specified as whitespace preserving,
+ * the serializer will potentially break long text lines at space
+ * boundaries, indent lines, and serialize elements on separate
+ * lines. Line terminators will be regarded as spaces, and
+ * spaces at beginning of line will be stripped.
+ *
+ *
+ * @version $Revision$ $Date$
+ * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
+ * @see Serializer
+ */
+public class XMLSerializer extends BaseMarkupSerializer
+{
+
+    /**
+     * Constructs a new serializer. The serializer cannot be used without
+     * calling {@link #setOutputCharStream} or {@link #setOutputByteStream}
+     * first.
+     */
+    public XMLSerializer()
+    {
+        super( new OutputFormat( Method.XML, null, false ) );
+    }
+
+
+    /**
+     * Constructs a new serializer. The serializer cannot be used without
+     * calling {@link #setOutputCharStream} or {@link #setOutputByteStream}
+     * first.
+     */
+    public XMLSerializer( OutputFormat format )
+    {
+        super( format != null ? format : new OutputFormat( Method.XML, null, false ) );
+        this.format.setMethod( Method.XML );
+    }
+
+
+    /**
+     * Constructs a new serializer that writes to the specified writer
+     * using the specified output format. If <tt>format</tt> is null,
+     * will use a default output format.
+     *
+     * @param writer The writer to use
+     * @param format The output format to use, null for the default
+     */
+    public XMLSerializer( Writer writer, OutputFormat format )
+    {
+        super( format != null ? format : new OutputFormat( Method.XML, null, false ) );
+        this.format.setMethod( Method.XML );
+        setOutputCharStream( writer );
+    }
+
+
+    /**
+     * Constructs a new serializer that writes to the specified output
+     * stream using the specified output format. If <tt>format</tt>
+     * is null, will use a default output format.
+     *
+     * @param output The output stream to use
+     * @param format The output format to use, null for the default
+     */
+    public XMLSerializer( OutputStream output, OutputFormat format )
+    {
+        super( format != null ? format : new OutputFormat( Method.XML, null, false ) );
+        this.format.setMethod( Method.XML );
+        setOutputByteStream( output );
+    }
+
+
+    public void setOutputFormat( OutputFormat format )
+    {
+        super.setOutputFormat( format != null ? format : new OutputFormat( Method.XML, null, false ) );
+    }
+
+
+    //-----------------------------------------//
+    // SAX content handler serializing methods //
+    //-----------------------------------------//
+
+
+    public void startElement( String namespaceURI, String localName,
+                              String rawName, Attributes attrs )
+        throws SAXException
+    {
+        int          i;
+        boolean      preserveSpace;
+        ElementState state;
+        String       name;
+        String       value;
+
+        try {
+        if ( printer == null )
+            throw new IllegalStateException( "SER002 No writer supplied for serializer" );
+
+        state = getElementState();
+        if ( isDocumentState() ) {
+            // If this is the root element handle it differently.
+            // If the first root element in the document, serialize
+            // the document's DOCTYPE. Space preserving defaults
+            // to that of the output format.
+            if ( ! started )
+                    startDocument( ( localName == null || localName.length() == 0 ) ? rawName : localName );
+        } else {
+            // For any other element, if first in parent, then
+            // close parent's opening tag and use the parnet's
+            // space preserving.
+            if ( state.empty )
+                printer.printText( '>' );
+            // Must leave CData section first
+            if ( state.inCData )
+            {
+                printer.printText( "]]>" );
+                state.inCData = false;
+            }
+            // Indent this element on a new line if the first
+            // content of the parent element or immediately
+            // following an element or a comment
+            if ( indenting && ! state.preserveSpace &&
+                 ( state.empty || state.afterElement || state.afterComment) )
+                printer.breakLine();
+        }
+        preserveSpace = state.preserveSpace;
+
+            //We remove the namespaces from the attributes list so that they will
+            //be in _prefixes
+            attrs = extractNamespaces(attrs);
+
+        // Do not change the current element state yet.
+        // This only happens in endElement().
+            if ( rawName == null || rawName.length() == 0 ) {
+                if ( localName == null )
+                    throw new SAXException( "No rawName and localName is null" );
+                if ( namespaceURI != null && ! namespaceURI.equals( "" ) ) {
+                String prefix;
+                prefix = getPrefix( namespaceURI );
+                    if ( prefix != null && prefix.length() > 0 )
+                    rawName = prefix + ":" + localName;
+                    else
+                        rawName = localName;
+                } else
+                    rawName = localName;
+        }
+
+        printer.printText( '<' );
+        printer.printText( rawName );
+        printer.indent();
+
+        // For each attribute print it's name and value as one part,
+        // separated with a space so the element can be broken on
+        // multiple lines.
+        if ( attrs != null ) {
+            for ( i = 0 ; i < attrs.getLength() ; ++i ) {
+                printer.printSpace();
+
+                name = attrs.getQName( i );
+                    if ( name != null && name.length() == 0 ) {
+                    String prefix;
+                    String attrURI;
+
+                    name = attrs.getLocalName( i );
+                    attrURI = attrs.getURI( i );
+                        if ( ( attrURI != null && attrURI.length() != 0 ) &&
+                             ( namespaceURI == null || namespaceURI.length() == 0 ||
+                                              ! attrURI.equals( namespaceURI ) ) ) {
+                        prefix = getPrefix( attrURI );
+                        if ( prefix != null && prefix.length() > 0 )
+                            name = prefix + ":" + name;
+                    }
+                }
+
+                value = attrs.getValue( i );
+                if ( value == null )
+                    value = "";
+                printer.printText( name );
+                printer.printText( "=\"" );
+                printEscaped( value );
+                printer.printText( '"' );
+
+                // If the attribute xml:space exists, determine whether
+                // to preserve spaces in this and child nodes based on
+                // its value.
+                if ( name.equals( "xml:space" ) ) {
+                    if ( value.equals( "preserve" ) )
+                        preserveSpace = true;
+                    else
+                        preserveSpace = format.getPreserveSpace();
+                }
+            }
+        }
+
+            if ( prefixes != null ) {
+            Enumeration keyEnum; 
+
+            keyEnum = prefixes.keys();
+            while ( keyEnum.hasMoreElements() ) {
+                printer.printSpace();
+                value = (String) keyEnum.nextElement();
+                name = (String) prefixes.get( value );
+                if ( name.length() == 0 ) {
+                    printer.printText( "xmlns=\"" );
+                    printEscaped( value );
+                    printer.printText( '"' );
+                } else {
+                    printer.printText( "xmlns:" );
+                    printer.printText( name );
+                    printer.printText( "=\"" );
+                    printEscaped( value );
+                    printer.printText( '"' );
+                }
+            }
+        }
+
+        // Now it's time to enter a new element state
+        // with the tag name and space preserving.
+        // We still do not change the curent element state.
+        state = enterElementState( namespaceURI, localName, rawName, preserveSpace );
+            name = ( localName == null || localName.length() == 0 ) ? rawName : namespaceURI + "^" + localName;
+            state.doCData = format.isCDataElement( name );
+            state.unescaped = format.isNonEscapingElement( name );
+        } catch ( IOException except ) {
+            throw new SAXException( except );
+        }
+    }
+
+
+    public void endElement( String namespaceURI, String localName,
+                            String rawName )
+        throws SAXException
+    {
+        try {
+            endElementIO( namespaceURI, localName, rawName );
+        } catch ( IOException except ) {
+            throw new SAXException( except );
+        }
+    }
+
+
+    public void endElementIO( String namespaceURI, String localName,
+                            String rawName )
+        throws IOException
+    {
+        ElementState state;
+
+        // Works much like content() with additions for closing
+        // an element. Note the different checks for the closed
+        // element's state and the parent element's state.
+        printer.unindent();
+        state = getElementState();
+        if ( state.empty ) {
+            printer.printText( "/>" );
+        } else {
+            // Must leave CData section first
+            if ( state.inCData )
+                printer.printText( "]]>" );
+            // This element is not empty and that last content was
+            // another element, so print a line break before that
+            // last element and this element's closing tag.
+            if ( indenting && ! state.preserveSpace && (state.afterElement || state.afterComment) )
+                printer.breakLine();
+            printer.printText( "</" );
+            printer.printText( state.rawName );
+            printer.printText( '>' );
+        }
+        // Leave the element state and update that of the parent
+        // (if we're not root) to not empty and after element.
+        state = leaveElementState();
+        state.afterElement = true;
+        state.afterComment = false;
+        state.empty = false;
+        if ( isDocumentState() )
+            printer.flush();
+    }
+
+
+    //------------------------------------------//
+    // SAX document handler serializing methods //
+    //------------------------------------------//
+
+
+    public void startElement( String tagName, AttributeList attrs )
+        throws SAXException
+    {
+        int          i;
+        boolean      preserveSpace;
+        ElementState state;
+        String       name;
+        String       value;
+
+        try {
+        if ( printer == null )
+            throw new IllegalStateException( "SER002 No writer supplied for serializer" );
+
+        state = getElementState();
+        if ( isDocumentState() ) {
+            // If this is the root element handle it differently.
+            // If the first root element in the document, serialize
+            // the document's DOCTYPE. Space preserving defaults
+            // to that of the output format.
+            if ( ! started )
+                startDocument( tagName );
+        } else {
+            // For any other element, if first in parent, then
+            // close parent's opening tag and use the parnet's
+            // space preserving.
+            if ( state.empty )
+                printer.printText( '>' );
+            // Must leave CData section first
+            if ( state.inCData )
+            {
+                printer.printText( "]]>" );
+                state.inCData = false;
+            }
+            // Indent this element on a new line if the first
+            // content of the parent element or immediately
+            // following an element.
+            if ( indenting && ! state.preserveSpace &&
+                 ( state.empty || state.afterElement || state.afterComment) )
+                printer.breakLine();
+        }
+        preserveSpace = state.preserveSpace;
+
+        // Do not change the current element state yet.
+        // This only happens in endElement().
+
+        printer.printText( '<' );
+        printer.printText( tagName );
+        printer.indent();
+
+        // For each attribute print it's name and value as one part,
+        // separated with a space so the element can be broken on
+        // multiple lines.
+        if ( attrs != null ) {
+            for ( i = 0 ; i < attrs.getLength() ; ++i ) {
+                printer.printSpace();
+                name = attrs.getName( i );
+                value = attrs.getValue( i );
+                if ( value != null ) {
+                    printer.printText( name );
+                    printer.printText( "=\"" );
+                    printEscaped( value );
+                    printer.printText( '"' );
+                }
+
+                // If the attribute xml:space exists, determine whether
+                // to preserve spaces in this and child nodes based on
+                // its value.
+                if ( name.equals( "xml:space" ) ) {
+                    if ( value.equals( "preserve" ) )
+                        preserveSpace = true;
+                    else
+                        preserveSpace = format.getPreserveSpace();
+                }
+            }
+        }
+        // Now it's time to enter a new element state
+        // with the tag name and space preserving.
+        // We still do not change the curent element state.
+        state = enterElementState( null, null, tagName, preserveSpace );
+        state.doCData = format.isCDataElement( tagName );
+        state.unescaped = format.isNonEscapingElement( tagName );
+        } catch ( IOException except ) {
+            throw new SAXException( except );
+    }
+
+    }
+
+
+    public void endElement( String tagName )
+        throws SAXException
+    {
+        endElement( null, null, tagName );
+    }
+
+
+
+    //------------------------------------------//
+    // Generic node serializing methods methods //
+    //------------------------------------------//
+
+
+    /**
+     * Called to serialize the document's DOCTYPE by the root element.
+     * The document type declaration must name the root element,
+     * but the root element is only known when that element is serialized,
+     * and not at the start of the document.
+     * <p>
+     * This method will check if it has not been called before ({@link #started}),
+     * will serialize the document type declaration, and will serialize all
+     * pre-root comments and PIs that were accumulated in the document
+     * (see {@link #serializePreRoot}). Pre-root will be serialized even if
+     * this is not the first root element of the document.
+     */
+    protected void startDocument( String rootTagName )
+        throws IOException
+    {
+        int    i;
+        String dtd;
+
+        dtd = printer.leaveDTD();
+        if ( ! started ) {
+
+            if ( ! format.getOmitXMLDeclaration() ) {
+                StringBuffer    buffer;
+
+                // Serialize the document declaration appreaing at the head
+                // of very XML document (unless asked not to).
+                buffer = new StringBuffer( "<?xml version=\"" );
+                if ( format.getVersion() != null )
+                    buffer.append( format.getVersion() );
+                else
+                    buffer.append( "1.0" );
+                buffer.append( '"' );
+                if ( format.getEncoding() != null ) {
+                    buffer.append( " encoding=\"" );
+                    buffer.append( format.getEncoding() );
+                    buffer.append( '"' );
+                }
+                if ( format.getStandalone() && docTypeSystemId == null &&
+                     docTypePublicId == null )
+                    buffer.append( " standalone=\"yes\"" );
+                buffer.append( "?>" );
+                printer.printText( buffer );
+                printer.breakLine();
+            }
+
+            if ( ! format.getOmitDocumentType() ) {
+                if ( docTypeSystemId != null ) {
+                    // System identifier must be specified to print DOCTYPE.
+                    // If public identifier is specified print 'PUBLIC
+                    // <public> <system>', if not, print 'SYSTEM <system>'.
+                    printer.printText( "<!DOCTYPE " );
+                    printer.printText( rootTagName );
+                    if ( docTypePublicId != null ) {
+                        printer.printText( " PUBLIC " );
+                        printDoctypeURL( docTypePublicId );
+                        if ( indenting ) {
+                            printer.breakLine();
+                            for ( i = 0 ; i < 18 + rootTagName.length() ; ++i )
+                                printer.printText( " " );
+                        } else
+                            printer.printText( " " );
+                    printDoctypeURL( docTypeSystemId );
+                    }
+                    else {
+                        printer.printText( " SYSTEM " );
+                        printDoctypeURL( docTypeSystemId );
+                    }
+
+                    // If we accumulated any DTD contents while printing.
+                    // this would be the place to print it.
+                    if ( dtd != null && dtd.length() > 0 ) {
+                        printer.printText( " [" );
+                        printText( dtd, true, true );
+                        printer.printText( ']' );
+                    }
+
+                    printer.printText( ">" );
+                    printer.breakLine();
+                } else if ( dtd != null && dtd.length() > 0 ) {
+                    printer.printText( "<!DOCTYPE " );
+                    printer.printText( rootTagName );
+                    printer.printText( " [" );
+                    printText( dtd, true, true );
+                    printer.printText( "]>" );
+                    printer.breakLine();
+                }
+            }
+        }
+        started = true;
+        // Always serialize these, even if not te first root element.
+        serializePreRoot();
+    }
+
+
+    /**
+     * Called to serialize a DOM element. Equivalent to calling {@link
+     * #startElement}, {@link #endElement} and serializing everything
+     * inbetween, but better optimized.
+     */
+    protected void serializeElement( Element elem )
+        throws IOException
+    {
+        Attr         attr;
+        NamedNodeMap attrMap;
+        int          i;
+        Node         child;
+        ElementState state;
+        boolean      preserveSpace;
+        String       name;
+        String       value;
+        String       tagName;
+
+        tagName = elem.getTagName();
+        state = getElementState();
+        if ( isDocumentState() ) {
+            // If this is the root element handle it differently.
+            // If the first root element in the document, serialize
+            // the document's DOCTYPE. Space preserving defaults
+            // to that of the output format.
+            if ( ! started )
+                startDocument( tagName );
+        } else {
+            // For any other element, if first in parent, then
+            // close parent's opening tag and use the parnet's
+            // space preserving.
+            if ( state.empty )
+                printer.printText( '>' );
+            // Must leave CData section first
+            if ( state.inCData )
+            {
+                printer.printText( "]]>" );
+                state.inCData = false;
+            }
+            // Indent this element on a new line if the first
+            // content of the parent element or immediately
+            // following an element.
+            if ( indenting && ! state.preserveSpace &&
+                 ( state.empty || state.afterElement || state.afterComment) )
+                printer.breakLine();
+        }
+        preserveSpace = state.preserveSpace;
+
+        // Do not change the current element state yet.
+        // This only happens in endElement().
+
+        printer.printText( '<' );
+        printer.printText( tagName );
+        printer.indent();
+
+        // Lookup the element's attribute, but only print specified
+        // attributes. (Unspecified attributes are derived from the DTD.
+        // For each attribute print it's name and value as one part,
+        // separated with a space so the element can be broken on
+        // multiple lines.
+        attrMap = elem.getAttributes();
+        if ( attrMap != null ) {
+            for ( i = 0 ; i < attrMap.getLength() ; ++i ) {
+                attr = (Attr) attrMap.item( i );
+                name = attr.getName();
+                value = attr.getValue();
+                if ( value == null )
+                    value = "";
+                if ( attr.getSpecified() ) {
+                    printer.printSpace();
+                    printer.printText( name );
+                    printer.printText( "=\"" );
+                    printEscaped( value );
+                    printer.printText( '"' );
+                }
+                // If the attribute xml:space exists, determine whether
+                // to preserve spaces in this and child nodes based on
+                // its value.
+                if ( name.equals( "xml:space" ) ) {
+                    if ( value.equals( "preserve" ) )
+                        preserveSpace = true;
+                    else
+                        preserveSpace = format.getPreserveSpace();
+                }
+            }
+        }
+
+        // If element has children, then serialize them, otherwise
+        // serialize en empty tag.
+        if ( elem.hasChildNodes() ) {
+            // Enter an element state, and serialize the children
+            // one by one. Finally, end the element.
+            state = enterElementState( null, null, tagName, preserveSpace );
+            state.doCData = format.isCDataElement( tagName );
+            state.unescaped = format.isNonEscapingElement( tagName );
+            child = elem.getFirstChild();
+            while ( child != null ) {
+                serializeNode( child );
+                child = child.getNextSibling();
+            }
+            endElementIO( null, null, tagName );
+        } else {
+            printer.unindent();
+            printer.printText( "/>" );
+            // After element but parent element is no longer empty.
+            state.afterElement = true;
+            state.afterComment = false;
+            state.empty = false;
+            if ( isDocumentState() )
+                printer.flush();
+        }
+    }
+
+
+    protected String getEntityRef( int ch )
+    {
+        // Encode special XML characters into the equivalent character references.
+        // These five are defined by default for all XML documents.
+        switch ( ch ) {
+        case '<':
+            return "lt";
+        case '>':
+            return "gt";
+        case '"':
+            return "quot";
+        case '\'':
+            return "apos";
+        case '&':
+            return "amp";
+        }
+        return null;
+    }
+
+
+    /** Retrieve and remove the namespaces declarations from the list of attributes.
+     *
+     */
+    private Attributes extractNamespaces( Attributes attrs )
+        throws SAXException
+    {
+        AttributesImpl attrsOnly;
+        String         rawName;
+        int            i;
+        int            length;
+
+        length = attrs.getLength();
+        attrsOnly = new AttributesImpl( attrs );
+
+        for ( i = length - 1 ; i >= 0 ; --i ) {
+            rawName = attrsOnly.getQName( i );
+
+            //We have to exclude the namespaces declarations from the attributes
+            //Append only when the feature http://xml.org/sax/features/namespace-prefixes"
+            //is TRUE
+            if ( rawName.startsWith( "xmlns" ) ) {
+                if (rawName.length() == 5) {
+                    startPrefixMapping( "", attrs.getValue( i ) );
+                    attrsOnly.removeAttribute( i );
+                } else if (rawName.charAt(5) == ':') {
+                    startPrefixMapping(rawName.substring(6), attrs.getValue(i));
+                    attrsOnly.removeAttribute( i );
+                }
+            }
+        }
+        return attrsOnly;
+    }
+}



Mime
View raw message