KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > serializer > SerializerBase


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: SerializerBase.java,v 1.1.2.2 2006/09/27 18:40:59 spericas Exp $
18  */

19 package com.sun.org.apache.xml.internal.serializer;
20
21 import java.io.IOException JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Stack JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import javax.xml.transform.SourceLocator JavaDoc;
27 import javax.xml.transform.Transformer JavaDoc;
28
29 import com.sun.org.apache.xml.internal.res.XMLErrorResources;
30 import com.sun.org.apache.xml.internal.res.XMLMessages;
31 import com.sun.org.apache.xml.internal.utils.BoolStack;
32 import org.xml.sax.Attributes JavaDoc;
33 import org.xml.sax.ContentHandler JavaDoc;
34 import org.xml.sax.Locator JavaDoc;
35 import org.xml.sax.SAXException JavaDoc;
36 import org.xml.sax.SAXParseException JavaDoc;
37
38 import javax.xml.XMLConstants JavaDoc;
39
40
41 /**
42  * This class acts as a base class for the XML "serializers"
43  * and the stream serializers.
44  * It contains a number of common fields and methods.
45  * @author Santiago Pericas-Geertsen
46  * @author G. Todd Miller
47  */

48 abstract public class SerializerBase
49     implements SerializationHandler, SerializerConstants, com.sun.org.apache.xml.internal.dtm.ref.dom2dtm.DOM2DTM.CharacterNodeHandler
50 {
51     
52
53     /**
54      * To fire off the end element trace event
55      * @param name Name of element
56      */

57     protected void fireEndElem(String JavaDoc name)
58         throws org.xml.sax.SAXException JavaDoc
59     {
60         if (m_tracer != null)
61         {
62             flushMyWriter();
63             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes JavaDoc)null);
64         }
65     }
66
67     /**
68      * Report the characters trace event
69      * @param chars content of characters
70      * @param start starting index of characters to output
71      * @param length number of characters to output
72      */

73     protected void fireCharEvent(char[] chars, int start, int length)
74         throws org.xml.sax.SAXException JavaDoc
75     {
76         if (m_tracer != null)
77         {
78             flushMyWriter();
79             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);
80         }
81     }
82
83     /**
84      * true if we still need to call startDocumentInternal()
85      */

86     protected boolean m_needToCallStartDocument = true;
87
88     /** True if a trailing "]]>" still needs to be written to be
89      * written out. Used to merge adjacent CDATA sections
90      */

91     protected boolean m_cdataTagOpen = false;
92
93     /**
94      * All the attributes of the current element, collected from
95      * startPrefixMapping() calls, or addAddtribute() calls, or
96      * from the SAX attributes in a startElement() call.
97      */

98     protected AttributesImplSerializer m_attributes = new AttributesImplSerializer();
99
100     /**
101      * Tells if we're in an EntityRef event.
102      */

103     protected boolean m_inEntityRef = false;
104
105     /** This flag is set while receiving events from the external DTD */
106     protected boolean m_inExternalDTD = false;
107
108     /**
109      * The System ID for the doc type.
110      */

111     private String JavaDoc m_doctypeSystem;
112
113     /**
114      * The public ID for the doc type.
115      */

116     private String JavaDoc m_doctypePublic;
117
118     /**
119      * Flag to tell that we need to add the doctype decl, which we can't do
120      * until the first element is encountered.
121      */

122     boolean m_needToOutputDocTypeDecl = true;
123
124     /**
125      * The character encoding. Must match the encoding used for the
126      * printWriter.
127      */

128     private String JavaDoc m_encoding = null;
129
130     /**
131      * Tells if we should write the XML declaration.
132      */

133     private boolean m_shouldNotWriteXMLHeader = false;
134
135     /**
136      * The standalone value for the doctype.
137      */

138     private String JavaDoc m_standalone;
139
140     /**
141      * True if standalone was specified.
142      */

143     protected boolean m_standaloneWasSpecified = false;
144
145     /**
146      * Flag to tell if indenting (pretty-printing) is on.
147      */

148     protected boolean m_doIndent = false;
149     /**
150      * Amount to indent.
151      */

152     protected int m_indentAmount = 0;
153
154     /**
155      * Tells the XML version, for writing out to the XML decl.
156      */

157     private String JavaDoc m_version = null;
158
159     /**
160      * The mediatype. Not used right now.
161      */

162     private String JavaDoc m_mediatype;
163
164     /**
165      * The transformer that was around when this output handler was created (if
166      * any).
167      */

168     private Transformer JavaDoc m_transformer;
169
170     /**
171      * Pairs of local names and corresponding URIs of CDATA sections. This list
172      * comes from the cdata-section-elements attribute. Every second one is a
173      * local name, and every other second one is the URI for the local name.
174      */

175     protected Vector JavaDoc m_cdataSectionElements = null;
176
177     /**
178      * Namespace support, that keeps track of currently defined
179      * prefix/uri mappings. As processed elements come and go, so do
180      * the associated mappings for that element.
181      */

182     protected NamespaceMappings m_prefixMap;
183     
184     /**
185      * Handle for firing generate events. This interface may be implemented
186      * by the referenced transformer object.
187      */

188     protected SerializerTrace m_tracer;
189     
190     protected SourceLocator JavaDoc m_sourceLocator;
191     
192
193     /**
194      * The writer to send output to. This field is only used in the ToStream
195      * serializers, but exists here just so that the fireStartDoc() and
196      * other fire... methods can flush this writer when tracing.
197      */

198     protected java.io.Writer JavaDoc m_writer = null;
199     
200     /**
201      * A reference to "stack frame" corresponding to
202      * the current element. Such a frame is pushed at a startElement()
203      * and popped at an endElement(). This frame contains information about
204      * the element, such as its namespace URI.
205      */

206     protected ElemContext m_elemContext = new ElemContext();
207     
208     /**
209      * A utility buffer for converting Strings passed to
210      * character() methods to character arrays.
211      * Reusing this buffer means not creating a new character array
212      * everytime and it runs faster.
213      */

214     protected char[] m_charsBuff = new char[60];
215     
216     /**
217      * A utility buffer for converting Strings passed to
218      * attribute methods to character arrays.
219      * Reusing this buffer means not creating a new character array
220      * everytime and it runs faster.
221      */

222     protected char[] m_attrBuff = new char[30];
223
224     /**
225      * Receive notification of a comment.
226      *
227      * @see com.sun.org.apache.xml.internal.serializer.ExtendedLexicalHandler#comment(String)
228      */

229     public void comment(String JavaDoc data) throws SAXException JavaDoc
230     {
231         final int length = data.length();
232         if (length > m_charsBuff.length)
233         {
234             m_charsBuff = new char[length * 2 + 1];
235         }
236         data.getChars(0, length, m_charsBuff, 0);
237         comment(m_charsBuff, 0, length);
238     }
239
240     /**
241       * TODO: This method is a HACK! Since XSLTC does not have access to the
242       * XML file, it sometimes generates a NS prefix of the form "ns?" for
243       * an attribute. If at runtime, when the qname of the attribute is
244       * known, another prefix is specified for the attribute, then we can get
245       * a qname of the form "ns?:otherprefix:name". This function patches the
246       * qname by simply ignoring "otherprefix".
247       */

248     protected String JavaDoc patchName(String JavaDoc qname)
249     {
250
251         
252         final int lastColon = qname.lastIndexOf(':');
253
254         if (lastColon > 0) {
255             final int firstColon = qname.indexOf(':');
256             final String JavaDoc prefix = qname.substring(0, firstColon);
257             final String JavaDoc localName = qname.substring(lastColon + 1);
258
259         // If uri is "" then ignore prefix
260
final String JavaDoc uri = m_prefixMap.lookupNamespace(prefix);
261             if (uri != null && uri.length() == 0) {
262                 return localName;
263             }
264             else if (firstColon != lastColon) {
265                 return prefix + ':' + localName;
266             }
267         }
268         return qname;
269     }
270
271     /**
272      * Returns the local name of a qualified name. If the name has no prefix,
273      * then it works as the identity (SAX2).
274      * @param qname the qualified name
275      * @return the name, but excluding any prefix and colon.
276      */

277     protected static String JavaDoc getLocalName(String JavaDoc qname)
278     {
279         final int col = qname.lastIndexOf(':');
280         return (col > 0) ? qname.substring(col + 1) : qname;
281     }
282
283     /**
284      * Receive an object for locating the origin of SAX document events.
285      *
286      * @param locator An object that can return the location of any SAX document
287      * event.
288      *
289      * Receive an object for locating the origin of SAX document events.
290      *
291      * <p>SAX parsers are strongly encouraged (though not absolutely
292      * required) to supply a locator: if it does so, it must supply
293      * the locator to the application by invoking this method before
294      * invoking any of the other methods in the DocumentHandler
295      * interface.</p>
296      *
297      * <p>The locator allows the application to determine the end
298      * position of any document-related event, even if the parser is
299      * not reporting an error. Typically, the application will
300      * use this information for reporting its own errors (such as
301      * character content that does not match an application's
302      * business rules). The information returned by the locator
303      * is probably not sufficient for use with a search engine.</p>
304      *
305      * <p>Note that the locator will return correct information only
306      * during the invocation of the events in this interface. The
307      * application should not attempt to use it at any other time.</p>
308      */

309     public void setDocumentLocator(Locator JavaDoc locator)
310     {
311         return;
312
313         // I don't do anything with this yet.
314
}
315
316     /**
317      * Adds the given attribute to the set of collected attributes , but only if
318      * there is a currently open element.
319      *
320      * An element is currently open if a startElement() notification has
321      * occured but the start of the element has not yet been written to the
322      * output. In the stream case this means that we have not yet been forced
323      * to close the elements opening tag by another notification, such as a
324      * character notification.
325      *
326      * @param uri the URI of the attribute
327      * @param localName the local name of the attribute
328      * @param rawName the qualified name of the attribute
329      * @param type the type of the attribute (probably CDATA)
330      * @param value the value of the attribute
331      * @see com.sun.org.apache.xml.internal.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
332      */

333     public void addAttribute(
334         String JavaDoc uri,
335         String JavaDoc localName,
336         String JavaDoc rawName,
337         String JavaDoc type,
338         String JavaDoc value)
339         throws SAXException JavaDoc
340     {
341         if (m_elemContext.m_startTagOpen)
342         {
343             addAttributeAlways(uri, localName, rawName, type, value);
344         }
345
346     }
347     
348     /**
349      * Adds the given attribute to the set of attributes, even if there is
350      * no currently open element. This is useful if a SAX startPrefixMapping()
351      * should need to add an attribute before the element name is seen.
352      *
353      * @param uri the URI of the attribute
354      * @param localName the local name of the attribute
355      * @param rawName the qualified name of the attribute
356      * @param type the type of the attribute (probably CDATA)
357      * @param value the value of the attribute
358      */

359     public void addAttributeAlways(
360         String JavaDoc uri,
361         String JavaDoc localName,
362         String JavaDoc rawName,
363         String JavaDoc type,
364         String JavaDoc value)
365     {
366 // final int index =
367
// (localName == null || uri == null) ?
368
// m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName);
369
int index;
370 // if (localName == null || uri == null){
371
// index = m_attributes.getIndex(rawName);
372
// }
373
// else {
374
// index = m_attributes.getIndex(uri, localName);
375
// }
376
index = m_attributes.getIndex(rawName);
377             if (index >= 0)
378             {
379                 /* We've seen the attribute before.
380                  * We may have a null uri or localName, but all
381                  * we really want to re-set is the value anyway.
382                  */

383                 m_attributes.setValue(index,value);
384             }
385             else
386             {
387                 // the attribute doesn't exist yet, create it
388
m_attributes.addAttribute(uri, localName, rawName, type, value);
389             }
390         
391     }
392   
393
394     /**
395      * Adds the given attribute to the set of collected attributes,
396      * but only if there is a currently open element. This method is only
397      * called by XSLTC.
398      *
399      * @param name the attribute's qualified name
400      * @param value the value of the attribute
401      */

402     public void addAttribute(String JavaDoc name, final String JavaDoc value)
403     {
404         if (m_elemContext.m_startTagOpen)
405         {
406             final String JavaDoc patchedName = patchName(name);
407             final String JavaDoc localName = getLocalName(patchedName);
408             final String JavaDoc uri = getNamespaceURI(patchedName, false);
409
410             addAttributeAlways(uri,localName, patchedName, "CDATA", value);
411          }
412     }
413
414
415     /**
416      * Add the given attributes to the currently collected ones. These
417      * attributes are always added, regardless of whether on not an element
418      * is currently open.
419      *
420      * When the SAX feature http://xml.org/sax/features/namespace-prefixes
421      * is enabled, a SAX parser can report ns decls as attributes in the ""
422      * namespace. Since ns decls are handled via startPrefixMapping and
423      * endPrefixMapping they should be ignored here.
424      *
425      * @param atts List of attributes to add to this list
426      */

427     public void addAttributes(Attributes JavaDoc atts) throws SAXException JavaDoc
428     {
429
430         int nAtts = atts.getLength();
431
432         for (int i = 0; i < nAtts; i++)
433         {
434             String JavaDoc uri = atts.getURI(i);
435
436             if (null == uri)
437                 uri = "";
438             
439             addAttributeAlways(
440                 uri,
441                 atts.getLocalName(i),
442                 atts.getQName(i),
443                 atts.getType(i),
444                 atts.getValue(i));
445
446         }
447     }
448
449     /**
450      * Return a {@link ContentHandler} interface into this serializer.
451      * If the serializer does not support the {@link ContentHandler}
452      * interface, it should return null.
453      *
454      * @return A {@link ContentHandler} interface into this serializer,
455      * or null if the serializer is not SAX 2 capable
456      * @throws IOException An I/O exception occured
457      */

458     public ContentHandler JavaDoc asContentHandler() throws IOException JavaDoc
459     {
460         return this;
461     }
462
463     /**
464      * Report the end of an entity.
465      *
466      * @param name The name of the entity that is ending.
467      * @throws org.xml.sax.SAXException The application may raise an exception.
468      * @see #startEntity
469      */

470     public void endEntity(String JavaDoc name) throws org.xml.sax.SAXException JavaDoc
471     {
472         if (name.equals("[dtd]"))
473             m_inExternalDTD = false;
474         m_inEntityRef = false;
475
476         if (m_tracer != null)
477             this.fireEndEntity(name);
478     }
479
480     /**
481      * Flush and close the underlying java.io.Writer. This method applies to
482      * ToStream serializers, not ToSAXHandler serializers.
483      * @see com.sun.org.apache.xml.internal.serializer.ToStream
484      */

485     public void close()
486     {
487         // do nothing (base behavior)
488
}
489
490     /**
491      * Initialize global variables
492      */

493     protected void initCDATA()
494     {
495         // CDATA stack
496
// _cdataStack = new Stack();
497
// _cdataStack.push(new Integer(-1)); // push dummy value
498
}
499
500     /**
501      * Returns the character encoding to be used in the output document.
502      * @return the character encoding to be used in the output document.
503      */

504     public String JavaDoc getEncoding()
505     {
506         return m_encoding;
507     }
508
509    /**
510      * Sets the character encoding coming from the xsl:output encoding stylesheet attribute.
511      * @param encoding the character encoding
512      */

513     public void setEncoding(String JavaDoc m_encoding)
514     {
515         this.m_encoding = m_encoding;
516     }
517
518     /**
519      * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute
520      * @param b true if the XML declaration is to be omitted from the output
521      * document.
522      */

523     public void setOmitXMLDeclaration(boolean b)
524     {
525         this.m_shouldNotWriteXMLHeader = b;
526     }
527
528
529     /**
530      * @return true if the XML declaration is to be omitted from the output
531      * document.
532      */

533     public boolean getOmitXMLDeclaration()
534     {
535         return m_shouldNotWriteXMLHeader;
536     }
537
538     /**
539      * Returns the previously set value of the value to be used as the public
540      * identifier in the document type declaration (DTD).
541      *
542      *@return the public identifier to be used in the DOCTYPE declaration in the
543      * output document.
544      */

545     public String JavaDoc getDoctypePublic()
546     {
547         return m_doctypePublic;
548     }
549
550     /** Set the value coming from the xsl:output doctype-public stylesheet attribute.
551       * @param doctypePublic the public identifier to be used in the DOCTYPE
552       * declaration in the output document.
553       */

554     public void setDoctypePublic(String JavaDoc doctypePublic)
555     {
556         this.m_doctypePublic = doctypePublic;
557     }
558
559
560     /**
561      * Returns the previously set value of the value to be used
562      * as the system identifier in the document type declaration (DTD).
563      * @return the system identifier to be used in the DOCTYPE declaration in
564      * the output document.
565      *
566      */

567     public String JavaDoc getDoctypeSystem()
568     {
569         return m_doctypeSystem;
570     }
571
572     /** Set the value coming from the xsl:output doctype-system stylesheet attribute.
573       * @param doctypeSystem the system identifier to be used in the DOCTYPE
574       * declaration in the output document.
575       */

576     public void setDoctypeSystem(String JavaDoc doctypeSystem)
577     {
578         this.m_doctypeSystem = doctypeSystem;
579     }
580
581     /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties
582      * @param doctypeSystem the system identifier to be used in the DOCTYPE
583      * declaration in the output document.
584      * @param doctypePublic the public identifier to be used in the DOCTYPE
585      * declaration in the output document.
586      */

587     public void setDoctype(String JavaDoc doctypeSystem, String JavaDoc doctypePublic)
588     {
589         this.m_doctypeSystem = doctypeSystem;
590         this.m_doctypePublic = doctypePublic;
591     }
592
593     /**
594      * Sets the value coming from the xsl:output standalone stylesheet attribute.
595      * @param standalone a value of "yes" indicates that the
596      * <code>standalone</code> delaration is to be included in the output
597      * document. This method remembers if the value was explicitly set using
598      * this method, verses if the value is the default value.
599      */

600     public void setStandalone(String JavaDoc standalone)
601     {
602         if (standalone != null)
603         {
604             m_standaloneWasSpecified = true;
605             setStandaloneInternal(standalone);
606         }
607     }
608     /**
609      * Sets the XSL standalone attribute, but does not remember if this is a
610      * default or explicite setting.
611      * @param standalone "yes" | "no"
612      */

613     protected void setStandaloneInternal(String JavaDoc standalone)
614     {
615         if ("yes".equals(standalone))
616             m_standalone = "yes";
617         else
618             m_standalone = "no";
619         
620     }
621
622     /**
623      * Gets the XSL standalone attribute
624      * @return a value of "yes" if the <code>standalone</code> delaration is to
625      * be included in the output document.
626      * @see com.sun.org.apache.xml.internal.serializer.XSLOutputAttributes#getStandalone()
627      */

628     public String JavaDoc getStandalone()
629     {
630         return m_standalone;
631     }
632
633     /**
634      * @return true if the output document should be indented to visually
635      * indicate its structure.
636      */

637     public boolean getIndent()
638     {
639         return m_doIndent;
640     }
641     /**
642      * Gets the mediatype the media-type or MIME type associated with the output
643      * document.
644      * @return the mediatype the media-type or MIME type associated with the
645      * output document.
646      */

647     public String JavaDoc getMediaType()
648     {
649         return m_mediatype;
650     }
651
652     /**
653      * Gets the version of the output format.
654      * @return the version of the output format.
655      */

