Save This Page
Home » openjdk-7 » com.sun.xml.internal » fastinfoset » stax » [javadoc | source]
    1   /*
    2    * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    *
   25    * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
   26    */
   27   
   28   /*
   29    * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
   30    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   31    *
   32    * This code is free software; you can redistribute it and/or modify it
   33    * under the terms of the GNU General Public License version 2 only, as
   34    * published by the Free Software Foundation.  Sun designates this
   35    * particular file as subject to the "Classpath" exception as provided
   36    * by Sun in the LICENSE file that accompanied this code.
   37    *
   38    * This code is distributed in the hope that it will be useful, but WITHOUT
   39    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   40    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41    * version 2 for more details (a copy is included in the LICENSE file that
   42    * accompanied this code).
   43    *
   44    * You should have received a copy of the GNU General Public License version
   45    * 2 along with this work; if not, write to the Free Software Foundation,
   46    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   47    *
   48    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   49    * CA 95054 USA or visit www.sun.com if you need additional information or
   50    * have any questions.
   51    *
   52    * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
   53    *
   54    */
   55   
   56   package com.sun.xml.internal.fastinfoset.stax;
   57   
   58   import com.sun.xml.internal.fastinfoset.Encoder;
   59   import com.sun.xml.internal.fastinfoset.EncodingConstants;
   60   import java.io.IOException;
   61   import java.io.OutputStream;
   62   import java.util.EmptyStackException;
   63   import java.util.Enumeration;
   64   import java.util.Iterator;
   65   import javax.xml.namespace.NamespaceContext;
   66   import javax.xml.stream.XMLStreamException;
   67   import javax.xml.stream.XMLStreamWriter;
   68   import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
   69   import org.xml.sax.helpers.NamespaceSupport;
   70   import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
   71   
   72   /**
   73    * The Fast Infoset StAX serializer.
   74    * <p>
   75    * Instantiate this serializer to serialize a fast infoset document in accordance
   76    * with the StAX API.
   77    *
   78    * <p>
   79    * More than one fast infoset document may be encoded to the
   80    * {@link java.io.OutputStream}.
   81    */
   82   public class StAXDocumentSerializer extends Encoder implements XMLStreamWriter {
   83       protected StAXManager _manager;
   84   
   85       protected String _encoding;
   86       /**
   87        * Local name of current element.
   88        */
   89       protected String _currentLocalName;
   90   
   91       /**
   92        * Namespace of current element.
   93        */
   94       protected String _currentUri;
   95   
   96       /**
   97        * Prefix of current element.
   98        */
   99       protected String _currentPrefix;
  100   
  101      /**
  102        * This flag indicates when there is a pending start element event.
  103        */
  104       protected boolean _inStartElement = false;
  105   
  106       /**
  107        * This flag indicates if the current element is empty.
  108        */
  109       protected boolean _isEmptyElement = false;
  110   
  111       /**
  112        * List of attributes qnames and values defined in the current element.
  113        */
  114       protected String[] _attributesArray = new String[4 * 16];
  115       protected int _attributesArrayIndex = 0;
  116   
  117       /**
  118        * Mapping between uris and prefixes.
  119        */
  120       protected NamespaceSupport _nsSupport = new NamespaceSupport();
  121   
  122       protected boolean[] _nsSupportContextStack = new boolean[32];
  123       protected int _stackCount = -1;
  124   
  125       protected NamespaceContext _nsContext = new NamespaceContextImpl();
  126   
  127       /**
  128        * List of namespaces defined in the current element.
  129        */
  130       protected String[] _namespacesArray = new String[2 * 8];
  131       protected int _namespacesArrayIndex = 0;
  132   
  133       public StAXDocumentSerializer() {
  134           super(true);
  135       }
  136   
  137       public StAXDocumentSerializer(OutputStream outputStream) {
  138           super(true);
  139           setOutputStream(outputStream);
  140       }
  141   
  142       public StAXDocumentSerializer(OutputStream outputStream, StAXManager manager) {
  143           super(true);
  144           setOutputStream(outputStream);
  145           _manager = manager;
  146       }
  147   
  148       public void reset() {
  149           super.reset();
  150   
  151           _attributesArrayIndex = 0;
  152           _namespacesArrayIndex = 0;
  153           _nsSupport.reset();
  154           _stackCount = -1;
  155   
  156           _currentUri = _currentPrefix = null;
  157           _currentLocalName = null;
  158   
  159           _inStartElement = _isEmptyElement = false;
  160       }
  161   
  162       // -- XMLStreamWriter Interface -------------------------------------------
  163   
  164       public void writeStartDocument() throws XMLStreamException {
  165           writeStartDocument("finf", "1.0");
  166       }
  167   
  168       public void writeStartDocument(String version) throws XMLStreamException {
  169           writeStartDocument("finf", version);
  170       }
  171   
  172       public void writeStartDocument(String encoding, String version)
  173           throws XMLStreamException
  174       {
  175           reset();
  176   
  177           try {
  178               encodeHeader(false);
  179               encodeInitialVocabulary();
  180           } catch (IOException e) {
  181               throw new XMLStreamException(e);
  182           }
  183       }
  184   
  185       public void writeEndDocument() throws XMLStreamException {
  186           // Need to flush a pending empty element?
  187           if (_inStartElement) {
  188   //            encodeTerminationAndCurrentElement();
  189           }
  190   
  191           try {
  192               // TODO
  193               // Use nsSupport to terminate all elements not terminated
  194               // by writeEndElement
  195   
  196   
  197               encodeDocumentTermination();
  198           }
  199           catch (IOException e) {
  200               throw new XMLStreamException(e);
  201           }
  202       }
  203   
  204       public void close() throws XMLStreamException {
  205           reset();
  206       }
  207   
  208       public void flush() throws XMLStreamException {
  209           try {
  210               _s.flush();
  211           }
  212           catch (IOException e) {
  213               throw new XMLStreamException(e);
  214           }
  215       }
  216   
  217       public void writeStartElement(String localName)
  218           throws XMLStreamException
  219       {
  220           // TODO is it necessary for FI to obtain the default namespace in scope?
  221           writeStartElement("", localName, "");
  222       }
  223   
  224       public void writeStartElement(String namespaceURI, String localName)
  225           throws XMLStreamException
  226       {
  227           writeStartElement(getPrefix(namespaceURI), localName, namespaceURI);
  228       }
  229   
  230       public void writeStartElement(String prefix, String localName,
  231           String namespaceURI) throws XMLStreamException
  232       {
  233           encodeTerminationAndCurrentElement(false);
  234   
  235           _inStartElement = true;
  236           _isEmptyElement = false;
  237   
  238           _currentLocalName = localName;
  239           _currentPrefix = prefix;
  240           _currentUri = namespaceURI;
  241   
  242           _stackCount++;
  243           if (_stackCount == _nsSupportContextStack.length) {
  244               boolean[] nsSupportContextStack = new boolean[_stackCount * 2];
  245               System.arraycopy(_nsSupportContextStack, 0, nsSupportContextStack, 0, _nsSupportContextStack.length);
  246               _nsSupportContextStack = nsSupportContextStack;
  247           }
  248   
  249           _nsSupportContextStack[_stackCount] = false;
  250           // _nsSupport.pushContext();
  251       }
  252   
  253       public void writeEmptyElement(String localName)
  254           throws XMLStreamException
  255       {
  256           writeEmptyElement("", localName, "");
  257       }
  258   
  259       public void writeEmptyElement(String namespaceURI, String localName)
  260           throws XMLStreamException
  261       {
  262           writeEmptyElement(getPrefix(namespaceURI), localName, namespaceURI);
  263       }
  264   
  265       public void writeEmptyElement(String prefix, String localName,
  266           String namespaceURI) throws XMLStreamException
  267       {
  268           encodeTerminationAndCurrentElement(false);
  269   
  270           _isEmptyElement = _inStartElement = true;
  271   
  272           _currentLocalName = localName;
  273           _currentPrefix = prefix;
  274           _currentUri = namespaceURI;
  275   
  276           _stackCount++;
  277           if (_stackCount == _nsSupportContextStack.length) {
  278               boolean[] nsSupportContextStack = new boolean[_stackCount * 2];
  279               System.arraycopy(_nsSupportContextStack, 0, nsSupportContextStack, 0, _nsSupportContextStack.length);
  280               _nsSupportContextStack = nsSupportContextStack;
  281           }
  282   
  283           _nsSupportContextStack[_stackCount] = false;
  284           //_nsSupport.pushContext();
  285       }
  286   
  287       public void writeEndElement() throws XMLStreamException {
  288           if (_inStartElement) {
  289               encodeTerminationAndCurrentElement(false);
  290           }
  291   
  292           try {
  293               encodeElementTermination();
  294               if (_nsSupportContextStack[_stackCount--] == true) {
  295                   _nsSupport.popContext();
  296               }
  297           }
  298           catch (IOException e) {
  299               throw new XMLStreamException(e);
  300           }
  301           catch (EmptyStackException e) {
  302               throw new XMLStreamException(e);
  303           }
  304       }
  305   
  306   
  307       public void writeAttribute(String localName, String value)
  308           throws XMLStreamException
  309       {
  310           writeAttribute("", "", localName, value);
  311       }
  312   
  313       public void writeAttribute(String namespaceURI, String localName,
  314           String value) throws XMLStreamException
  315       {
  316           String prefix = "";
  317   
  318           // Find prefix for attribute, ignoring default namespace
  319           if (namespaceURI.length() > 0) {
  320               prefix = _nsSupport.getPrefix(namespaceURI);
  321   
  322               // Undeclared prefix or ignorable default ns?
  323               if (prefix == null || prefix.length() == 0) {
  324                   // Workaround for BUG in SAX NamespaceSupport helper
  325                   // which incorrectly defines namespace declaration URI
  326                   if (namespaceURI == EncodingConstants.XMLNS_NAMESPACE_NAME ||
  327                           namespaceURI.equals(EncodingConstants.XMLNS_NAMESPACE_NAME)) {
  328                       // TODO
  329                       // Need to check carefully the rule for the writing of
  330                       // namespaces in StAX. Is it safe to ignore such
  331                       // attributes, as declarations will be made using the
  332                       // writeNamespace method
  333                       return;
  334                   }
  335                   throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.URIUnbound", new Object[]{namespaceURI}));
  336               }
  337           }
  338           writeAttribute(prefix, namespaceURI, localName, value);
  339       }
  340   
  341       public void writeAttribute(String prefix, String namespaceURI,
  342           String localName, String value) throws XMLStreamException
  343       {
  344           if (!_inStartElement) {
  345               throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.attributeWritingNotAllowed"));
  346           }
  347   
  348           // TODO
  349           // Need to check carefully the rule for the writing of
  350           // namespaces in StAX. Is it safe to ignore such
  351           // attributes, as declarations will be made using the
  352           // writeNamespace method
  353           if (namespaceURI == EncodingConstants.XMLNS_NAMESPACE_NAME ||
  354                   namespaceURI.equals(EncodingConstants.XMLNS_NAMESPACE_NAME)) {
  355               return;
  356           }
  357   
  358           if (_attributesArrayIndex == _attributesArray.length) {
  359               final String[] attributesArray = new String[_attributesArrayIndex * 2];
  360               System.arraycopy(_attributesArray, 0, attributesArray, 0, _attributesArrayIndex);
  361               _attributesArray = attributesArray;
  362           }
  363   
  364           _attributesArray[_attributesArrayIndex++] = namespaceURI;
  365           _attributesArray[_attributesArrayIndex++] = prefix;
  366           _attributesArray[_attributesArrayIndex++] = localName;
  367           _attributesArray[_attributesArrayIndex++] = value;
  368       }
  369   
  370       public void writeNamespace(String prefix, String namespaceURI)
  371           throws XMLStreamException
  372       {
  373           if (prefix == null || prefix.length() == 0 || prefix.equals(EncodingConstants.XMLNS_NAMESPACE_PREFIX)) {
  374               writeDefaultNamespace(namespaceURI);
  375           }
  376           else {
  377               if (!_inStartElement) {
  378                   throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.attributeWritingNotAllowed"));
  379               }
  380   
  381               if (_namespacesArrayIndex == _namespacesArray.length) {
  382                   final String[] namespacesArray = new String[_namespacesArrayIndex * 2];
  383                   System.arraycopy(_namespacesArray, 0, namespacesArray, 0, _namespacesArrayIndex);
  384                   _namespacesArray = namespacesArray;
  385               }
  386   
  387               _namespacesArray[_namespacesArrayIndex++] = prefix;
  388               _namespacesArray[_namespacesArrayIndex++] = namespaceURI;
  389           }
  390       }
  391   
  392       public void writeDefaultNamespace(String namespaceURI)
  393           throws XMLStreamException
  394       {
  395           if (!_inStartElement) {
  396               throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.attributeWritingNotAllowed"));
  397           }
  398   
  399           if (_namespacesArrayIndex == _namespacesArray.length) {
  400               final String[] namespacesArray = new String[_namespacesArrayIndex * 2];
  401               System.arraycopy(_namespacesArray, 0, namespacesArray, 0, _namespacesArrayIndex);
  402               _namespacesArray = namespacesArray;
  403           }
  404   
  405           _namespacesArray[_namespacesArrayIndex++] = "";
  406           _namespacesArray[_namespacesArrayIndex++] = namespaceURI;
  407       }
  408   
  409       public void writeComment(String data) throws XMLStreamException {
  410           try {
  411               if (getIgnoreComments()) return;
  412   
  413               encodeTerminationAndCurrentElement(true);
  414   
  415               // TODO: avoid array copy here
  416               encodeComment(data.toCharArray(), 0, data.length());
  417           }
  418           catch (IOException e) {
  419               throw new XMLStreamException(e);
  420           }
  421       }
  422   
  423       public void writeProcessingInstruction(String target)
  424           throws XMLStreamException
  425       {
  426           writeProcessingInstruction(target, "");
  427       }
  428   
  429       public void writeProcessingInstruction(String target, String data)
  430           throws XMLStreamException
  431       {
  432           try {
  433               if (getIgnoreProcesingInstructions()) return;
  434   
  435               encodeTerminationAndCurrentElement(true);
  436   
  437               encodeProcessingInstruction(target, data);
  438           }
  439           catch (IOException e) {
  440               throw new XMLStreamException(e);
  441           }
  442       }
  443   
  444       public void writeCData(String data) throws XMLStreamException {
  445           throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.notImplemented"));
  446      }
  447   
  448       public void writeDTD(String dtd) throws XMLStreamException {
  449           throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.notImplemented"));
  450       }
  451   
  452       public void writeEntityRef(String name) throws XMLStreamException {
  453           throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.notImplemented"));
  454       }
  455   
  456       public void writeCharacters(String text) throws XMLStreamException {
  457            try {
  458               final int length = text.length();
  459               if (length == 0) {
  460                   return;
  461               } else if (length < _charBuffer.length) {
  462                   if (getIgnoreWhiteSpaceTextContent() &&
  463                           isWhiteSpace(text)) return;
  464   
  465                   // Warning: this method must be called before any state
  466                   // is modified, such as the _charBuffer contents,
  467                   // so the characters of text cannot be copied to _charBuffer
  468                   // before this call
  469                   encodeTerminationAndCurrentElement(true);
  470   
  471                   text.getChars(0, length, _charBuffer, 0);
  472                   encodeCharacters(_charBuffer, 0, length);
  473               } else {
  474                   final char ch[] = text.toCharArray();
  475                   if (getIgnoreWhiteSpaceTextContent() &&
  476                           isWhiteSpace(ch, 0, length)) return;
  477   
  478                   encodeTerminationAndCurrentElement(true);
  479   
  480                   encodeCharactersNoClone(ch, 0, length);
  481               }
  482           }
  483           catch (IOException e) {
  484               throw new XMLStreamException(e);
  485           }
  486       }
  487   
  488       public void writeCharacters(char[] text, int start, int len)
  489           throws XMLStreamException
  490       {
  491            try {
  492               if (len <= 0) {
  493                   return;
  494               }
  495   
  496               if (getIgnoreWhiteSpaceTextContent() &&
  497                       isWhiteSpace(text, start, len)) return;
  498   
  499               encodeTerminationAndCurrentElement(true);
  500   
  501               encodeCharacters(text, start, len);
  502           }
  503           catch (IOException e) {
  504               throw new XMLStreamException(e);
  505           }
  506       }
  507   
  508       public String getPrefix(String uri) throws XMLStreamException {
  509           return _nsSupport.getPrefix(uri);
  510       }
  511   
  512       public void setPrefix(String prefix, String uri)
  513           throws XMLStreamException
  514       {
  515           if (_stackCount > -1 && _nsSupportContextStack[_stackCount] == false) {
  516               _nsSupportContextStack[_stackCount] = true;
  517               _nsSupport.pushContext();
  518           }
  519   
  520           _nsSupport.declarePrefix(prefix, uri);
  521       }
  522   
  523       public void setDefaultNamespace(String uri) throws XMLStreamException {
  524           setPrefix("", uri);
  525       }
  526   
  527       /**
  528        * Sets the current namespace context for prefix and uri bindings.
  529        * This context becomes the root namespace context for writing and
  530        * will replace the current root namespace context.  Subsequent calls
  531        * to setPrefix and setDefaultNamespace will bind namespaces using
  532        * the context passed to the method as the root context for resolving
  533        * namespaces.  This method may only be called once at the start of
  534        * the document.  It does not cause the namespaces to be declared.
  535        * If a namespace URI to prefix mapping is found in the namespace
  536        * context it is treated as declared and the prefix may be used
  537        * by the StreamWriter.
  538        * @param context the namespace context to use for this writer, may not be null
  539        * @throws XMLStreamException
  540        */
  541       public void setNamespaceContext(NamespaceContext context)
  542           throws XMLStreamException
  543       {
  544           throw new UnsupportedOperationException("setNamespaceContext");
  545       }
  546   
  547       public NamespaceContext getNamespaceContext() {
  548           return _nsContext;
  549       }
  550   
  551       public Object getProperty(java.lang.String name)
  552           throws IllegalArgumentException
  553       {
  554           if (_manager != null) {
  555               return _manager.getProperty(name);
  556           }
  557           return null;
  558       }
  559   
  560       public void setManager(StAXManager manager) {
  561           _manager = manager;
  562       }
  563   
  564       public void setEncoding(String encoding) {
  565           _encoding = encoding;
  566       }
  567   
  568       protected class NamespaceContextImpl implements NamespaceContext {
  569           public final String getNamespaceURI(String prefix) {
  570               return _nsSupport.getURI(prefix);
  571           }
  572   
  573           public final String getPrefix(String namespaceURI) {
  574               return _nsSupport.getPrefix(namespaceURI);
  575           }
  576   
  577           public final Iterator getPrefixes(String namespaceURI) {
  578               final Enumeration e = _nsSupport.getPrefixes(namespaceURI);
  579   
  580               return new Iterator() {
  581                       public boolean hasNext() {
  582                           return e.hasMoreElements();
  583                       }
  584   
  585                       public Object next() {
  586                           return e.nextElement();
  587                       }
  588   
  589                       public void remove() {
  590                           throw new UnsupportedOperationException();
  591                       }
  592                   };
  593           }
  594       }
  595   
  596       public void writeOctets(byte[] b, int start, int len)
  597           throws XMLStreamException
  598       {
  599            try {
  600               if (len == 0) {
  601                   return;
  602               }
  603   
  604               encodeTerminationAndCurrentElement(true);
  605   
  606               encodeCIIOctetAlgorithmData(EncodingAlgorithmIndexes.BASE64, b, start, len);
  607           }
  608           catch (IOException e) {
  609               throw new XMLStreamException(e);
  610           }
  611       }
  612   
  613       protected void encodeTerminationAndCurrentElement(boolean terminateAfter) throws XMLStreamException {
  614           try {
  615               encodeTermination();
  616   
  617               if (_inStartElement) {
  618   
  619                   _b = EncodingConstants.ELEMENT;
  620                   if (_attributesArrayIndex > 0) {
  621                       _b |= EncodingConstants.ELEMENT_ATTRIBUTE_FLAG;
  622                   }
  623   
  624                   // Encode namespace decls associated with this element
  625                   if (_namespacesArrayIndex > 0) {
  626                       write(_b | EncodingConstants.ELEMENT_NAMESPACES_FLAG);
  627                       for (int i = 0; i < _namespacesArrayIndex;) {
  628                           encodeNamespaceAttribute(_namespacesArray[i++], _namespacesArray[i++]);
  629                       }
  630                       _namespacesArrayIndex = 0;
  631   
  632                       write(EncodingConstants.TERMINATOR);
  633   
  634                       _b = 0;
  635                   }
  636   
  637                   // Encode element and its attributes
  638                   encodeElementQualifiedNameOnThirdBit(_currentUri, _currentPrefix, _currentLocalName);
  639   
  640                   for (int i = 0; i < _attributesArrayIndex;) {
  641                       encodeAttributeQualifiedNameOnSecondBit(
  642                               _attributesArray[i++], _attributesArray[i++], _attributesArray[i++]);
  643   
  644                       final String value = _attributesArray[i];
  645                       _attributesArray[i++] = null;
  646                       final boolean addToTable = (value.length() < attributeValueSizeConstraint) ? true : false;
  647                       encodeNonIdentifyingStringOnFirstBit(value, _v.attributeValue, addToTable);
  648   
  649                       _b = EncodingConstants.TERMINATOR;
  650                       _terminate = true;
  651                   }
  652                   _attributesArrayIndex = 0;
  653                   _inStartElement = false;
  654   
  655                   if (_isEmptyElement) {
  656                       encodeElementTermination();
  657                       if (_nsSupportContextStack[_stackCount--] == true) {
  658                           _nsSupport.popContext();
  659                       }
  660   
  661                       _isEmptyElement = false;
  662                   }
  663   
  664                   if (terminateAfter) {
  665                       encodeTermination();
  666                   }
  667               }
  668           } catch (IOException e) {
  669               throw new XMLStreamException(e);
  670           }
  671       }
  672   }

Save This Page
Home » openjdk-7 » com.sun.xml.internal » fastinfoset » stax » [javadoc | source]