Save This Page
Home » openjdk-7 » com.sun.org.apache.xml.internal » serializer » [javadoc | source]
    1   /*
    2    * reserved comment block
    3    * DO NOT REMOVE OR ALTER!
    4    */
    5   /*
    6    * Copyright 1999-2004 The Apache Software Foundation.
    7    *
    8    * Licensed under the Apache License, Version 2.0 (the "License");
    9    * you may not use this file except in compliance with the License.
   10    * You may obtain a copy of the License at
   11    *
   12    *     http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing, software
   15    * distributed under the License is distributed on an "AS IS" BASIS,
   16    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   17    * See the License for the specific language governing permissions and
   18    * limitations under the License.
   19    */
   20   /*
   21    * $Id: ToUnknownStream.java,v 1.3 2005/09/28 13:49:08 pvedula Exp $
   22    */
   23   package com.sun.org.apache.xml.internal.serializer;
   24   
   25   import java.io.IOException;
   26   import java.io.OutputStream;
   27   import java.io.Writer;
   28   import java.util.Properties;
   29   import java.util.Vector;
   30   
   31   import javax.xml.transform.SourceLocator;
   32   import javax.xml.transform.Transformer;
   33   
   34   import org.w3c.dom.Node;
   35   import org.xml.sax.Attributes;
   36   import org.xml.sax.ContentHandler;
   37   import org.xml.sax.Locator;
   38   import org.xml.sax.SAXException;
   39   
   40   
   41   /**
   42    *This class wraps another SerializationHandler. The wrapped object will either
   43    * handler XML or HTML, which is not known until a little later when the first XML
   44    * tag is seen.  If the first tag is <html> then the wrapped object is an HTML
   45    * handler, otherwise it is an XML handler.
   46    *
   47    * This class effectively caches the first few calls to it then passes them
   48    * on to the wrapped handler (once it exists).  After that subsequent calls a
   49    * simply passed directly to the wrapped handler.
   50    *
   51    * The user of this class doesn't know if the output is ultimatley XML or HTML.
   52    *
   53    * This class is not a public API, it is public because it is used within Xalan.
   54    * @xsl.usage internal
   55    */
   56   public final class ToUnknownStream extends SerializerBase
   57   {
   58   
   59       /**
   60        * The wrapped handler, initially XML but possibly switched to HTML
   61        */
   62       private SerializationHandler m_handler;
   63   
   64       /**
   65        * A String with no characters
   66        */
   67       private static final String EMPTYSTRING = "";
   68   
   69       /**
   70        * true if the underlying handler (XML or HTML) is fully initialized
   71        */
   72       private boolean m_wrapped_handler_not_initialized = false;
   73   
   74   
   75       /**
   76        * the prefix of the very first tag in the document
   77        */
   78       private String m_firstElementPrefix;
   79       /**
   80        * the element name (including any prefix) of the very first tag in the document
   81        */
   82       private String m_firstElementName;
   83   
   84       /**
   85        * the namespace URI associated with the first element
   86        */
   87       private String m_firstElementURI;
   88   
   89       /**
   90        * the local name (no prefix) associated with the first element
   91        */
   92       private String m_firstElementLocalName = null;
   93   
   94       /**
   95        * true if the first tag has been emitted to the wrapped handler
   96        */
   97       private boolean m_firstTagNotEmitted = true;
   98   
   99       /**
  100        * A collection of namespace URI's (only for first element).
  101        * _namespacePrefix has the matching prefix for these URI's
  102        */
  103       private Vector m_namespaceURI = null;
  104       /**
  105        * A collection of namespace Prefix (only for first element)
  106        * _namespaceURI has the matching URIs for these prefix'
  107        */
  108       private Vector m_namespacePrefix = null;
  109   
  110       /**
  111        * true if startDocument() was called before the underlying handler
  112        * was initialized
  113        */
  114       private boolean m_needToCallStartDocument = false;
  115       /**
  116        * true if setVersion() was called before the underlying handler
  117        * was initialized
  118        */
  119       private boolean m_setVersion_called = false;
  120       /**
  121        * true if setDoctypeSystem() was called before the underlying handler
  122        * was initialized
  123        */
  124       private boolean m_setDoctypeSystem_called = false;
  125       /**
  126        * true if setDoctypePublic() was called before the underlying handler
  127        * was initialized
  128        */
  129       private boolean m_setDoctypePublic_called = false;
  130       /**
  131        * true if setMediaType() was called before the underlying handler
  132        * was initialized
  133        */
  134       private boolean m_setMediaType_called = false;
  135   
  136       /**
  137        * Default constructor.
  138        * Initially this object wraps an XML Stream object, so _handler is never null.
  139        * That may change later to an HTML Stream object.
  140        */
  141       public ToUnknownStream()
  142       {
  143           m_handler = new ToXMLStream();
  144       }
  145   
  146       /**
  147        * @see Serializer#asContentHandler()
  148        * @return the wrapped XML or HTML handler
  149        */
  150       public ContentHandler asContentHandler() throws IOException
  151       {
  152           /* don't return the real handler ( m_handler ) because
  153            * that would expose the real handler to the outside.
  154            * Keep m_handler private so it can be internally swapped
  155            * to an HTML handler.
  156            */
  157           return this;
  158       }
  159   
  160       /**
  161        * @see SerializationHandler#close()
  162        */
  163       public void close()
  164       {
  165           m_handler.close();
  166       }
  167   
  168       /**
  169        * @see Serializer#getOutputFormat()
  170        * @return the properties of the underlying handler
  171        */
  172       public Properties getOutputFormat()
  173       {
  174           return m_handler.getOutputFormat();
  175       }
  176   
  177       /**
  178        * @see Serializer#getOutputStream()
  179        * @return the OutputStream of the underlying XML or HTML handler
  180        */
  181       public OutputStream getOutputStream()
  182       {
  183           return m_handler.getOutputStream();
  184       }
  185   
  186       /**
  187        * @see Serializer#getWriter()
  188        * @return the Writer of the underlying XML or HTML handler
  189        */
  190       public Writer getWriter()
  191       {
  192           return m_handler.getWriter();
  193       }
  194   
  195       /**
  196        * passes the call on to the underlying HTML or XML handler
  197        * @see Serializer#reset()
  198        * @return ???
  199        */
  200       public boolean reset()
  201       {
  202           return m_handler.reset();
  203       }
  204   
  205       /**
  206        * Converts the DOM node to output
  207        * @param node the DOM node to transform to output
  208        * @see DOMSerializer#serialize(Node)
  209        *
  210        */
  211       public void serialize(Node node) throws IOException
  212       {
  213           if (m_firstTagNotEmitted)
  214           {
  215               flush();
  216           }
  217           m_handler.serialize(node);
  218       }
  219   
  220       /**
  221        * @see SerializationHandler#setEscaping(boolean)
  222        */
  223       public boolean setEscaping(boolean escape) throws SAXException
  224       {
  225           return m_handler.setEscaping(escape);
  226       }
  227   
  228       /**
  229        * Set the properties of the handler
  230        * @param format the output properties to set
  231        * @see Serializer#setOutputFormat(Properties)
  232        */
  233       public void setOutputFormat(Properties format)
  234       {
  235           m_handler.setOutputFormat(format);
  236       }
  237   
  238       /**
  239        * Sets the output stream to write to
  240        * @param output the OutputStream to write to
  241        * @see Serializer#setOutputStream(OutputStream)
  242        */
  243       public void setOutputStream(OutputStream output)
  244       {
  245           m_handler.setOutputStream(output);
  246       }
  247   
  248       /**
  249        * Sets the writer to write to
  250        * @param writer the writer to write to
  251        * @see Serializer#setWriter(Writer)
  252        */
  253       public void setWriter(Writer writer)
  254       {
  255           m_handler.setWriter(writer);
  256       }
  257   
  258       /**
  259        * Adds an attribute to the currenly open tag
  260        * @param uri the URI of a namespace
  261        * @param localName the attribute name, without prefix
  262        * @param rawName the attribute name, with prefix (if any)
  263        * @param type the type of the attribute, typically "CDATA"
  264        * @param value the value of the parameter
  265        * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
  266        * @see ExtendedContentHandler#addAttribute(String, String, String, String, String)
  267        */
  268       public void addAttribute(
  269           String uri,
  270           String localName,
  271           String rawName,
  272           String type,
  273           String value)
  274           throws SAXException
  275       {
  276           addAttribute(uri, localName, rawName, type, value, false);
  277       }
  278   
  279       /**
  280        * Adds an attribute to the currenly open tag
  281        * @param uri the URI of a namespace
  282        * @param localName the attribute name, without prefix
  283        * @param rawName the attribute name, with prefix (if any)
  284        * @param type the type of the attribute, typically "CDATA"
  285        * @param value the value of the parameter
  286        * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
  287        * @see ExtendedContentHandler#addAttribute(String, String, String, String, String)
  288        */
  289       public void addAttribute(
  290           String uri,
  291           String localName,
  292           String rawName,
  293           String type,
  294           String value,
  295           boolean XSLAttribute)
  296           throws SAXException
  297       {
  298           if (m_firstTagNotEmitted)
  299           {
  300               flush();
  301           }
  302           m_handler.addAttribute(uri, localName, rawName, type, value, XSLAttribute);
  303       }
  304       /**
  305        * Adds an attribute to the currenly open tag
  306        * @param rawName the attribute name, with prefix (if any)
  307        * @param value the value of the parameter
  308        * @see ExtendedContentHandler#addAttribute(String, String)
  309        */
  310       public void addAttribute(String rawName, String value)
  311       {
  312           if (m_firstTagNotEmitted)
  313           {
  314               flush();
  315           }
  316           m_handler.addAttribute(rawName, value);
  317   
  318       }
  319   
  320       /**
  321        * Adds a unique attribute to the currenly open tag
  322        */
  323       public void addUniqueAttribute(String rawName, String value, int flags)
  324           throws SAXException
  325       {
  326           if (m_firstTagNotEmitted)
  327           {
  328               flush();
  329           }
  330           m_handler.addUniqueAttribute(rawName, value, flags);
  331   
  332       }
  333   
  334       /**
  335        * Converts the String to a character array and calls the SAX method
  336        * characters(char[],int,int);
  337        *
  338        * @see ExtendedContentHandler#characters(String)
  339        */
  340       public void characters(String chars) throws SAXException
  341       {
  342           final int length = chars.length();
  343           if (length > m_charsBuff.length)
  344           {
  345               m_charsBuff = new char[length*2 + 1];
  346           }
  347           chars.getChars(0, length, m_charsBuff, 0);
  348           this.characters(m_charsBuff, 0, length);
  349       }
  350   
  351       /**
  352        * Pass the call on to the underlying handler
  353        * @see ExtendedContentHandler#endElement(String)
  354        */
  355       public void endElement(String elementName) throws SAXException
  356       {
  357           if (m_firstTagNotEmitted)
  358           {
  359               flush();
  360           }
  361           m_handler.endElement(elementName);
  362       }
  363   
  364   
  365       /**
  366        * @see org.xml.sax.ContentHandler#startPrefixMapping(String, String)
  367        * @param prefix The prefix that maps to the URI
  368        * @param uri The URI for the namespace
  369        */
  370       public void startPrefixMapping(String prefix, String uri) throws SAXException
  371       {
  372           this.startPrefixMapping(prefix,uri, true);
  373       }
  374   
  375       /**
  376        * This method is used when a prefix/uri namespace mapping
  377        * is indicated after the element was started with a
  378        * startElement() and before and endElement().
  379        * startPrefixMapping(prefix,uri) would be used before the
  380        * startElement() call.
  381        * @param uri the URI of the namespace
  382        * @param prefix the prefix associated with the given URI.
  383        *
  384        * @see ExtendedContentHandler#namespaceAfterStartElement(String, String)
  385        */
  386       public void namespaceAfterStartElement(String prefix, String uri)
  387           throws SAXException
  388       {
  389           // hack for XSLTC with finding URI for default namespace
  390           if (m_firstTagNotEmitted && m_firstElementURI == null && m_firstElementName != null)
  391           {
  392               String prefix1 = getPrefixPart(m_firstElementName);
  393               if (prefix1 == null && EMPTYSTRING.equals(prefix))
  394               {
  395                   // the elements URI is not known yet, and it
  396                   // doesn't have a prefix, and we are currently
  397                   // setting the uri for prefix "", so we have
  398                   // the uri for the element... lets remember it
  399                   m_firstElementURI = uri;
  400               }
  401           }
  402           startPrefixMapping(prefix,uri, false);
  403       }
  404   
  405       public boolean startPrefixMapping(String prefix, String uri, boolean shouldFlush)
  406           throws SAXException
  407       {
  408           boolean pushed = false;
  409           if (m_firstTagNotEmitted)
  410           {
  411               if (m_firstElementName != null && shouldFlush)
  412               {
  413                   /* we've already seen a startElement, and this is a prefix mapping
  414                    * for the up coming element, so flush the old element
  415                    * then send this event on its way.
  416                    */
  417                   flush();
  418                   pushed = m_handler.startPrefixMapping(prefix, uri, shouldFlush);
  419               }
  420               else
  421               {
  422                   if (m_namespacePrefix == null)
  423                   {
  424                       m_namespacePrefix = new Vector();
  425                       m_namespaceURI = new Vector();
  426                   }
  427                   m_namespacePrefix.addElement(prefix);
  428                   m_namespaceURI.addElement(uri);
  429   
  430                   if (m_firstElementURI == null)
  431                   {
  432                       if (prefix.equals(m_firstElementPrefix))
  433                           m_firstElementURI = uri;
  434                   }
  435               }
  436   
  437           }
  438           else
  439           {
  440              pushed = m_handler.startPrefixMapping(prefix, uri, shouldFlush);
  441           }
  442           return pushed;
  443       }
  444   
  445       /**
  446         * This method cannot be cached because default is different in
  447         * HTML and XML (we need more than a boolean).
  448         */
  449   
  450       public void setVersion(String version)
  451       {
  452           m_handler.setVersion(version);
  453   
  454           // Cache call to setVersion()
  455           //       super.setVersion(version);
  456           m_setVersion_called = true;
  457       }
  458   
  459       /**
  460        * @see org.xml.sax.ContentHandler#startDocument()
  461        */
  462       public void startDocument() throws SAXException
  463       {
  464           m_needToCallStartDocument = true;
  465       }
  466   
  467   
  468   
  469       public void startElement(String qName) throws SAXException
  470       {
  471           this.startElement(null, null, qName, null);
  472       }
  473   
  474       public void startElement(String namespaceURI, String localName, String qName) throws SAXException
  475       {
  476           this.startElement(namespaceURI, localName, qName, null);
  477       }
  478   
  479       public void startElement(
  480           String namespaceURI,
  481           String localName,
  482           String elementName,
  483           Attributes atts) throws SAXException
  484       {
  485   
  486           if (m_needToCallSetDocumentInfo){
  487               super.setDocumentInfo();
  488               m_needToCallSetDocumentInfo = false;
  489           }
  490   
  491           /* we are notified of the start of an element */
  492           if (m_firstTagNotEmitted)
  493           {
  494               /* we have not yet sent the first element on its way */
  495               if (m_firstElementName != null)
  496               {
  497                   /* this is not the first element, but a later one.
  498                    * But we have the old element pending, so flush it out,
  499                    * then send this one on its way.
  500                    */
  501                   flush();
  502                   m_handler.startElement(namespaceURI, localName, elementName,  atts);
  503               }
  504               else
  505               {
  506                   /* this is the very first element that we have seen,
  507                    * so save it for flushing later.  We may yet get to know its
  508                    * URI due to added attributes.
  509                    */
  510   
  511                   m_wrapped_handler_not_initialized = true;
  512                   m_firstElementName = elementName;
  513   
  514                   // null if not known
  515                   m_firstElementPrefix = getPrefixPartUnknown(elementName);
  516   
  517                   // null if not known
  518                   m_firstElementURI = namespaceURI;
  519   
  520                   // null if not known
  521                   m_firstElementLocalName = localName;
  522   
  523                   if (m_tracer != null)
  524                       firePseudoElement(elementName);
  525   
  526                   /* we don't want to call our own addAttributes, which
  527                    * merely delegates to the wrapped handler, but we want to
  528                    * add these attributes to m_attributes. So me must call super.
  529                    * addAttributes() In this case m_attributes is only used for the
  530                    * first element, after that this class totally delegates to the
  531                    * wrapped handler which is either XML or HTML.
  532                    */
  533                   if (atts != null)
  534                       super.addAttributes(atts);
  535   
  536                   // if there are attributes, then lets make the flush()
  537                   // call the startElement on the handler and send the
  538                   // attributes on their way.
  539                   if (atts != null)
  540                       flush();
  541   
  542               }
  543           }
  544           else
  545           {
  546               // this is not the first element, but a later one, so just
  547               // send it on its way.
  548               m_handler.startElement(namespaceURI, localName, elementName,  atts);
  549           }
  550       }
  551   
  552       /**
  553        * Pass the call on to the underlying handler
  554        * @see ExtendedLexicalHandler#comment(String)
  555        */
  556       public void comment(String comment) throws SAXException
  557       {
  558           if (m_firstTagNotEmitted && m_firstElementName != null)
  559           {
  560               emitFirstTag();
  561           }
  562           else if (m_needToCallStartDocument)
  563           {
  564               m_handler.startDocument();
  565               m_needToCallStartDocument = false;
  566           }
  567   
  568           m_handler.comment(comment);
  569       }
  570   
  571       /**
  572        * Pass the call on to the underlying handler
  573        * @see XSLOutputAttributes#getDoctypePublic()
  574        */
  575       public String getDoctypePublic()
  576       {
  577   
  578           return m_handler.getDoctypePublic();
  579       }
  580   
  581       /**
  582        * Pass the call on to the underlying handler
  583        * @see XSLOutputAttributes#getDoctypeSystem()
  584        */
  585       public String getDoctypeSystem()
  586       {
  587           return m_handler.getDoctypeSystem();
  588       }
  589   
  590       /**
  591        * Pass the call on to the underlying handler
  592        * @see XSLOutputAttributes#getEncoding()
  593        */
  594       public String getEncoding()
  595       {
  596           return m_handler.getEncoding();
  597       }
  598   
  599       /**
  600        * Pass the call on to the underlying handler
  601        * @see XSLOutputAttributes#getIndent()
  602        */
  603       public boolean getIndent()
  604       {
  605           return m_handler.getIndent();
  606       }
  607   
  608       /**
  609        * Pass the call on to the underlying handler
  610        * @see XSLOutputAttributes#getIndentAmount()
  611        */
  612       public int getIndentAmount()
  613       {
  614           return m_handler.getIndentAmount();
  615       }
  616   
  617       /**
  618        * Pass the call on to the underlying handler
  619        * @see XSLOutputAttributes#getMediaType()
  620        */
  621       public String getMediaType()
  622       {
  623           return m_handler.getMediaType();
  624       }
  625   
  626       /**
  627        * Pass the call on to the underlying handler
  628        * @see XSLOutputAttributes#getOmitXMLDeclaration()
  629        */
  630       public boolean getOmitXMLDeclaration()
  631       {
  632           return m_handler.getOmitXMLDeclaration();
  633       }
  634   
  635       /**
  636        * Pass the call on to the underlying handler
  637        * @see XSLOutputAttributes#getStandalone()
  638        */
  639       public String getStandalone()
  640       {
  641           return m_handler.getStandalone();
  642       }
  643   
  644       /**
  645        * Pass the call on to the underlying handler
  646        * @see XSLOutputAttributes#getVersion()
  647        */
  648       public String getVersion()
  649       {
  650           return m_handler.getVersion();
  651       }
  652   
  653       /**
  654        * @see XSLOutputAttributes#setDoctype(String, String)
  655        */
  656       public void setDoctype(String system, String pub)
  657       {
  658           m_handler.setDoctypePublic(pub);
  659           m_handler.setDoctypeSystem(system);
  660       }
  661   
  662       /**
  663        * Set the doctype in the underlying XML handler. Remember that this method
  664        * was called, just in case we need to transfer this doctype to an HTML handler
  665        * @param doctype the public doctype to set
  666        * @see XSLOutputAttributes#setDoctypePublic(String)
  667        */
  668       public void setDoctypePublic(String doctype)
  669       {
  670           m_handler.setDoctypePublic(doctype);
  671           m_setDoctypePublic_called = true;
  672       }
  673   
  674       /**
  675        * Set the doctype in the underlying XML handler. Remember that this method
  676        * was called, just in case we need to transfer this doctype to an HTML handler
  677        * @param doctype the system doctype to set
  678        * @see XSLOutputAttributes#setDoctypeSystem(String)
  679        */
  680       public void setDoctypeSystem(String doctype)
  681       {
  682           m_handler.setDoctypeSystem(doctype);
  683           m_setDoctypeSystem_called = true;
  684       }
  685   
  686       /**
  687        * Pass the call on to the underlying handler
  688        * @see XSLOutputAttributes#setEncoding(String)
  689        */
  690       public void setEncoding(String encoding)
  691       {
  692           m_handler.setEncoding(encoding);
  693       }
  694   
  695       /**
  696        * Pass the call on to the underlying handler
  697        * @see XSLOutputAttributes#setIndent(boolean)
  698        */
  699       public void setIndent(boolean indent)
  700       {
  701           m_handler.setIndent(indent);
  702       }
  703   
  704       /**
  705        * Pass the call on to the underlying handler
  706        */
  707       public void setIndentAmount(int value)
  708       {
  709           m_handler.setIndentAmount(value);
  710       }
  711   
  712       /**
  713        * @see XSLOutputAttributes#setMediaType(String)
  714        */
  715       public void setMediaType(String mediaType)
  716       {
  717           m_handler.setMediaType(mediaType);
  718           m_setMediaType_called = true;
  719       }
  720   
  721       /**
  722        * Pass the call on to the underlying handler
  723        * @see XSLOutputAttributes#setOmitXMLDeclaration(boolean)
  724        */
  725       public void setOmitXMLDeclaration(boolean b)
  726       {
  727           m_handler.setOmitXMLDeclaration(b);
  728       }
  729   
  730       /**
  731        * Pass the call on to the underlying handler
  732        * @see XSLOutputAttributes#setStandalone(String)
  733        */
  734       public void setStandalone(String standalone)
  735       {
  736           m_handler.setStandalone(standalone);
  737       }
  738   
  739       /**
  740        * @see XSLOutputAttributes#setVersion(String)
  741        */
  742   
  743       /**
  744        * Pass the call on to the underlying handler
  745        * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String)
  746        */
  747       public void attributeDecl(
  748           String arg0,
  749           String arg1,
  750           String arg2,
  751           String arg3,
  752           String arg4)
  753           throws SAXException
  754       {
  755           m_handler.attributeDecl(arg0, arg1, arg2, arg3, arg4);
  756       }
  757   
  758       /**
  759        * Pass the call on to the underlying handler
  760        * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String)
  761        */
  762       public void elementDecl(String arg0, String arg1) throws SAXException
  763       {
  764           if (m_firstTagNotEmitted)
  765           {
  766               emitFirstTag();
  767           }
  768           m_handler.elementDecl(arg0, arg1);
  769       }
  770   
  771       /**
  772        * Pass the call on to the underlying handler
  773        * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String)
  774        */
  775       public void externalEntityDecl(
  776           String name,
  777           String publicId,
  778           String systemId)
  779           throws SAXException
  780       {
  781           if (m_firstTagNotEmitted)
  782           {
  783               flush();
  784           }
  785           m_handler.externalEntityDecl(name, publicId, systemId);
  786       }
  787   
  788       /**
  789        * Pass the call on to the underlying handler
  790        * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(String, String)
  791        */
  792       public void internalEntityDecl(String arg0, String arg1)
  793           throws SAXException
  794       {
  795           if (m_firstTagNotEmitted)
  796           {
  797               flush();
  798           }
  799           m_handler.internalEntityDecl(arg0, arg1);
  800       }
  801   
  802       /**
  803        * Pass the call on to the underlying handler
  804        * @see org.xml.sax.ContentHandler#characters(char[], int, int)
  805        */
  806       public void characters(char[] characters, int offset, int length)
  807           throws SAXException
  808       {
  809           if (m_firstTagNotEmitted)
  810           {
  811               flush();
  812           }
  813   
  814           m_handler.characters(characters, offset, length);
  815   
  816       }
  817   
  818       /**
  819        * Pass the call on to the underlying handler
  820        * @see org.xml.sax.ContentHandler#endDocument()
  821        */
  822       public void endDocument() throws SAXException
  823       {
  824           if (m_firstTagNotEmitted)
  825           {
  826               flush();
  827           }
  828   
  829           m_handler.endDocument();
  830   
  831   
  832       }
  833   
  834       /**
  835        * Pass the call on to the underlying handler
  836        * @see org.xml.sax.ContentHandler#endElement(String, String, String)
  837        */
  838       public void endElement(String namespaceURI, String localName, String qName)
  839           throws SAXException
  840       {
  841           if (m_firstTagNotEmitted)
  842           {
  843               flush();
  844               if (namespaceURI == null && m_firstElementURI != null)
  845                   namespaceURI = m_firstElementURI;
  846   
  847   
  848               if (localName == null && m_firstElementLocalName != null)
  849                   localName = m_firstElementLocalName;
  850           }
  851   
  852           m_handler.endElement(namespaceURI, localName, qName);
  853       }
  854   
  855       /**
  856        * Pass the call on to the underlying handler
  857        * @see org.xml.sax.ContentHandler#endPrefixMapping(String)
  858        */
  859       public void endPrefixMapping(String prefix) throws SAXException
  860       {
  861           m_handler.endPrefixMapping(prefix);
  862       }
  863   
  864       /**
  865        * Pass the call on to the underlying handler
  866        * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
  867        */
  868       public void ignorableWhitespace(char[] ch, int start, int length)
  869           throws SAXException
  870       {
  871           if (m_firstTagNotEmitted)
  872           {
  873               flush();
  874           }
  875           m_handler.ignorableWhitespace(ch, start, length);
  876       }
  877   
  878       /**
  879        * Pass the call on to the underlying handler
  880        * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
  881        */
  882       public void processingInstruction(String target, String data)
  883           throws SAXException
  884       {
  885             if (m_firstTagNotEmitted)
  886           {
  887               flush();
  888           }
  889   
  890           m_handler.processingInstruction(target, data);
  891       }
  892   
  893       /**
  894        * Pass the call on to the underlying handler
  895        * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
  896        */
  897       public void setDocumentLocator(Locator locator)
  898       {
  899           super.setDocumentLocator(locator);
  900           m_handler.setDocumentLocator(locator);
  901       }
  902   
  903       /**
  904        * Pass the call on to the underlying handler
  905        * @see org.xml.sax.ContentHandler#skippedEntity(String)
  906        */
  907       public void skippedEntity(String name) throws SAXException
  908       {
  909           m_handler.skippedEntity(name);
  910       }
  911   
  912   
  913   
  914       /**
  915        * Pass the call on to the underlying handler
  916        * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
  917        */
  918       public void comment(char[] ch, int start, int length) throws SAXException
  919       {
  920           if (m_firstTagNotEmitted)
  921           {
  922               flush();
  923           }
  924   
  925           m_handler.comment(ch, start, length);
  926       }
  927   
  928       /**
  929        * Pass the call on to the underlying handler
  930        * @see org.xml.sax.ext.LexicalHandler#endCDATA()
  931        */
  932       public void endCDATA() throws SAXException
  933       {
  934   
  935           m_handler.endCDATA();
  936       }
  937   
  938       /**
  939        * Pass the call on to the underlying handler
  940        * @see org.xml.sax.ext.LexicalHandler#endDTD()
  941        */
  942       public void endDTD() throws SAXException
  943       {
  944   
  945           m_handler.endDTD();
  946       }
  947   
  948       /**
  949        * Pass the call on to the underlying handler
  950        * @see org.xml.sax.ext.LexicalHandler#endEntity(String)
  951        */
  952       public void endEntity(String name) throws SAXException
  953       {
  954           if (m_firstTagNotEmitted)
  955           {
  956               emitFirstTag();
  957           }
  958           m_handler.endEntity(name);
  959       }
  960   
  961       /**
  962        * Pass the call on to the underlying handler
  963        * @see org.xml.sax.ext.LexicalHandler#startCDATA()
  964        */
  965       public void startCDATA() throws SAXException
  966       {
  967           m_handler.startCDATA();
  968       }
  969   
  970       /**
  971        * Pass the call on to the underlying handler
  972        * @see org.xml.sax.ext.LexicalHandler#startDTD(String, String, String)
  973        */
  974       public void startDTD(String name, String publicId, String systemId)
  975           throws SAXException
  976       {
  977           m_handler.startDTD(name, publicId, systemId);
  978       }
  979   
  980       /**
  981        * Pass the call on to the underlying handler
  982        * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
  983        */
  984       public void startEntity(String name) throws SAXException
  985       {
  986           m_handler.startEntity(name);
  987       }
  988   
  989       /**
  990        * Initialize the wrapped output stream (XML or HTML).
  991        * If the stream handler should be HTML, then replace the XML handler with
  992        * an HTML handler. After than send the starting method calls that were cached
  993        * to the wrapped handler.
  994        *
  995        */
  996       private void initStreamOutput() throws SAXException
  997       {
  998   
  999           // Try to rule out if this is an not to be an HTML document based on prefix
 1000           boolean firstElementIsHTML = isFirstElemHTML();
 1001   
 1002           if (firstElementIsHTML)
 1003           {
 1004               // create an HTML output handler, and initialize it
 1005   
 1006               // keep a reference to the old handler, ... it will soon be gone
 1007               SerializationHandler oldHandler = m_handler;
 1008   
 1009               /* We have to make sure we get an output properties with the proper
 1010                * defaults for the HTML method.  The easiest way to do this is to
 1011                * have the OutputProperties class do it.
 1012                */
 1013   
 1014               Properties htmlProperties =
 1015                   OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML);
 1016               Serializer serializer =
 1017                   SerializerFactory.getSerializer(htmlProperties);
 1018   
 1019               // The factory should be returning a ToStream
 1020               // Don't know what to do if it doesn't
 1021               // i.e. the user has over-ridden the content-handler property
 1022               // for html
 1023               m_handler = (SerializationHandler) serializer;
 1024               //m_handler = new ToHTMLStream();
 1025   
 1026               Writer writer = oldHandler.getWriter();
 1027   
 1028               if (null != writer)
 1029                   m_handler.setWriter(writer);
 1030               else
 1031               {
 1032                   OutputStream os = oldHandler.getOutputStream();
 1033   
 1034                   if (null != os)
 1035                       m_handler.setOutputStream(os);
 1036               }
 1037   
 1038               // need to copy things from the old handler to the new one here
 1039   
 1040               //            if (_setVersion_called)
 1041               //            {
 1042               m_handler.setVersion(oldHandler.getVersion());
 1043               //            }
 1044               //            if (_setDoctypeSystem_called)
 1045               //            {
 1046               m_handler.setDoctypeSystem(oldHandler.getDoctypeSystem());
 1047               //            }
 1048               //            if (_setDoctypePublic_called)
 1049               //            {
 1050               m_handler.setDoctypePublic(oldHandler.getDoctypePublic());
 1051               //            }
 1052               //            if (_setMediaType_called)
 1053               //            {
 1054               m_handler.setMediaType(oldHandler.getMediaType());
 1055               //            }
 1056   
 1057               m_handler.setTransformer(oldHandler.getTransformer());
 1058           }
 1059   
 1060           /* Now that we have a real wrapped handler (XML or HTML) lets
 1061            * pass any cached calls to it
 1062            */
 1063           // Call startDocument() if necessary
 1064           if (m_needToCallStartDocument)
 1065           {
 1066               m_handler.startDocument();
 1067               m_needToCallStartDocument = false;
 1068           }
 1069   
 1070           // the wrapped handler is now fully initialized
 1071           m_wrapped_handler_not_initialized = false;
 1072       }
 1073   
 1074       private void emitFirstTag() throws SAXException
 1075       {
 1076           if (m_firstElementName != null)
 1077           {
 1078               if (m_wrapped_handler_not_initialized)
 1079               {
 1080                   initStreamOutput();
 1081                   m_wrapped_handler_not_initialized = false;
 1082               }
 1083               // Output first tag
 1084               m_handler.startElement(m_firstElementURI, null, m_firstElementName, m_attributes);
 1085               // don't need the collected attributes of the first element anymore.
 1086               m_attributes = null;
 1087   
 1088               // Output namespaces of first tag
 1089               if (m_namespacePrefix != null)
 1090               {
 1091                   final int n = m_namespacePrefix.size();
 1092                   for (int i = 0; i < n; i++)
 1093                   {
 1094                       final String prefix =
 1095                           (String) m_namespacePrefix.elementAt(i);
 1096                       final String uri = (String) m_namespaceURI.elementAt(i);
 1097                       m_handler.startPrefixMapping(prefix, uri, false);
 1098                   }
 1099                   m_namespacePrefix = null;
 1100                   m_namespaceURI = null;
 1101               }
 1102               m_firstTagNotEmitted = false;
 1103           }
 1104       }
 1105   
 1106       /**
 1107        * Utility function for calls to local-name().
 1108        *
 1109        * Don't want to override static function on SerializerBase
 1110        * So added Unknown suffix to method name.
 1111        */
 1112       private String getLocalNameUnknown(String value)
 1113       {
 1114           int idx = value.lastIndexOf(':');
 1115           if (idx >= 0)
 1116               value = value.substring(idx + 1);
 1117           idx = value.lastIndexOf('@');
 1118           if (idx >= 0)
 1119               value = value.substring(idx + 1);
 1120           return (value);
 1121       }
 1122   
 1123       /**
 1124            * Utility function to return prefix
 1125            *
 1126            * Don't want to override static function on SerializerBase
 1127            * So added Unknown suffix to method name.
 1128            */
 1129       private String getPrefixPartUnknown(String qname)
 1130       {
 1131           final int index = qname.indexOf(':');
 1132           return (index > 0) ? qname.substring(0, index) : EMPTYSTRING;
 1133       }
 1134   
 1135       /**
 1136        * Determine if the firts element in the document is <html> or <HTML>
 1137        * This uses the cached first element name, first element prefix and the
 1138        * cached namespaces from previous method calls
 1139        *
 1140        * @return true if the first element is an opening <html> tag
 1141        */
 1142       private boolean isFirstElemHTML()
 1143       {
 1144           boolean isHTML;
 1145   
 1146           // is the first tag html, not considering the prefix ?
 1147           isHTML =
 1148               getLocalNameUnknown(m_firstElementName).equalsIgnoreCase("html");
 1149   
 1150           // Try to rule out if this is not to be an HTML document based on URI
 1151           if (isHTML
 1152               && m_firstElementURI != null
 1153               && !EMPTYSTRING.equals(m_firstElementURI))
 1154           {
 1155               // the <html> element has a non-trivial namespace
 1156               isHTML = false;
 1157           }
 1158           // Try to rule out if this is an not to be an HTML document based on prefix
 1159           if (isHTML && m_namespacePrefix != null)
 1160           {
 1161               /* the first element has a name of "html", but lets check the prefix.
 1162                * If the prefix points to a namespace with a URL that is not ""
 1163                * then the doecument doesn't start with an <html> tag, and isn't html
 1164                */
 1165               final int max = m_namespacePrefix.size();
 1166               for (int i = 0; i < max; i++)
 1167               {
 1168                   final String prefix = (String) m_namespacePrefix.elementAt(i);
 1169                   final String uri = (String) m_namespaceURI.elementAt(i);
 1170   
 1171                   if (m_firstElementPrefix != null
 1172                       && m_firstElementPrefix.equals(prefix)
 1173                       && !EMPTYSTRING.equals(uri))
 1174                   {
 1175                       // The first element has a prefix, so it can't be <html>
 1176                       isHTML = false;
 1177                       break;
 1178                   }
 1179               }
 1180   
 1181           }
 1182           return isHTML;
 1183       }
 1184       /**
 1185        * @see Serializer#asDOMSerializer()
 1186        */
 1187       public DOMSerializer asDOMSerializer() throws IOException
 1188       {
 1189           return m_handler.asDOMSerializer();
 1190       }
 1191   
 1192       /**
 1193        * @param URI_and_localNames Vector a list of pairs of URI/localName
 1194        * specified in the cdata-section-elements attribute.
 1195        * @see SerializationHandler#setCdataSectionElements(java.util.Vector)
 1196        */
 1197       public void setCdataSectionElements(Vector URI_and_localNames)
 1198       {
 1199           m_handler.setCdataSectionElements(URI_and_localNames);
 1200       }
 1201       /**
 1202        * @see ExtendedContentHandler#addAttributes(org.xml.sax.Attributes)
 1203        */
 1204       public void addAttributes(Attributes atts) throws SAXException
 1205       {
 1206           m_handler.addAttributes(atts);
 1207       }
 1208   
 1209       /**
 1210        * Get the current namespace mappings.
 1211        * Simply returns the mappings of the wrapped handler.
 1212        * @see ExtendedContentHandler#getNamespaceMappings()
 1213        */
 1214       public NamespaceMappings getNamespaceMappings()
 1215       {
 1216           NamespaceMappings mappings = null;
 1217           if (m_handler != null)
 1218           {
 1219               mappings = m_handler.getNamespaceMappings();
 1220           }
 1221           return mappings;
 1222       }
 1223       /**
 1224        * @see SerializationHandler#flushPending()
 1225        */
 1226       public void flushPending() throws SAXException
 1227       {
 1228   
 1229           flush();
 1230   
 1231           m_handler.flushPending();
 1232       }
 1233   
 1234       private void flush()
 1235       {
 1236           try
 1237           {
 1238           if (m_firstTagNotEmitted)
 1239           {
 1240               emitFirstTag();
 1241           }
 1242           if (m_needToCallStartDocument)
 1243           {
 1244               m_handler.startDocument();
 1245               m_needToCallStartDocument = false;
 1246           }
 1247           }
 1248           catch(SAXException e)
 1249           {
 1250               throw new RuntimeException(e.toString());
 1251           }
 1252   
 1253   
 1254       }
 1255   
 1256       /**
 1257        * @see ExtendedContentHandler#getPrefix
 1258        */
 1259       public String getPrefix(String namespaceURI)
 1260       {
 1261           return m_handler.getPrefix(namespaceURI);
 1262       }
 1263       /**
 1264        * @see ExtendedContentHandler#entityReference(java.lang.String)
 1265        */
 1266       public void entityReference(String entityName) throws SAXException
 1267       {
 1268           m_handler.entityReference(entityName);
 1269       }
 1270   
 1271       /**
 1272        * @see ExtendedContentHandler#getNamespaceURI(java.lang.String, boolean)
 1273        */
 1274       public String getNamespaceURI(String qname, boolean isElement)
 1275       {
 1276           return m_handler.getNamespaceURI(qname, isElement);
 1277       }
 1278   
 1279       public String getNamespaceURIFromPrefix(String prefix)
 1280       {
 1281           return m_handler.getNamespaceURIFromPrefix(prefix);
 1282       }
 1283   
 1284       public void setTransformer(Transformer t)
 1285       {
 1286           m_handler.setTransformer(t);
 1287           if ((t instanceof SerializerTrace) &&
 1288               (((SerializerTrace) t).hasTraceListeners())) {
 1289              m_tracer = (SerializerTrace) t;
 1290           } else {
 1291              m_tracer = null;
 1292           }
 1293       }
 1294       public Transformer getTransformer()
 1295       {
 1296           return m_handler.getTransformer();
 1297       }
 1298   
 1299       /**
 1300        * @see SerializationHandler#setContentHandler(org.xml.sax.ContentHandler)
 1301        */
 1302       public void setContentHandler(ContentHandler ch)
 1303       {
 1304           m_handler.setContentHandler(ch);
 1305       }
 1306       /**
 1307        * This method is used to set the source locator, which might be used to
 1308        * generated an error message.
 1309        * @param locator the source locator
 1310        *
 1311        * @see ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
 1312        */
 1313       public void setSourceLocator(SourceLocator locator)
 1314       {
 1315           m_handler.setSourceLocator(locator);
 1316       }
 1317   
 1318       protected void firePseudoElement(String elementName)
 1319       {
 1320   
 1321           if (m_tracer != null) {
 1322               StringBuffer sb = new StringBuffer();
 1323   
 1324               sb.append('<');
 1325               sb.append(elementName);
 1326   
 1327               // convert the StringBuffer to a char array and
 1328               // emit the trace event that these characters "might"
 1329               // be written
 1330               char ch[] = sb.toString().toCharArray();
 1331               m_tracer.fireGenerateEvent(
 1332                   SerializerTrace.EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS,
 1333                   ch,
 1334                   0,
 1335                   ch.length);
 1336           }
 1337       }
 1338   }

Save This Page
Home » openjdk-7 » com.sun.org.apache.xml.internal » serializer » [javadoc | source]