656     public String JavaDoc getVersion()
657     {
658         return m_version;
659     }
660
661     /**
662      * Sets the value coming from the xsl:output version attribute.
663      * @param version the version of the output format.
664      * @see com.sun.org.apache.xml.internal.serializer.SerializationHandler#setVersion(String)
665      */

666     public void setVersion(String JavaDoc version)
667     {
668         m_version = version;
669     }
670
671     /**
672      * Sets the value coming from the xsl:output media-type stylesheet attribute.
673      * @param mediaType the non-null media-type or MIME type associated with the
674      * output document.
675      * @see javax.xml.transform.OutputKeys#MEDIA_TYPE
676      * @see com.sun.org.apache.xml.internal.serializer.SerializationHandler#setMediaType(String)
677      */

678     public void setMediaType(String JavaDoc mediaType)
679     {
680         m_mediatype = mediaType;
681     }
682
683     /**
684      * @return the number of spaces to indent for each indentation level.
685      */

686     public int getIndentAmount()
687     {
688         return m_indentAmount;
689     }
690
691     /**
692      * Sets the indentation amount.
693      * @param m_indentAmount The m_indentAmount to set
694      */

695     public void setIndentAmount(int m_indentAmount)
696     {
697         this.m_indentAmount = m_indentAmount;
698     }
699
700     /**
701      * Sets the value coming from the xsl:output indent stylesheet
702      * attribute.
703      * @param doIndent true if the output document should be indented to
704      * visually indicate its structure.
705      * @see com.sun.org.apache.xml.internal.serializer.XSLOutputAttributes#setIndent(boolean)
706      */

707     public void setIndent(boolean doIndent)
708     {
709         m_doIndent = doIndent;
710     }
711
712     /**
713      * This method is used when a prefix/uri namespace mapping
714      * is indicated after the element was started with a
715      * startElement() and before and endElement().
716      * startPrefixMapping(prefix,uri) would be used before the
717      * startElement() call.
718      * @param uri the URI of the namespace
719      * @param prefix the prefix associated with the given URI.
720      *
721      * @see com.sun.org.apache.xml.internal.serializer.ExtendedContentHandler#namespaceAfterStartElement(String, String)
722      */

723     public void namespaceAfterStartElement(String JavaDoc uri, String JavaDoc prefix)
724         throws SAXException JavaDoc
725     {
726         // default behavior is to do nothing
727
}
728
729     /**
730      * Return a {@link DOMSerializer} interface into this serializer. If the
731      * serializer does not support the {@link DOMSerializer} interface, it should
732      * return null.
733      *
734      * @return A {@link DOMSerializer} interface into this serializer, or null
735      * if the serializer is not DOM capable
736      * @throws IOException An I/O exception occured
737      * @see com.sun.org.apache.xml.internal.serializer.Serializer#asDOMSerializer()
738      */

739     public DOMSerializer asDOMSerializer() throws IOException JavaDoc
740     {
741         return this;
742     }
743
744     /**
745      * Push a boolean state based on if the name of the element
746      * is found in the list of qnames. A state is only pushed if
747      * there were some cdata-section-names were specified.
748      *
749      * @param namespaceURI Should be a non-null reference to the namespace URL
750      * of the element that owns the state, or empty string.
751      * @param localName Should be a non-null reference to the local name
752      * of the element that owns the state.
753      *
754      * Hidden parameters are the vector of qualified elements specified in
755      * cdata-section-names attribute, and the m_cdataSectionStates stack
756      * onto which whether the current element is in the list is pushed (true or
757      * false). Other hidden parameters are the current elements namespaceURI,
758      * localName and qName
759      */

760     protected boolean isCdataSection()
761     {
762
763         boolean b = false;
764
765         if (null != m_cdataSectionElements)
766         {
767             if (m_elemContext.m_elementLocalName == null)
768                 m_elemContext.m_elementLocalName =
769                     getLocalName(m_elemContext.m_elementName);
770             if (m_elemContext.m_elementURI == null)
771             {
772                 String JavaDoc prefix = getPrefixPart(m_elemContext.m_elementName);
773                 if (prefix != null)
774                     m_elemContext.m_elementURI =
775                         m_prefixMap.lookupNamespace(prefix);
776
777             }
778
779             if ((null != m_elemContext.m_elementURI)
780                 && m_elemContext.m_elementURI.length() == 0)
781                 m_elemContext.m_elementURI = null;
782
783             int nElems = m_cdataSectionElements.size();
784
785             // loop through 2 at a time, as these are pairs of URI and localName
786
for (int i = 0; i < nElems; i += 2)
787             {
788                 String JavaDoc uri = (String JavaDoc) m_cdataSectionElements.elementAt(i);
789                 String JavaDoc loc = (String JavaDoc) m_cdataSectionElements.elementAt(i + 1);
790                 if (loc.equals(m_elemContext.m_elementLocalName)
791                     && subPartMatch(m_elemContext.m_elementURI, uri))
792                 {
793                     b = true;
794
795                     break;
796                 }
797             }
798         }
799         return b;
800     }
801
802     /**
803      * Tell if two strings are equal, without worry if the first string is null.
804      *
805      * @param p String reference, which may be null.
806      * @param t String reference, which may be null.
807      *
808      * @return true if strings are equal.
809      */

