All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.org.apache.xml.internal.serializer.SerializerBase Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id: SerializerBase.java,v 1.11 2010-11-01 04:34:44 joehw Exp $
 */
package com.sun.org.apache.xml.internal.serializer;

import java.io.IOException;
import java.util.Vector;

import javax.xml.transform.SourceLocator;
import javax.xml.transform.Transformer;

import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
import com.sun.org.apache.xml.internal.serializer.utils.Utils;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.Locator2;


/**
 * This class acts as a base class for the XML "serializers"
 * and the stream serializers.
 * It contains a number of common fields and methods.
 * 
 * @xsl.usage internal
 */
public abstract class SerializerBase
    implements SerializationHandler, SerializerConstants
{
    

    /**
     * To fire off the end element trace event
     * @param name Name of element
     */
    protected void fireEndElem(String name)
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);
        }     	        	    	
    }

    /**
     * Report the characters trace event
     * @param chars  content of characters
     * @param start  starting index of characters to output
     * @param length  number of characters to output
     */
    protected void fireCharEvent(char[] chars, int start, int length)
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);
        }     	        	    	
    }

    /**
     * true if we still need to call startDocumentInternal() 
	 */
    protected boolean m_needToCallStartDocument = true; 

    /** True if a trailing "]]>" still needs to be written to be
     * written out. Used to merge adjacent CDATA sections
     */
    protected boolean m_cdataTagOpen = false;

    /**
     * All the attributes of the current element, collected from
     * startPrefixMapping() calls, or addAddtribute() calls, or 
     * from the SAX attributes in a startElement() call.
     */
    protected AttributesImplSerializer m_attributes = new AttributesImplSerializer();

    /**
     * Tells if we're in an EntityRef event.
     */
    protected boolean m_inEntityRef = false;

    /** This flag is set while receiving events from the external DTD */
    protected boolean m_inExternalDTD = false;

    /**
     * The System ID for the doc type.
     */
    private String m_doctypeSystem;

    /**
     * The public ID for the doc type.
     */
    private String m_doctypePublic;

    /**
     * Flag to tell that we need to add the doctype decl, which we can't do
     * until the first element is encountered.
     */
    boolean m_needToOutputDocTypeDecl = true;

    /**
     * The character encoding.  Must match the encoding used for the
     * printWriter.
     */
    private String m_encoding = null;

    /**
     * Tells if we should write the XML declaration.
     */
    private boolean m_shouldNotWriteXMLHeader = false;

    /**
     * The standalone value for the doctype.
     */
    private String m_standalone;

    /**
     * True if standalone was specified.
     */
    protected boolean m_standaloneWasSpecified = false;

    /**
     * Flag to tell if indenting (pretty-printing) is on.
     */
    protected boolean m_doIndent = false;
    /**
     * Amount to indent.
     */
    protected int m_indentAmount = 0;

    /**
     * Tells the XML version, for writing out to the XML decl.
     */
    private String m_version = null;

    /**
     * The mediatype.  Not used right now.
     */
    private String m_mediatype;

    /**
     * The transformer that was around when this output handler was created (if
     * any).
     */
    private Transformer m_transformer;

    /** 
     * Pairs of local names and corresponding URIs of CDATA sections. This list
     * comes from the cdata-section-elements attribute. Every second one is a
     * local name, and every other second one is the URI for the local name. 
     */
    protected Vector m_cdataSectionElements = null;

    /**
     * Namespace support, that keeps track of currently defined 
     * prefix/uri mappings. As processed elements come and go, so do
     * the associated mappings for that element.
     */
    protected NamespaceMappings m_prefixMap;
    
    /**
     * Handle for firing generate events.  This interface may be implemented
     * by the referenced transformer object.
     */
    protected SerializerTrace m_tracer;
    
    protected SourceLocator m_sourceLocator;
    

    /**
     * The writer to send output to. This field is only used in the ToStream
     * serializers, but exists here just so that the fireStartDoc() and
     * other fire... methods can flush this writer when tracing.
     */
    protected java.io.Writer m_writer = null;
    
    /**
     * A reference to "stack frame" corresponding to
     * the current element. Such a frame is pushed at a startElement()
     * and popped at an endElement(). This frame contains information about
     * the element, such as its namespace URI. 
     */
    protected ElemContext m_elemContext = new ElemContext();
    
    /**
     * A utility buffer for converting Strings passed to
     * character() methods to character arrays.
     * Reusing this buffer means not creating a new character array
     * everytime and it runs faster.
     */
    protected char[] m_charsBuff = new char[60];
    
    /**
     * A utility buffer for converting Strings passed to
     * attribute methods to character arrays.
     * Reusing this buffer means not creating a new character array
     * everytime and it runs faster.
     */
    protected char[] m_attrBuff = new char[30];    

    private Locator m_locator = null;
    
    protected boolean m_needToCallSetDocumentInfo = true;
    
    /**
     * Receive notification of a comment.
     * 
     * @see ExtendedLexicalHandler#comment(String)
     */
    public void comment(String data) throws SAXException
    {
        final int length = data.length();
        if (length > m_charsBuff.length)
        {
            m_charsBuff = new char[length * 2 + 1];
        }
        data.getChars(0, length, m_charsBuff, 0);
        comment(m_charsBuff, 0, length);
    }

    /**
     * If at runtime, when the qname of the attribute is
     * known, another prefix is specified for the attribute, then we can
     * patch or hack the name with this method. For
     * a qname of the form "ns?:otherprefix:name", this function patches the
     * qname by simply ignoring "otherprefix".
     * TODO: This method is a HACK! We do not have access to the
     * XML file, it sometimes generates a NS prefix of the form "ns?" for
     * an attribute.
     */
    protected String patchName(String qname)
    {

        
        final int lastColon = qname.lastIndexOf(':');

        if (lastColon > 0) {
            final int firstColon = qname.indexOf(':');
            final String prefix = qname.substring(0, firstColon);
            final String localName = qname.substring(lastColon + 1);

        // If uri is "" then ignore prefix
            final String uri = m_prefixMap.lookupNamespace(prefix);
            if (uri != null && uri.length() == 0) {
                return localName;
            }
            else if (firstColon != lastColon) {
                return prefix + ':' + localName;
            }
        }
        return qname;        
    }

    /**
     * Returns the local name of a qualified name. If the name has no prefix,
     * then it works as the identity (SAX2).
     * @param qname the qualified name 
     * @return the name, but excluding any prefix and colon.
     */
    protected static String getLocalName(String qname)
    {
        final int col = qname.lastIndexOf(':');
        return (col > 0) ? qname.substring(col + 1) : qname;
    }

    /**
     * Receive an object for locating the origin of SAX document events.
     *
     * @param locator An object that can return the location of any SAX document
     * event.
     * 
     * Receive an object for locating the origin of SAX document events.
     *
     * 

SAX parsers are strongly encouraged (though not absolutely * required) to supply a locator: if it does so, it must supply * the locator to the application by invoking this method before * invoking any of the other methods in the DocumentHandler * interface.

* *

The locator allows the application to determine the end * position of any document-related event, even if the parser is * not reporting an error. Typically, the application will * use this information for reporting its own errors (such as * character content that does not match an application's * business rules). The information returned by the locator * is probably not sufficient for use with a search engine.

* *

Note that the locator will return correct information only * during the invocation of the events in this interface. The * application should not attempt to use it at any other time.

*/ public void setDocumentLocator(Locator locator) { m_locator = locator; } /** * Adds the given attribute to the set of collected attributes , but only if * there is a currently open element. * * An element is currently open if a startElement() notification has * occured but the start of the element has not yet been written to the * output. In the stream case this means that we have not yet been forced * to close the elements opening tag by another notification, such as a * character notification. * * @param uri the URI of the attribute * @param localName the local name of the attribute * @param rawName the qualified name of the attribute * @param type the type of the attribute (probably CDATA) * @param value the value of the attribute * @param XSLAttribute true if this attribute is coming from an xsl:attriute element * @see ExtendedContentHandler#addAttribute(String, String, String, String, String) */ public void addAttribute( String uri, String localName, String rawName, String type, String value, boolean XSLAttribute) throws SAXException { if (m_elemContext.m_startTagOpen) { addAttributeAlways(uri, localName, rawName, type, value, XSLAttribute); } } /** * Adds the given attribute to the set of attributes, even if there is * no currently open element. This is useful if a SAX startPrefixMapping() * should need to add an attribute before the element name is seen. * * @param uri the URI of the attribute * @param localName the local name of the attribute * @param rawName the qualified name of the attribute * @param type the type of the attribute (probably CDATA) * @param value the value of the attribute * @param XSLAttribute true if this attribute is coming from an xsl:attribute element * @return true if the attribute was added, * false if an existing value was replaced. */ public boolean addAttributeAlways( String uri, String localName, String rawName, String type, String value, boolean XSLAttribute) { boolean was_added; // final int index = // (localName == null || uri == null) ? // m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName); int index; // if (localName == null || uri == null){ // index = m_attributes.getIndex(rawName); // } // else { // index = m_attributes.getIndex(uri, localName); // } if (localName == null || uri == null || uri.length() == 0) index = m_attributes.getIndex(rawName); else { index = m_attributes.getIndex(uri,localName); } if (index >= 0) { /* We've seen the attribute before. * We may have a null uri or localName, but all * we really want to re-set is the value anyway. */ m_attributes.setValue(index,value); was_added = false; } else { // the attribute doesn't exist yet, create it m_attributes.addAttribute(uri, localName, rawName, type, value); was_added = true; } return was_added; } /** * Adds the given attribute to the set of collected attributes, * but only if there is a currently open element. * * @param name the attribute's qualified name * @param value the value of the attribute */ public void addAttribute(String name, final String value) { if (m_elemContext.m_startTagOpen) { final String patchedName = patchName(name); final String localName = getLocalName(patchedName); final String uri = getNamespaceURI(patchedName, false); addAttributeAlways(uri,localName, patchedName, "CDATA", value, false); } } /** * Adds the given xsl:attribute to the set of collected attributes, * but only if there is a currently open element. * * @param name the attribute's qualified name (prefix:localName) * @param value the value of the attribute * @param uri the URI that the prefix of the name points to */ public void addXSLAttribute(String name, final String value, final String uri) { if (m_elemContext.m_startTagOpen) { final String patchedName = patchName(name); final String localName = getLocalName(patchedName); addAttributeAlways(uri,localName, patchedName, "CDATA", value, true); } } /** * Add the given attributes to the currently collected ones. These * attributes are always added, regardless of whether on not an element * is currently open. * @param atts List of attributes to add to this list */ public void addAttributes(Attributes atts) throws SAXException { int nAtts = atts.getLength(); for (int i = 0; i < nAtts; i++) { String uri = atts.getURI(i); if (null == uri) uri = ""; addAttributeAlways( uri, atts.getLocalName(i), atts.getQName(i), atts.getType(i), atts.getValue(i), false); } } /** * Return a {@link ContentHandler} interface into this serializer. * If the serializer does not support the {@link ContentHandler} * interface, it should return null. * * @return A {@link ContentHandler} interface into this serializer, * or null if the serializer is not SAX 2 capable * @throws IOException An I/O exception occured */ public ContentHandler asContentHandler() throws IOException { return this; } /** * Report the end of an entity. * * @param name The name of the entity that is ending. * @throws org.xml.sax.SAXException The application may raise an exception. * @see #startEntity */ public void endEntity(String name) throws org.xml.sax.SAXException { if (name.equals("[dtd]")) m_inExternalDTD = false; m_inEntityRef = false; if (m_tracer != null) this.fireEndEntity(name); } /** * Flush and close the underlying java.io.Writer. This method applies to * ToStream serializers, not ToSAXHandler serializers. * @see ToStream */ public void close() { // do nothing (base behavior) } /** * Initialize global variables */ protected void initCDATA() { // CDATA stack // _cdataStack = new Stack(); // _cdataStack.push(new Integer(-1)); // push dummy value } /** * Returns the character encoding to be used in the output document. * @return the character encoding to be used in the output document. */ public String getEncoding() { return m_encoding; } /** * Sets the character encoding coming from the xsl:output encoding stylesheet attribute. * @param m_encoding the character encoding */ public void setEncoding(String m_encoding) { this.m_encoding = m_encoding; } /** * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute * @param b true if the XML declaration is to be omitted from the output * document. */ public void setOmitXMLDeclaration(boolean b) { this.m_shouldNotWriteXMLHeader = b; } /** * @return true if the XML declaration is to be omitted from the output * document. */ public boolean getOmitXMLDeclaration() { return m_shouldNotWriteXMLHeader; } /** * Returns the previously set value of the value to be used as the public * identifier in the document type declaration (DTD). * *@return the public identifier to be used in the DOCTYPE declaration in the * output document. */ public String getDoctypePublic() { return m_doctypePublic; } /** Set the value coming from the xsl:output doctype-public stylesheet attribute. * @param doctypePublic the public identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctypePublic(String doctypePublic) { this.m_doctypePublic = doctypePublic; } /** * Returns the previously set value of the value to be used * as the system identifier in the document type declaration (DTD). * @return the system identifier to be used in the DOCTYPE declaration in * the output document. * */ public String getDoctypeSystem() { return m_doctypeSystem; } /** Set the value coming from the xsl:output doctype-system stylesheet attribute. * @param doctypeSystem the system identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctypeSystem(String doctypeSystem) { this.m_doctypeSystem = doctypeSystem; } /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties * @param doctypeSystem the system identifier to be used in the DOCTYPE * declaration in the output document. * @param doctypePublic the public identifier to be used in the DOCTYPE * declaration in the output document. */ public void setDoctype(String doctypeSystem, String doctypePublic) { this.m_doctypeSystem = doctypeSystem; this.m_doctypePublic = doctypePublic; } /** * Sets the value coming from the xsl:output standalone stylesheet attribute. * @param standalone a value of "yes" indicates that the * standalone delaration is to be included in the output * document. This method remembers if the value was explicitly set using * this method, verses if the value is the default value. */ public void setStandalone(String standalone) { if (standalone != null) { m_standaloneWasSpecified = true; setStandaloneInternal(standalone); } } /** * Sets the XSL standalone attribute, but does not remember if this is a * default or explicite setting. * @param standalone "yes" | "no" */ protected void setStandaloneInternal(String standalone) { if ("yes".equals(standalone)) m_standalone = "yes"; else m_standalone = "no"; } /** * Gets the XSL standalone attribute * @return a value of "yes" if the standalone delaration is to * be included in the output document. * @see XSLOutputAttributes#getStandalone() */ public String getStandalone() { return m_standalone; } /** * @return true if the output document should be indented to visually * indicate its structure. */ public boolean getIndent() { return m_doIndent; } /** * Gets the mediatype the media-type or MIME type associated with the output * document. * @return the mediatype the media-type or MIME type associated with the * output document. */ public String getMediaType() { return m_mediatype; } /** * Gets the version of the output format. * @return the version of the output format. */ public String getVersion() { return m_version; } /** * Sets the value coming from the xsl:output version attribute. * @param version the version of the output format. * @see SerializationHandler#setVersion(String) */ public void setVersion(String version) { m_version = version; } /** * Sets the value coming from the xsl:output media-type stylesheet attribute. * @param mediaType the non-null media-type or MIME type associated with the * output document. * @see javax.xml.transform.OutputKeys#MEDIA_TYPE * @see SerializationHandler#setMediaType(String) */ public void setMediaType(String mediaType) { m_mediatype = mediaType; } /** * @return the number of spaces to indent for each indentation level. */ public int getIndentAmount() { return m_indentAmount; } /** * Sets the indentation amount. * @param m_indentAmount The m_indentAmount to set */ public void setIndentAmount(int m_indentAmount) { this.m_indentAmount = m_indentAmount; } /** * Sets the value coming from the xsl:output indent stylesheet * attribute. * @param doIndent true if the output document should be indented to * visually indicate its structure. * @see XSLOutputAttributes#setIndent(boolean) */ public void setIndent(boolean doIndent) { m_doIndent = doIndent; } /** * This method is used when a prefix/uri namespace mapping * is indicated after the element was started with a * startElement() and before and endElement(). * startPrefixMapping(prefix,uri) would be used before the * startElement() call. * @param uri the URI of the namespace * @param prefix the prefix associated with the given URI. * * @see ExtendedContentHandler#namespaceAfterStartElement(String, String) */ public void namespaceAfterStartElement(String uri, String prefix) throws SAXException { // default behavior is to do nothing } /** * Return a {@link DOMSerializer} interface into this serializer. If the * serializer does not support the {@link DOMSerializer} interface, it should * return null. * * @return A {@link DOMSerializer} interface into this serializer, or null * if the serializer is not DOM capable * @throws IOException An I/O exception occured * @see Serializer#asDOMSerializer() */ public DOMSerializer asDOMSerializer() throws IOException { return this; } /** * Push a boolean state based on if the name of the current element * is found in the list of qnames. A state is only pushed if * there were some cdata-section-names were specified. *

* Hidden parameters are the vector of qualified elements specified in * cdata-section-names attribute, and the m_cdataSectionStates stack * onto which whether the current element is in the list is pushed (true or * false). Other hidden parameters are the current elements namespaceURI, * localName and qName */ protected boolean isCdataSection() { boolean b = false; if (null != m_cdataSectionElements) { if (m_elemContext.m_elementLocalName == null) m_elemContext.m_elementLocalName = getLocalName(m_elemContext.m_elementName); if (m_elemContext.m_elementURI == null) { String prefix = getPrefixPart(m_elemContext.m_elementName); if (prefix != null) m_elemContext.m_elementURI = m_prefixMap.lookupNamespace(prefix); } if ((null != m_elemContext.m_elementURI) && m_elemContext.m_elementURI.length() == 0) m_elemContext.m_elementURI = null; int nElems = m_cdataSectionElements.size(); // loop through 2 at a time, as these are pairs of URI and localName for (int i = 0; i < nElems; i += 2) { String uri = (String) m_cdataSectionElements.elementAt(i); String loc = (String) m_cdataSectionElements.elementAt(i + 1); if (loc.equals(m_elemContext.m_elementLocalName) && subPartMatch(m_elemContext.m_elementURI, uri)) { b = true; break; } } } return b; } /** * Tell if two strings are equal, without worry if the first string is null. * * @param p String reference, which may be null. * @param t String reference, which may be null. * * @return true if strings are equal. */ private static final boolean subPartMatch(String p, String t) { return (p == t) || ((null != p) && (p.equals(t))); } /** * Returns the local name of a qualified name. * If the name has no prefix, * then it works as the identity (SAX2). * * @param qname a qualified name * @return returns the prefix of the qualified name, * or null if there is no prefix. */ protected static final String getPrefixPart(String qname) { final int col = qname.indexOf(':'); return (col > 0) ? qname.substring(0, col) : null; //return (col > 0) ? qname.substring(0,col) : ""; } /** * Some users of the serializer may need the current namespace mappings * @return the current namespace mappings (prefix/uri) * @see ExtendedContentHandler#getNamespaceMappings() */ public NamespaceMappings getNamespaceMappings() { return m_prefixMap; } /** * Returns the prefix currently pointing to the given URI (if any). * @param namespaceURI the uri of the namespace in question * @return a prefix pointing to the given URI (if any). * @see ExtendedContentHandler#getPrefix(String) */ public String getPrefix(String namespaceURI) { String prefix = m_prefixMap.lookupPrefix(namespaceURI); return prefix; } /** * Returns the URI of an element or attribute. Note that default namespaces * do not apply directly to attributes. * @param qname a qualified name * @param isElement true if the qualified name is the name of * an element. * @return returns the namespace URI associated with the qualified name. */ public String getNamespaceURI(String qname, boolean isElement) { String uri = EMPTYSTRING; int col = qname.lastIndexOf(':'); final String prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING; if (!EMPTYSTRING.equals(prefix) || isElement) { if (m_prefixMap != null) { uri = m_prefixMap.lookupNamespace(prefix); if (uri == null && !prefix.equals(XMLNS_PREFIX)) { throw new RuntimeException( Utils.messages.createMessage( MsgKey.ER_NAMESPACE_PREFIX, new Object[] { qname.substring(0, col) } )); } } } return uri; } /** * Returns the URI of prefix (if any) * * @param prefix the prefix whose URI is searched for * @return the namespace URI currently associated with the * prefix, null if the prefix is undefined. */ public String getNamespaceURIFromPrefix(String prefix) { String uri = null; if (m_prefixMap != null) uri = m_prefixMap.lookupNamespace(prefix); return uri; } /** * Entity reference event. * * @param name Name of entity * * @throws org.xml.sax.SAXException */ public void entityReference(String name) throws org.xml.sax.SAXException { flushPending(); startEntity(name); endEntity(name); if (m_tracer != null) fireEntityReference(name); } /** * Sets the transformer associated with this serializer * @param t the transformer associated with this serializer. * @see SerializationHandler#setTransformer(Transformer) */ public void setTransformer(Transformer t) { m_transformer = t; // If this transformer object implements the SerializerTrace interface // then assign m_tracer to the transformer object so it can be used // to fire trace events. if ((m_transformer instanceof SerializerTrace) && (((SerializerTrace) m_transformer).hasTraceListeners())) { m_tracer = (SerializerTrace) m_transformer; } else { m_tracer = null; } } /** * Gets the transformer associated with this serializer * @return returns the transformer associated with this serializer. * @see SerializationHandler#getTransformer() */ public Transformer getTransformer() { return m_transformer; } /** * This method gets the nodes value as a String and uses that String as if * it were an input character notification. * @param node the Node to serialize * @throws org.xml.sax.SAXException */ public void characters(org.w3c.dom.Node node) throws org.xml.sax.SAXException { flushPending(); String data = node.getNodeValue(); if (data != null) { final int length = data.length(); if (length > m_charsBuff.length) { m_charsBuff = new char[length * 2 + 1]; } data.getChars(0, length, m_charsBuff, 0); characters(m_charsBuff, 0, length); } } /** * @see org.xml.sax.ErrorHandler#error(SAXParseException) */ public void error(SAXParseException exc) throws SAXException { } /** * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException) */ public void fatalError(SAXParseException exc) throws SAXException { m_elemContext.m_startTagOpen = false; } /** * @see org.xml.sax.ErrorHandler#warning(SAXParseException) */ public void warning(SAXParseException exc) throws SAXException { } /** * To fire off start entity trace event * @param name Name of entity */ protected void fireStartEntity(String name) throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF, name); } } /** * Report the characters event * @param chars content of characters * @param start starting index of characters to output * @param length number of characters to output */ // protected void fireCharEvent(char[] chars, int start, int length) // throws org.xml.sax.SAXException // { // if (m_tracer != null) // m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length); // } // /** * This method is only used internally when flushing the writer from the * various fire...() trace events. Due to the writer being wrapped with * SerializerTraceWriter it may cause the flush of these trace events: * EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS * EVENTTYPE_OUTPUT_CHARACTERS * which trace the output written to the output stream. * */ private void flushMyWriter() { if (m_writer != null) { try { m_writer.flush(); } catch(IOException ioe) { } } } /** * Report the CDATA trace event * @param chars content of CDATA * @param start starting index of characters to output * @param length number of characters to output */ protected void fireCDATAEvent(char[] chars, int start, int length) throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CDATA, chars, start,length); } } /** * Report the comment trace event * @param chars content of comment * @param start starting index of comment to output * @param length number of characters to output */ protected void fireCommentEvent(char[] chars, int start, int length) throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_COMMENT, new String(chars, start, length)); } } /** * To fire off end entity trace event * @param name Name of entity */ public void fireEndEntity(String name) throws org.xml.sax.SAXException { if (m_tracer != null) flushMyWriter(); // we do not need to handle this. } /** * To fire off start document trace event */ protected void fireStartDoc() throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTDOCUMENT); } } /** * To fire off end document trace event */ protected void fireEndDoc() throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDDOCUMENT); } } /** * Report the start element trace event. This trace method needs to be * called just before the attributes are cleared. * * @param elemName the qualified name of the element * */ protected void fireStartElem(String elemName) throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTELEMENT, elemName, m_attributes); } } /** * To fire off the end element event * @param name Name of element */ // protected void fireEndElem(String name) // throws org.xml.sax.SAXException // { // if (m_tracer != null) // m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null); // } /** * To fire off the PI trace event * @param name Name of PI */ protected void fireEscapingEvent(String name, String data) throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_PI,name, data); } } /** * To fire off the entity reference trace event * @param name Name of entity reference */ protected void fireEntityReference(String name) throws org.xml.sax.SAXException { if (m_tracer != null) { flushMyWriter(); m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF,name, (Attributes)null); } } /** * Receive notification of the beginning of a document. * This method is never a self generated call, * but only called externally. * *

The SAX parser will invoke this method only once, before any * other methods in this interface or in DTDHandler (except for * setDocumentLocator).

* * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException */ public void startDocument() throws org.xml.sax.SAXException { // if we do get called with startDocument(), handle it right away startDocumentInternal(); m_needToCallStartDocument = false; return; } /** * This method handles what needs to be done at a startDocument() call, * whether from an external caller, or internally called in the * serializer. For historical reasons the serializer is flexible to * startDocument() not always being called. * Even if no external call is * made into startDocument() this method will always be called as a self * generated internal startDocument, it handles what needs to be done at a * startDocument() call. * * This method exists just to make sure that startDocument() is only ever * called from an external caller, which in principle is just a matter of * style. * * @throws SAXException */ protected void startDocumentInternal() throws org.xml.sax.SAXException { if (m_tracer != null) this.fireStartDoc(); } /* This method extracts version and encoding information from SAX events. */ protected void setDocumentInfo() { if (m_locator == null) return; try{ String strVersion = ((Locator2)m_locator).getXMLVersion(); if (strVersion != null) setVersion(strVersion); /*String strEncoding = ((Locator2)m_locator).getEncoding(); if (strEncoding != null) setEncoding(strEncoding); */ }catch(ClassCastException e){} } /** * This method is used to set the source locator, which might be used to * generated an error message. * @param locator the source locator * * @see ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator) */ public void setSourceLocator(SourceLocator locator) { m_sourceLocator = locator; } /** * Used only by TransformerSnapshotImpl to restore the serialization * to a previous state. * * @param mappings NamespaceMappings */ public void setNamespaceMappings(NamespaceMappings mappings) { m_prefixMap = mappings; } public boolean reset() { resetSerializerBase(); return true; } /** * Reset all of the fields owned by SerializerBase * */ private void resetSerializerBase() { this.m_attributes.clear(); this.m_cdataSectionElements = null; this.m_elemContext = new ElemContext(); this.m_doctypePublic = null; this.m_doctypeSystem = null; this.m_doIndent = false; this.m_encoding = null; this.m_indentAmount = 0; this.m_inEntityRef = false; this.m_inExternalDTD = false; this.m_mediatype = null; this.m_needToCallStartDocument = true; this.m_needToOutputDocTypeDecl = false; if (this.m_prefixMap != null) this.m_prefixMap.reset(); this.m_shouldNotWriteXMLHeader = false; this.m_sourceLocator = null; this.m_standalone = null; this.m_standaloneWasSpecified = false; this.m_tracer = null; this.m_transformer = null; this.m_version = null; // don't set writer to null, so that it might be re-used //this.m_writer = null; } /** * Returns true if the serializer is used for temporary output rather than * final output. * * This concept is made clear in the XSLT 2.0 draft. */ final boolean inTemporaryOutputState() { /* This is a hack. We should really be letting the serializer know * that it is in temporary output state with an explicit call, but * from a pragmatic point of view (for now anyways) having no output * encoding at all, not even the default UTF-8 indicates that the serializer * is being used for temporary RTF. */ return (getEncoding() == null); } /** * This method adds an attribute the the current element, * but should not be used for an xsl:attribute child. * @see ExtendedContentHandler#addAttribute(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public void addAttribute(String uri, String localName, String rawName, String type, String value) throws SAXException { if (m_elemContext.m_startTagOpen) { addAttributeAlways(uri, localName, rawName, type, value, false); } } /** * @see org.xml.sax.DTDHandler#notationDecl(java.lang.String, java.lang.String, java.lang.String) */ public void notationDecl(String arg0, String arg1, String arg2) throws SAXException { // This method just provides a definition to satisfy the interface // A particular sub-class of SerializerBase provides the implementation (if desired) } /** * @see org.xml.sax.DTDHandler#unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public void unparsedEntityDecl( String arg0, String arg1, String arg2, String arg3) throws SAXException { // This method just provides a definition to satisfy the interface // A particular sub-class of SerializerBase provides the implementation (if desired) } /** * If set to false the serializer does not expand DTD entities, * but leaves them as is, the default value is true. */ public void setDTDEntityExpansion(boolean expand) { // This method just provides a definition to satisfy the interface // A particular sub-class of SerializerBase provides the implementation (if desired) } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy