src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBuffer.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 515
6cd506508147
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2005, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.stream.buffer;
    28 import com.sun.xml.internal.stream.buffer.sax.SAXBufferProcessor;
    29 import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferProcessor;
    30 import com.sun.xml.internal.stream.buffer.stax.StreamWriterBufferProcessor;
    31 import java.io.IOException;
    32 import java.io.InputStream;
    33 import java.util.Collections;
    34 import java.util.Map;
    35 import javax.xml.stream.XMLStreamException;
    36 import javax.xml.stream.XMLStreamReader;
    37 import javax.xml.stream.XMLStreamWriter;
    38 import javax.xml.transform.TransformerFactory;
    39 import javax.xml.transform.Transformer;
    40 import javax.xml.transform.TransformerException;
    41 import javax.xml.transform.dom.DOMResult;
    43 import org.xml.sax.ContentHandler;
    44 import org.xml.sax.DTDHandler;
    45 import org.xml.sax.ErrorHandler;
    46 import org.xml.sax.SAXException;
    47 import org.xml.sax.XMLReader;
    48 import org.xml.sax.ext.LexicalHandler;
    49 import org.w3c.dom.Node;
    51 /**
    52  * An immutable stream-based buffer of an XML infoset.
    53  *
    54  * <p>
    55  * A XMLStreamBuffer is an abstract class. It is immutable with
    56  * respect to the methods on the class, which are non-modifying in terms
    57  * of state.
    58  *
    59  * <p>
    60  * A XMLStreamBuffer can be processed using specific SAX and StAX-based
    61  * processors. Utility methods on XMLStreamBuffer are provided for
    62  * such functionality that utilize SAX and StAX-based processors.
    63  * The same instance of a XMLStreamBuffer may be processed
    64  * multiple times and concurrently by more than one processor.
    65  *
    66  * <p>
    67  * There are two concrete implementations of XMLStreamBuffer.
    68  * The first, {@link MutableXMLStreamBuffer}, can be instantiated for the creation
    69  * of a buffer using SAX and StAX-based creators, and from which may be
    70  * processed as an XMLStreamBuffer. The second,
    71  * {@link XMLStreamBufferMark}, can be instantiated to mark into an existing
    72  * buffer that is being created or processed. This allows a subtree of
    73  * {@link XMLStreamBuffer} to be treated as its own {@link XMLStreamBuffer}.
    74  *
    75  * <p>
    76  * A XMLStreamBuffer can represent a complete XML infoset or a subtree
    77  * of an XML infoset. It is also capable of representing a "forest",
    78  * where the buffer represents multiple adjacent XML elements, although
    79  * in this mode there are restrictions about how you can consume such
    80  * forest, because not all XML APIs handle forests very well.
    81  */
    82 public abstract class XMLStreamBuffer {
    84     /**
    85      * In scope namespaces on a fragment
    86      */
    87     protected Map<String,String> _inscopeNamespaces = Collections.emptyMap();
    89     /**
    90      * True if the buffer was created from a parser that interns Strings
    91      * as specified by the SAX interning features
    92      */
    93     protected boolean _hasInternedStrings;
    95     /**
    96      * Fragmented array to hold structural information
    97      */
    98     protected FragmentedArray<byte[]> _structure;
    99     protected int _structurePtr;
   101     /**
   102      * Fragmented array to hold structural information as strings
   103      */
   104     protected FragmentedArray<String[]> _structureStrings;
   105     protected int _structureStringsPtr;
   107     /**
   108      * Fragmented array to hold content information in a shared char[]
   109      */
   110     protected FragmentedArray<char[]> _contentCharactersBuffer;
   111     protected int _contentCharactersBufferPtr;
   113     /**
   114      * Fragmented array to hold content information as objects
   115      */
   116     protected FragmentedArray<Object[]> _contentObjects;
   117     protected int _contentObjectsPtr;
   119     /**
   120      * Number of trees in this stream buffer.
   121      *
   122      * <p>
   123      * 1 if there's only one, which is the normal case. When the buffer
   124      * holds a forest, this value is greater than 1. If the buffer is empty, then 0.
   125      *
   126      * <p>
   127      * Notice that we cannot infer this value by looking at the {@link FragmentedArray}s,
   128      * because this {@link XMLStreamBuffer} maybe a view of a portion of another bigger
   129      * {@link XMLStreamBuffer}.
   130      */
   131     protected int treeCount;
   133     /**
   134      * The system identifier associated with the buffer
   135      */
   136     protected String systemId;
   138     /**
   139      * Is the buffer created by creator.
   140      *
   141      * @return
   142      * <code>true</code> if the buffer has been created.
   143      */
   144     public final boolean isCreated() {
   145         return _structure.getArray()[0] != AbstractCreatorProcessor.T_END;
   146     }
   148     /**
   149      * Is the buffer a representation of a fragment of an XML infoset.
   150      *
   151      * @return
   152      * <code>true</code> if the buffer is a representation of a fragment
   153      * of an XML infoset.
   154      */
   155     public final boolean isFragment() {
   156         return (isCreated() && (_structure.getArray()[_structurePtr] & AbstractCreatorProcessor.TYPE_MASK)
   157                 != AbstractCreatorProcessor.T_DOCUMENT);
   158     }
   160     /**
   161      * Is the buffer a representation of a fragment of an XML infoset
   162      * that is an element (and its contents).
   163      *
   164      * @return
   165      * <code>true</code> if the buffer a representation
   166      * of a fragment of an XML infoset that is an element (and its contents).
   167      */
   168     public final boolean isElementFragment() {
   169         return (isCreated() && (_structure.getArray()[_structurePtr] & AbstractCreatorProcessor.TYPE_MASK)
   170                 == AbstractCreatorProcessor.T_ELEMENT);
   171     }
   173     /**
   174      * Returns ture if this buffer represents a forest, which is
   175      * are more than one adjacent XML elements.
   176      */
   177     public final boolean isForest() {
   178         return isCreated() && treeCount>1;
   179     }
   181     /**
   182      * Get the system identifier associated with the buffer.
   183      * @return The system identifier.
   184      */
   185     public final String getSystemId() {
   186         return systemId;
   187     }
   189     /**
   190      * Get the in-scope namespaces.
   191      *
   192      * <p>
   193      *
   194      * The in-scope namespaces will be empty if the buffer is not a
   195      * fragment ({@link #isFragment} returns <code>false</code>).
   196      *
   197      * The in-scope namespace will correspond to the in-scope namespaces of the
   198      * fragment if the buffer is a fragment ({@link #isFragment}
   199      * returns <code>false</code>). The in-scope namespaces will include any
   200      * namespace delcarations on an element if the fragment correspond to that
   201      * of an element ({@link #isElementFragment} returns <code>false</code>).
   202      *
   203      * @return
   204      *      The in-scope namespaces of the XMLStreamBuffer.
   205      *      Prefix to namespace URI.
   206      */
   207     public final Map<String,String> getInscopeNamespaces() {
   208         return _inscopeNamespaces;
   209     }
   211     /**
   212      * Has the buffer been created using Strings that have been interned
   213      * for certain properties of information items. The Strings that are interned
   214      * are those that correspond to Strings that are specified by the SAX API
   215      * "string-interning" property
   216      * (see <a href="http://java.sun.com/j2se/1.5.0/docs/api/org/xml/sax/package-summary.html#package_description">here</a>).
   217      *
   218      * <p>
   219      * An buffer may have been created, for example, from an XML document parsed
   220      * using the Xerces SAX parser. The Xerces SAX parser will have interned certain Strings
   221      * according to the SAX string interning property.
   222      * This method enables processors to avoid the duplication of
   223      * String interning if such a feature is required by a procesing application and the
   224      * buffer being processed was created using Strings that have been interned.
   225      *
   226      * @return
   227      * <code>true</code> if the buffer has been created using Strings that
   228      * have been interned.
   229      */
   230     public final boolean hasInternedStrings() {
   231         return _hasInternedStrings;
   232     }
   234     /**
   235      * Read the contents of the buffer as a {@link XMLStreamReader}.
   236      *
   237      * @return
   238      * A an instance of a {@link StreamReaderBufferProcessor}. Always non-null.
   239      */
   240     public final StreamReaderBufferProcessor readAsXMLStreamReader() throws XMLStreamException {
   241         return new StreamReaderBufferProcessor(this);
   242     }
   244     /**
   245      * Write the contents of the buffer to an XMLStreamWriter.
   246      *
   247      * <p>
   248      * The XMLStreamBuffer will be written out to the XMLStreamWriter using
   249      * an instance of {@link StreamWriterBufferProcessor}.
   250      *
   251      * @param writer
   252      *      A XMLStreamWriter to write to.
   253      * @param writeAsFragment
   254      *      If true, {@link XMLStreamWriter} will not receive {@link XMLStreamWriter#writeStartDocument()}
   255      *      nor {@link XMLStreamWriter#writeEndDocument()}. This is desirable behavior when
   256      *      you are writing the contents of a buffer into a bigger document.
   257      */
   258     public final void writeToXMLStreamWriter(XMLStreamWriter writer, boolean writeAsFragment) throws XMLStreamException {
   259         StreamWriterBufferProcessor p = new StreamWriterBufferProcessor(this,writeAsFragment);
   260         p.process(writer);
   261     }
   263     /**
   264      * @deprecated
   265      *      Use {@link #writeToXMLStreamWriter(XMLStreamWriter, boolean)}
   266      */
   267     public final void writeToXMLStreamWriter(XMLStreamWriter writer) throws XMLStreamException {
   268         writeToXMLStreamWriter(writer, this.isFragment());
   269     }
   271     /**
   272      * Reads the contents of the buffer from a {@link XMLReader}.
   273      *
   274      * @return
   275      * A an instance of a {@link SAXBufferProcessor}.
   276      * @deprecated
   277      *      Use {@link #readAsXMLReader(boolean)}
   278      */
   279     public final SAXBufferProcessor readAsXMLReader() {
   280         return new SAXBufferProcessor(this,isFragment());
   281     }
   283     /**
   284      * Reads the contents of the buffer from a {@link XMLReader}.
   285      *
   286      * @param produceFragmentEvent
   287      *      True to generate fragment SAX events without start/endDocument.
   288      *      False to generate a full document SAX events.
   289      * @return
   290      *      A an instance of a {@link SAXBufferProcessor}.
   291      */
   292     public final SAXBufferProcessor readAsXMLReader(boolean produceFragmentEvent) {
   293         return new SAXBufferProcessor(this,produceFragmentEvent);
   294     }
   296     /**
   297      * Write the contents of the buffer to a {@link ContentHandler}.
   298      *
   299      * <p>
   300      * If the <code>handler</code> is also an instance of other SAX-based
   301      * handlers, such as {@link LexicalHandler}, than corresponding SAX events
   302      * will be reported to those handlers.
   303      *
   304      * @param handler
   305      *      The ContentHandler to receive SAX events.
   306      * @param produceFragmentEvent
   307      *      True to generate fragment SAX events without start/endDocument.
   308      *      False to generate a full document SAX events.
   309      *
   310      * @throws SAXException
   311      *      if a parsing fails, or if {@link ContentHandler} throws a {@link SAXException}.
   312      */
   313     public final void writeTo(ContentHandler handler, boolean produceFragmentEvent) throws SAXException {
   314         SAXBufferProcessor p = readAsXMLReader(produceFragmentEvent);
   315         p.setContentHandler(handler);
   316         if (p instanceof LexicalHandler) {
   317             p.setLexicalHandler((LexicalHandler)handler);
   318         }
   319         if (p instanceof DTDHandler) {
   320             p.setDTDHandler((DTDHandler)handler);
   321         }
   322         if (p instanceof ErrorHandler) {
   323             p.setErrorHandler((ErrorHandler)handler);
   324         }
   325         p.process();
   326     }
   328     /**
   329      * @deprecated
   330      *      Use {@link #writeTo(ContentHandler,boolean)}
   331      */
   332     public final void writeTo(ContentHandler handler) throws SAXException {
   333         writeTo(handler,isFragment());
   334     }
   336     /**
   337      * Write the contents of the buffer to a {@link ContentHandler} with errors
   338      * report to a {@link ErrorHandler}.
   339      *
   340      * <p>
   341      * If the <code>handler</code> is also an instance of other SAX-based
   342      * handlers, such as {@link LexicalHandler}, than corresponding SAX events
   343      * will be reported to those handlers.
   344      *
   345      * @param handler
   346      * The ContentHandler to receive SAX events.
   347      * @param errorHandler
   348      * The ErrorHandler to receive error events.
   349      *
   350      * @throws SAXException
   351      *      if a parsing fails and {@link ErrorHandler} throws a {@link SAXException},
   352      *      or if {@link ContentHandler} throws a {@link SAXException}.
   353      */
   354     public final void writeTo(ContentHandler handler, ErrorHandler errorHandler, boolean produceFragmentEvent) throws SAXException {
   355         SAXBufferProcessor p = readAsXMLReader(produceFragmentEvent);
   356         p.setContentHandler(handler);
   357         if (p instanceof LexicalHandler) {
   358             p.setLexicalHandler((LexicalHandler)handler);
   359         }
   360         if (p instanceof DTDHandler) {
   361             p.setDTDHandler((DTDHandler)handler);
   362         }
   364         p.setErrorHandler(errorHandler);
   366         p.process();
   367     }
   369     public final void writeTo(ContentHandler handler, ErrorHandler errorHandler) throws SAXException {
   370         writeTo(handler, errorHandler, isFragment());
   371     }
   373     private static final ContextClassloaderLocal<TransformerFactory> trnsformerFactory = new ContextClassloaderLocal<TransformerFactory>() {
   374         @Override
   375         protected TransformerFactory initialValue() throws Exception {
   376             return TransformerFactory.newInstance();
   377         }
   378     };
   380     /**
   381      * Writes out the contents of this buffer as DOM node and append that to the given node.
   382      *
   383      * Faster implementation would be desirable.
   384      *
   385      * @return
   386      *      The newly added child node.
   387      */
   388     public final Node writeTo(Node n) throws XMLStreamBufferException {
   389         try {
   390             Transformer t = trnsformerFactory.get().newTransformer();
   391             t.transform(new XMLStreamBufferSource(this), new DOMResult(n));
   392             return n.getLastChild();
   393         } catch (TransformerException e) {
   394             throw new XMLStreamBufferException(e);
   395         }
   396     }
   398     /**
   399      * Create a new buffer from a XMLStreamReader.
   400      *
   401      * @param reader
   402      * A XMLStreamReader to read from to create.
   403      * @return XMLStreamBuffer the created buffer
   404      * @see MutableXMLStreamBuffer#createFromXMLStreamReader(XMLStreamReader)
   405      */
   406     public static XMLStreamBuffer createNewBufferFromXMLStreamReader(XMLStreamReader reader)
   407             throws XMLStreamException {
   408         MutableXMLStreamBuffer b = new MutableXMLStreamBuffer();
   409         b.createFromXMLStreamReader(reader);
   410         return b;
   411     }
   413     /**
   414      * Create a new buffer from a {@link XMLReader} and {@link InputStream}.
   415      *
   416      * @param reader
   417      * The {@link XMLReader} to use for parsing.
   418      * @param in
   419      * The {@link InputStream} to be parsed.
   420      * @return XMLStreamBuffer the created buffer
   421      * @see MutableXMLStreamBuffer#createFromXMLReader(XMLReader, InputStream)
   422      */
   423     public static XMLStreamBuffer createNewBufferFromXMLReader(XMLReader reader, InputStream in) throws SAXException, IOException {
   424         MutableXMLStreamBuffer b = new MutableXMLStreamBuffer();
   425         b.createFromXMLReader(reader, in);
   426         return b;
   427     }
   429     /**
   430      * Create a new buffer from a {@link XMLReader} and {@link InputStream}.
   431      *
   432      * @param reader
   433      * The {@link XMLReader} to use for parsing.
   434      * @param in
   435      * The {@link InputStream} to be parsed.
   436      * @param systemId
   437      * The system ID of the input stream.
   438      * @return XMLStreamBuffer the created buffer
   439      * @see MutableXMLStreamBuffer#createFromXMLReader(XMLReader, InputStream, String)
   440      */
   441     public static XMLStreamBuffer createNewBufferFromXMLReader(XMLReader reader, InputStream in,
   442                                                                String systemId) throws SAXException, IOException {
   443         MutableXMLStreamBuffer b = new MutableXMLStreamBuffer();
   444         b.createFromXMLReader(reader, in, systemId);
   445         return b;
   446     }
   448     protected final FragmentedArray<byte[]> getStructure() {
   449         return _structure;
   450     }
   452     protected final int getStructurePtr() {
   453         return _structurePtr;
   454     }
   456     protected final FragmentedArray<String[]> getStructureStrings() {
   457         return _structureStrings;
   458     }
   460     protected final int getStructureStringsPtr() {
   461         return _structureStringsPtr;
   462     }
   464     protected final FragmentedArray<char[]> getContentCharactersBuffer() {
   465         return _contentCharactersBuffer;
   466     }
   468     protected final int getContentCharactersBufferPtr() {
   469         return _contentCharactersBufferPtr;
   470     }
   472     protected final FragmentedArray<Object[]> getContentObjects() {
   473         return _contentObjects;
   474     }
   476     protected final int getContentObjectsPtr() {
   477         return _contentObjectsPtr;
   478     }
   479 }

mercurial