810     private static final boolean subPartMatch(String JavaDoc p, String JavaDoc t)
811     {
812         return (p == t) || ((null != p) && (p.equals(t)));
813     }
814
815     /**
816      * Returns the local name of a qualified name.
817      * If the name has no prefix,
818      * then it works as the identity (SAX2).
819      *
820      * @param qname a qualified name
821      * @return returns the prefix of the qualified name,
822      * or null if there is no prefix.
823      */

824     protected static final String JavaDoc getPrefixPart(String JavaDoc qname)
825     {
826         final int col = qname.indexOf(':');
827         return (col > 0) ? qname.substring(0, col) : null;
828         //return (col > 0) ? qname.substring(0,col) : "";
829
}
830
831     /**
832      * Some users of the serializer may need the current namespace mappings
833      * @return the current namespace mappings (prefix/uri)
834      * @see com.sun.org.apache.xml.internal.serializer.ExtendedContentHandler#getNamespaceMappings()
835      */

836     public NamespaceMappings getNamespaceMappings()
837     {
838         return m_prefixMap;
839     }
840
841     /**
842      * Returns the prefix currently pointing to the given URI (if any).
843      * @param namespaceURI the uri of the namespace in question
844      * @return a prefix pointing to the given URI (if any).
845      * @see com.sun.org.apache.xml.internal.serializer.ExtendedContentHandler#getPrefix(String)
846      */

847     public String JavaDoc getPrefix(String JavaDoc namespaceURI)
848     {
849         String JavaDoc prefix = m_prefixMap.lookupPrefix(namespaceURI);
850         return prefix;
851     }
852
853     /**
854      * Returns the URI of an element or attribute. Note that default namespaces
855      * do not apply directly to attributes.
856      * @param qname a qualified name
857      * @param isElement true if the qualified name is the name of
858      * an element.
859      * @return returns the namespace URI associated with the qualified name.
860      */

861     public String JavaDoc getNamespaceURI(String JavaDoc qname, boolean isElement)
862     {
863         String JavaDoc uri = EMPTYSTRING;
864         int col = qname.lastIndexOf(':');
865         final String JavaDoc prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING;
866
867         if (!EMPTYSTRING.equals(prefix) || isElement)
868         {
869             if (m_prefixMap != null)
870             {
871                 uri = m_prefixMap.lookupNamespace(prefix);
872                 if (uri == null && !prefix.equals(XMLNS_PREFIX))
873                 {
874                     throw new RuntimeException JavaDoc(
875                         XMLMessages.createXMLMessage(
876                             XMLErrorResources.ER_NAMESPACE_PREFIX,
877                             new Object JavaDoc[] { qname.substring(0, col) } ));
878                 }
879             }
880         }
881         return uri;
882     }
883
884     /**
885      * Returns the URI of prefix (if any)
886      *
887      * @param prefix the prefix whose URI is searched for
888      * @return the namespace URI currently associated with the
889      * prefix, null if the prefix is undefined.
890      */

891     public String JavaDoc getNamespaceURIFromPrefix(String JavaDoc prefix)
892     {
893         String JavaDoc uri = null;
894         if (m_prefixMap != null)
895             uri = m_prefixMap.lookupNamespace(prefix);
896         return uri;
897     }
898
899     /**
900      * Entity reference event.
901      *
902      * @param name Name of entity
903      *
904      * @throws org.xml.sax.SAXException
905      */

906     public void entityReference(String JavaDoc name) throws org.xml.sax.SAXException JavaDoc
907     {
908
909         flushPending();
910
911         startEntity(name);
912         endEntity(name);
913
914         if (m_tracer != null)
915             fireEntityReference(name);
916     }
917
918     /**
919      * Sets the transformer associated with this serializer
920      * @param t the transformer associated with this serializer.
921      * @see com.sun.org.apache.xml.internal.serializer.SerializationHandler#setTransformer(Transformer)
922      */

923     public void setTransformer(Transformer JavaDoc t)
924     {
925         m_transformer = t;
926         
927         // If this transformer object implements the SerializerTrace interface
928
// then assign m_tracer to the transformer object so it can be used
929
// to fire trace events.
930
if ((m_transformer instanceof SerializerTrace) &&
931             (((SerializerTrace) m_transformer).hasTraceListeners())) {
932            m_tracer = (SerializerTrace) m_transformer;
933         } else {
934            m_tracer = null;
935         }
936     }
937     /**
938      * Gets the transformer associated with this serializer
939      * @return returns the transformer associated with this serializer.
940      * @see com.sun.org.apache.xml.internal.serializer.SerializationHandler#getTransformer()
941      */

942     public Transformer JavaDoc getTransformer()
943     {
944         return m_transformer;
945     }
946     
947     /**
948      * This method gets the nodes value as a String and uses that String as if
949      * it were an input character notification.
950      * @param node the Node to serialize
951      * @throws org.xml.sax.SAXException
952      */

953     public void characters(org.w3c.dom.Node JavaDoc node)
954         throws org.xml.sax.SAXException JavaDoc
955     {
956         flushPending();
957         String JavaDoc data = node.getNodeValue();
958         if (data != null)
959         {
960             final int length = data.length();
961             if (length > m_charsBuff.length)
962             {
963                 m_charsBuff = new char[length * 2 + 1];
964             }
965             data.getChars(0, length, m_charsBuff, 0);
966             characters(m_charsBuff, 0, length);
967         }
968     }
969     
970
971     /**
972      * @see org.xml.sax.ErrorHandler#error(SAXParseException)
973      */

974     public void error(SAXParseException JavaDoc exc) throws SAXException JavaDoc {
975     }
976
977     /**
978      * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
979      */

980     public void fatalError(SAXParseException JavaDoc exc) throws SAXException JavaDoc {
981         
982       m_elemContext.m_startTagOpen = false;
983
984     }
985
986     /**
987      * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
988      */

989     public void warning(SAXParseException JavaDoc exc) throws SAXException JavaDoc
990     {
991     }
992
993     /**
994      * To fire off start entity trace event
995      * @param name Name of entity
996      */

997     protected void fireStartEntity(String JavaDoc name)
998         throws org.xml.sax.SAXException JavaDoc
999     {
1000        if (m_tracer != null)
1001        {
1002            flushMyWriter();
1003            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF, name);
1004        }
1005    }
1006
1007    /**
1008     * Report the characters event
1009     * @param chars content of characters
1010     * @param start starting index of characters to output
1011     * @param length number of characters to output
1012     */

1013// protected void fireCharEvent(char[] chars, int start, int length)
1014
// throws org.xml.sax.SAXException
1015
// {
1016
// if (m_tracer != null)
1017
// m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);
1018
// }
1019
//
1020

1021    /**
1022     * This method is only used internally when flushing the writer from the
1023     * various fire...() trace events. Due to the writer being wrapped with
1024     * SerializerTraceWriter it may cause the flush of these trace events:
1025     * EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS
1026     * EVENTTYPE_OUTPUT_CHARACTERS
1027     * which trace the output written to the output stream.
1028     *
1029     */

1030    private void flushMyWriter()
1031    {
1032        if (m_writer != null)
1033        {
1034            try
1035            {
1036                m_writer.flush();
1037            }
1038            catch(IOException JavaDoc ioe)
1039            {
1040            
1041            }
1042        }
1043    }
1044    /**
1045     * Report the CDATA trace event
1046     * @param chars content of CDATA
1047     * @param start starting index of characters to output
1048     * @param length number of characters to output
1049     */

1050    protected void fireCDATAEvent(char[] chars, int start, int length)
1051        throws org.xml.sax.SAXException JavaDoc
1052    {
1053        if (m_tracer != null)
1054        {
1055            flushMyWriter();
1056            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CDATA, chars, start,length);
1057        }
1058    }
1059
1060    /**
1061     * Report the comment trace event
1062     * @param chars content of comment
1063     * @param start starting index of comment to output
1064     * @param length number of characters to output
1065     */

1066    protected void fireCommentEvent(char[] chars, int start, int length)
1067        throws org.xml.sax.SAXException JavaDoc
1068    {
1069        if (m_tracer != null)
1070        {
1071            flushMyWriter();
1072            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_COMMENT, new String JavaDoc(chars, start, length));
1073        }
1074    }
1075
1076
1077    /**
1078     * To fire off end entity trace event
1079     * @param name Name of entity
1080     */

1081    public void fireEndEntity(String JavaDoc name)
1082        throws org.xml.sax.SAXException JavaDoc
1083    {
1084        if (m_tracer != null)
1085            flushMyWriter();
1086        // we do not need to handle this.
1087
}
1088
1089    /**
1090     * To fire off start document trace event
1091     */

1092     protected void fireStartDoc()
1093        throws org.xml.sax.SAXException JavaDoc
1094    {
1095        if (m_tracer != null)
1096        {
1097            flushMyWriter();
1098            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTDOCUMENT);
1099        }
1100    }
1101
1102
1103    /**
1104     * To fire off end document trace event
1105     */

1106    protected void fireEndDoc()
1107        throws org.xml.sax.SAXException JavaDoc
1108    {
1109        if (m_tracer != null)
1110        {
1111            flushMyWriter();
1112            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDDOCUMENT);
1113        }
1114    }
1115    
1116    /**
1117     * Report the start element trace event. This trace method needs to be
1118     * called just before the attributes are cleared.
1119     *
1120     * @param elemName the qualified name of the element
1121     *
1122     */

1123    protected void fireStartElem(String JavaDoc elemName)
1124        throws org.xml.sax.SAXException JavaDoc
1125    {
1126        if (m_tracer != null)
1127        {
1128            flushMyWriter();
1129            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTELEMENT,
1130                elemName, m_attributes);
1131        }
1132    }
1133
1134
1135    /**
1136     * To fire off the end element event
1137     * @param name Name of element
1138     */

1139// protected void fireEndElem(String name)
1140
// throws org.xml.sax.SAXException
1141
// {
1142
// if (m_tracer != null)
1143
// m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);
1144
// }
1145

1146
1147    /**
1148     * To fire off the PI trace event
1149     * @param name Name of PI
1150     */

1151    protected void fireEscapingEvent(String JavaDoc name, String JavaDoc data)
1152        throws org.xml.sax.SAXException JavaDoc
1153    {
1154
1155        if (m_tracer != null)
1156        {
1157            flushMyWriter();
1158            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_PI,name, data);
1159        }
1160    }
1161
1162
1163    /**
1164     * To fire off the entity reference trace event
1165     * @param name Name of entity reference
1166     */

1167    protected void fireEntityReference(String JavaDoc name)
1168        throws org.xml.sax.SAXException JavaDoc
1169    {
1170        if (m_tracer != null)
1171        {
1172            flushMyWriter();
1173            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF,name, (Attributes JavaDoc)null);
1174        }
1175    }
1176
1177    /**
1178     * Receive notification of the beginning of a document.
1179     * This method is never a self generated call,
1180     * but only called externally.
1181     *
1182     * <p>The SAX parser will invoke this method only once, before any
1183     * other methods in this interface or in DTDHandler (except for
1184     * setDocumentLocator).</p>
1185     *
1186     * @throws org.xml.sax.SAXException Any SAX exception, possibly
1187     * wrapping another exception.
1188     *
1189     * @throws org.xml.sax.SAXException
1190     */

1191    public void startDocument() throws org.xml.sax.SAXException JavaDoc
1192    {
1193
1194        // if we do get called with startDocument(), handle it right away
1195
startDocumentInternal();
1196        m_needToCallStartDocument = false;
1197        return;
1198    }
1199    
1200    /**
1201     * This method handles what needs to be done at a startDocument() call,
1202     * whether from an external caller, or internally called in the
1203     * serializer. Historically Xalan has not always called a startDocument()
1204     * although it always calls endDocument() on the serializer.
1205     * So the serializer must be flexible for that. Even if no external call is
1206     * made into startDocument() this method will always be called as a self
1207     * generated internal startDocument, it handles what needs to be done at a
1208     * startDocument() call.
1209     *
1210     * This method exists just to make sure that startDocument() is only ever
1211     * called from an external caller, which in principle is just a matter of
1212     * style.
1213     *
1214     * @throws SAXException
1215     */

1216    protected void startDocumentInternal() throws org.xml.sax.SAXException JavaDoc
1217    {
1218        if (m_tracer != null)
1219            this.fireStartDoc();
1220    }
1221    /**
1222     * This method is used to set the source locator, which might be used to
1223     * generated an error message.
1224     * @param locator the source locator
1225     *
1226     * @see com.sun.org.apache.xml.internal.serializer.ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
1227     */

1228    public void setSourceLocator(SourceLocator JavaDoc locator)
1229    {
1230        m_sourceLocator = locator;
1231    }
1232
1233    
1234    /**
1235     * Used only by TransformerSnapshotImpl to restore the serialization
1236     * to a previous state.
1237     *
1238     * @param NamespaceMappings
1239     */

1240    public void setNamespaceMappings(NamespaceMappings mappings) {
1241        m_prefixMap = mappings;
1242    }
1243    
1244    public boolean reset()
1245    {
1246        resetSerializerBase();
1247        return true;
1248    }
1249    
1250    /**
1251     * Reset all of the fields owned by SerializerBase
1252     *
1253     */

1254    private void resetSerializerBase()
1255    {
1256        this.m_attributes.clear();
1257        this.m_cdataSectionElements = null;
1258        this.m_elemContext = new ElemContext();
1259        this.m_doctypePublic = null;
1260        this.m_doctypeSystem = null;
1261        this.m_doIndent = false;
1262        this.m_encoding = null;
1263        this.m_indentAmount = 0;
1264        this.m_inEntityRef = false;
1265        this.m_inExternalDTD = false;
1266        this.m_mediatype = null;
1267        this.m_needToCallStartDocument = true;
1268        this.m_needToOutputDocTypeDecl = false;
1269        if (this.m_prefixMap != null)
1270            this.m_prefixMap.reset();
1271        this.m_shouldNotWriteXMLHeader = false;
1272        this.m_sourceLocator = null;
1273        this.m_standalone = null;
1274        this.m_standaloneWasSpecified = false;
1275        this.m_tracer = null;
1276        this.m_transformer = null;
1277        this.m_version = null;
1278        // don't set writer to null, so that it might be re-used
1279
//this.m_writer = null;
1280
}
1281
1282}
1283
Popular Tags