1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBuffer.java Tue Mar 06 16:09:35 2012 -0800 1.3 @@ -0,0 +1,474 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.stream.buffer; 1.30 + 1.31 +import com.sun.xml.internal.stream.buffer.sax.SAXBufferProcessor; 1.32 +import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferProcessor; 1.33 +import com.sun.xml.internal.stream.buffer.stax.StreamWriterBufferProcessor; 1.34 +import java.io.IOException; 1.35 +import java.io.InputStream; 1.36 +import java.util.Collections; 1.37 +import java.util.Map; 1.38 +import javax.xml.stream.XMLStreamException; 1.39 +import javax.xml.stream.XMLStreamReader; 1.40 +import javax.xml.stream.XMLStreamWriter; 1.41 +import javax.xml.transform.TransformerFactory; 1.42 +import javax.xml.transform.Transformer; 1.43 +import javax.xml.transform.TransformerException; 1.44 +import javax.xml.transform.dom.DOMResult; 1.45 + 1.46 +import org.xml.sax.ContentHandler; 1.47 +import org.xml.sax.DTDHandler; 1.48 +import org.xml.sax.ErrorHandler; 1.49 +import org.xml.sax.SAXException; 1.50 +import org.xml.sax.XMLReader; 1.51 +import org.xml.sax.ext.LexicalHandler; 1.52 +import org.w3c.dom.Node; 1.53 + 1.54 +/** 1.55 + * An immutable stream-based buffer of an XML infoset. 1.56 + * 1.57 + * <p> 1.58 + * A XMLStreamBuffer is an abstract class. It is immutable with 1.59 + * respect to the methods on the class, which are non-modifying in terms 1.60 + * of state. 1.61 + * 1.62 + * <p> 1.63 + * A XMLStreamBuffer can be processed using specific SAX and StAX-based 1.64 + * processors. Utility methods on XMLStreamBuffer are provided for 1.65 + * such functionality that utilize SAX and StAX-based processors. 1.66 + * The same instance of a XMLStreamBuffer may be processed 1.67 + * multiple times and concurrently by more than one processor. 1.68 + * 1.69 + * <p> 1.70 + * There are two concrete implementations of XMLStreamBuffer. 1.71 + * The first, {@link MutableXMLStreamBuffer}, can be instantiated for the creation 1.72 + * of a buffer using SAX and StAX-based creators, and from which may be 1.73 + * processed as an XMLStreamBuffer. The second, 1.74 + * {@link XMLStreamBufferMark}, can be instantiated to mark into an existing 1.75 + * buffer that is being created or processed. This allows a subtree of 1.76 + * {@link XMLStreamBuffer} to be treated as its own {@link XMLStreamBuffer}. 1.77 + * 1.78 + * <p> 1.79 + * A XMLStreamBuffer can represent a complete XML infoset or a subtree 1.80 + * of an XML infoset. It is also capable of representing a "forest", 1.81 + * where the buffer represents multiple adjacent XML elements, although 1.82 + * in this mode there are restrictions about how you can consume such 1.83 + * forest, because not all XML APIs handle forests very well. 1.84 + */ 1.85 +public abstract class XMLStreamBuffer { 1.86 + 1.87 + /** 1.88 + * In scope namespaces on a fragment 1.89 + */ 1.90 + protected Map<String,String> _inscopeNamespaces = Collections.emptyMap(); 1.91 + 1.92 + /** 1.93 + * True if the buffer was created from a parser that interns Strings 1.94 + * as specified by the SAX interning features 1.95 + */ 1.96 + protected boolean _hasInternedStrings; 1.97 + 1.98 + /** 1.99 + * Fragmented array to hold structural information 1.100 + */ 1.101 + protected FragmentedArray<byte[]> _structure; 1.102 + protected int _structurePtr; 1.103 + 1.104 + /** 1.105 + * Fragmented array to hold structural information as strings 1.106 + */ 1.107 + protected FragmentedArray<String[]> _structureStrings; 1.108 + protected int _structureStringsPtr; 1.109 + 1.110 + /** 1.111 + * Fragmented array to hold content information in a shared char[] 1.112 + */ 1.113 + protected FragmentedArray<char[]> _contentCharactersBuffer; 1.114 + protected int _contentCharactersBufferPtr; 1.115 + 1.116 + /** 1.117 + * Fragmented array to hold content information as objects 1.118 + */ 1.119 + protected FragmentedArray<Object[]> _contentObjects; 1.120 + protected int _contentObjectsPtr; 1.121 + 1.122 + /** 1.123 + * Number of trees in this stream buffer. 1.124 + * 1.125 + * <p> 1.126 + * 1 if there's only one, which is the normal case. When the buffer 1.127 + * holds a forest, this value is greater than 1. If the buffer is empty, then 0. 1.128 + * 1.129 + * <p> 1.130 + * Notice that we cannot infer this value by looking at the {@link FragmentedArray}s, 1.131 + * because this {@link XMLStreamBuffer} maybe a view of a portion of another bigger 1.132 + * {@link XMLStreamBuffer}. 1.133 + */ 1.134 + protected int treeCount; 1.135 + 1.136 + /** 1.137 + * The system identifier associated with the buffer 1.138 + */ 1.139 + protected String systemId; 1.140 + 1.141 + /** 1.142 + * Is the buffer created by creator. 1.143 + * 1.144 + * @return 1.145 + * <code>true</code> if the buffer has been created. 1.146 + */ 1.147 + public final boolean isCreated() { 1.148 + return _structure.getArray()[0] != AbstractCreatorProcessor.T_END; 1.149 + } 1.150 + 1.151 + /** 1.152 + * Is the buffer a representation of a fragment of an XML infoset. 1.153 + * 1.154 + * @return 1.155 + * <code>true</code> if the buffer is a representation of a fragment 1.156 + * of an XML infoset. 1.157 + */ 1.158 + public final boolean isFragment() { 1.159 + return (isCreated() && (_structure.getArray()[_structurePtr] & AbstractCreatorProcessor.TYPE_MASK) 1.160 + != AbstractCreatorProcessor.T_DOCUMENT); 1.161 + } 1.162 + 1.163 + /** 1.164 + * Is the buffer a representation of a fragment of an XML infoset 1.165 + * that is an element (and its contents). 1.166 + * 1.167 + * @return 1.168 + * <code>true</code> if the buffer a representation 1.169 + * of a fragment of an XML infoset that is an element (and its contents). 1.170 + */ 1.171 + public final boolean isElementFragment() { 1.172 + return (isCreated() && (_structure.getArray()[_structurePtr] & AbstractCreatorProcessor.TYPE_MASK) 1.173 + == AbstractCreatorProcessor.T_ELEMENT); 1.174 + } 1.175 + 1.176 + /** 1.177 + * Returns ture if this buffer represents a forest, which is 1.178 + * are more than one adjacent XML elements. 1.179 + */ 1.180 + public final boolean isForest() { 1.181 + return isCreated() && treeCount>1; 1.182 + } 1.183 + 1.184 + /** 1.185 + * Get the system identifier associated with the buffer. 1.186 + * @return The system identifier. 1.187 + */ 1.188 + public final String getSystemId() { 1.189 + return systemId; 1.190 + } 1.191 + 1.192 + /** 1.193 + * Get the in-scope namespaces. 1.194 + * 1.195 + * <p> 1.196 + * 1.197 + * The in-scope namespaces will be empty if the buffer is not a 1.198 + * fragment ({@link #isFragment} returns <code>false</code>). 1.199 + * 1.200 + * The in-scope namespace will correspond to the in-scope namespaces of the 1.201 + * fragment if the buffer is a fragment ({@link #isFragment} 1.202 + * returns <code>false</code>). The in-scope namespaces will include any 1.203 + * namespace delcarations on an element if the fragment correspond to that 1.204 + * of an element ({@link #isElementFragment} returns <code>false</code>). 1.205 + * 1.206 + * @return 1.207 + * The in-scope namespaces of the XMLStreamBuffer. 1.208 + * Prefix to namespace URI. 1.209 + */ 1.210 + public final Map<String,String> getInscopeNamespaces() { 1.211 + return _inscopeNamespaces; 1.212 + } 1.213 + 1.214 + /** 1.215 + * Has the buffer been created using Strings that have been interned 1.216 + * for certain properties of information items. The Strings that are interned 1.217 + * are those that correspond to Strings that are specified by the SAX API 1.218 + * "string-interning" property 1.219 + * (see <a href="http://java.sun.com/j2se/1.5.0/docs/api/org/xml/sax/package-summary.html#package_description">here</a>). 1.220 + * 1.221 + * <p> 1.222 + * An buffer may have been created, for example, from an XML document parsed 1.223 + * using the Xerces SAX parser. The Xerces SAX parser will have interned certain Strings 1.224 + * according to the SAX string interning property. 1.225 + * This method enables processors to avoid the duplication of 1.226 + * String interning if such a feature is required by a procesing application and the 1.227 + * buffer being processed was created using Strings that have been interned. 1.228 + * 1.229 + * @return 1.230 + * <code>true</code> if the buffer has been created using Strings that 1.231 + * have been interned. 1.232 + */ 1.233 + public final boolean hasInternedStrings() { 1.234 + return _hasInternedStrings; 1.235 + } 1.236 + 1.237 + /** 1.238 + * Read the contents of the buffer as a {@link XMLStreamReader}. 1.239 + * 1.240 + * @return 1.241 + * A an instance of a {@link StreamReaderBufferProcessor}. Always non-null. 1.242 + */ 1.243 + public final StreamReaderBufferProcessor readAsXMLStreamReader() throws XMLStreamException { 1.244 + return new StreamReaderBufferProcessor(this); 1.245 + } 1.246 + 1.247 + /** 1.248 + * Write the contents of the buffer to an XMLStreamWriter. 1.249 + * 1.250 + * <p> 1.251 + * The XMLStreamBuffer will be written out to the XMLStreamWriter using 1.252 + * an instance of {@link StreamWriterBufferProcessor}. 1.253 + * 1.254 + * @param writer 1.255 + * A XMLStreamWriter to write to. 1.256 + * @param writeAsFragment 1.257 + * If true, {@link XMLStreamWriter} will not receive {@link XMLStreamWriter#writeStartDocument()} 1.258 + * nor {@link XMLStreamWriter#writeEndDocument()}. This is desirable behavior when 1.259 + * you are writing the contents of a buffer into a bigger document. 1.260 + */ 1.261 + public final void writeToXMLStreamWriter(XMLStreamWriter writer, boolean writeAsFragment) throws XMLStreamException { 1.262 + StreamWriterBufferProcessor p = new StreamWriterBufferProcessor(this,writeAsFragment); 1.263 + p.process(writer); 1.264 + } 1.265 + 1.266 + /** 1.267 + * @deprecated 1.268 + * Use {@link #writeToXMLStreamWriter(XMLStreamWriter, boolean)} 1.269 + */ 1.270 + public final void writeToXMLStreamWriter(XMLStreamWriter writer) throws XMLStreamException { 1.271 + writeToXMLStreamWriter(writer, this.isFragment()); 1.272 + } 1.273 + 1.274 + /** 1.275 + * Reads the contents of the buffer from a {@link XMLReader}. 1.276 + * 1.277 + * @return 1.278 + * A an instance of a {@link SAXBufferProcessor}. 1.279 + * @deprecated 1.280 + * Use {@link #readAsXMLReader(boolean)} 1.281 + */ 1.282 + public final SAXBufferProcessor readAsXMLReader() { 1.283 + return new SAXBufferProcessor(this,isFragment()); 1.284 + } 1.285 + 1.286 + /** 1.287 + * Reads the contents of the buffer from a {@link XMLReader}. 1.288 + * 1.289 + * @param produceFragmentEvent 1.290 + * True to generate fragment SAX events without start/endDocument. 1.291 + * False to generate a full document SAX events. 1.292 + * @return 1.293 + * A an instance of a {@link SAXBufferProcessor}. 1.294 + */ 1.295 + public final SAXBufferProcessor readAsXMLReader(boolean produceFragmentEvent) { 1.296 + return new SAXBufferProcessor(this,produceFragmentEvent); 1.297 + } 1.298 + 1.299 + /** 1.300 + * Write the contents of the buffer to a {@link ContentHandler}. 1.301 + * 1.302 + * <p> 1.303 + * If the <code>handler</code> is also an instance of other SAX-based 1.304 + * handlers, such as {@link LexicalHandler}, than corresponding SAX events 1.305 + * will be reported to those handlers. 1.306 + * 1.307 + * @param handler 1.308 + * The ContentHandler to receive SAX events. 1.309 + * @param produceFragmentEvent 1.310 + * True to generate fragment SAX events without start/endDocument. 1.311 + * False to generate a full document SAX events. 1.312 + * 1.313 + * @throws SAXException 1.314 + * if a parsing fails, or if {@link ContentHandler} throws a {@link SAXException}. 1.315 + */ 1.316 + public final void writeTo(ContentHandler handler, boolean produceFragmentEvent) throws SAXException { 1.317 + SAXBufferProcessor p = readAsXMLReader(produceFragmentEvent); 1.318 + p.setContentHandler(handler); 1.319 + if (p instanceof LexicalHandler) { 1.320 + p.setLexicalHandler((LexicalHandler)handler); 1.321 + } 1.322 + if (p instanceof DTDHandler) { 1.323 + p.setDTDHandler((DTDHandler)handler); 1.324 + } 1.325 + if (p instanceof ErrorHandler) { 1.326 + p.setErrorHandler((ErrorHandler)handler); 1.327 + } 1.328 + p.process(); 1.329 + } 1.330 + 1.331 + /** 1.332 + * @deprecated 1.333 + * Use {@link #writeTo(ContentHandler,boolean)} 1.334 + */ 1.335 + public final void writeTo(ContentHandler handler) throws SAXException { 1.336 + writeTo(handler,isFragment()); 1.337 + } 1.338 + 1.339 + /** 1.340 + * Write the contents of the buffer to a {@link ContentHandler} with errors 1.341 + * report to a {@link ErrorHandler}. 1.342 + * 1.343 + * <p> 1.344 + * If the <code>handler</code> is also an instance of other SAX-based 1.345 + * handlers, such as {@link LexicalHandler}, than corresponding SAX events 1.346 + * will be reported to those handlers. 1.347 + * 1.348 + * @param handler 1.349 + * The ContentHandler to receive SAX events. 1.350 + * @param errorHandler 1.351 + * The ErrorHandler to receive error events. 1.352 + * 1.353 + * @throws SAXException 1.354 + * if a parsing fails and {@link ErrorHandler} throws a {@link SAXException}, 1.355 + * or if {@link ContentHandler} throws a {@link SAXException}. 1.356 + */ 1.357 + public final void writeTo(ContentHandler handler, ErrorHandler errorHandler, boolean produceFragmentEvent) throws SAXException { 1.358 + SAXBufferProcessor p = readAsXMLReader(produceFragmentEvent); 1.359 + p.setContentHandler(handler); 1.360 + if (p instanceof LexicalHandler) { 1.361 + p.setLexicalHandler((LexicalHandler)handler); 1.362 + } 1.363 + if (p instanceof DTDHandler) { 1.364 + p.setDTDHandler((DTDHandler)handler); 1.365 + } 1.366 + 1.367 + p.setErrorHandler(errorHandler); 1.368 + 1.369 + p.process(); 1.370 + } 1.371 + 1.372 + public final void writeTo(ContentHandler handler, ErrorHandler errorHandler) throws SAXException { 1.373 + writeTo(handler, errorHandler, isFragment()); 1.374 + } 1.375 + 1.376 + private static final TransformerFactory trnsformerFactory = TransformerFactory.newInstance(); 1.377 + 1.378 + /** 1.379 + * Writes out the contents of this buffer as DOM node and append that to the given node. 1.380 + * 1.381 + * Faster implementation would be desirable. 1.382 + * 1.383 + * @return 1.384 + * The newly added child node. 1.385 + */ 1.386 + public final Node writeTo(Node n) throws XMLStreamBufferException { 1.387 + try { 1.388 + Transformer t = trnsformerFactory.newTransformer(); 1.389 + t.transform(new XMLStreamBufferSource(this), new DOMResult(n)); 1.390 + return n.getLastChild(); 1.391 + } catch (TransformerException e) { 1.392 + throw new XMLStreamBufferException(e); 1.393 + } 1.394 + } 1.395 + 1.396 + /** 1.397 + * Create a new buffer from a XMLStreamReader. 1.398 + * 1.399 + * @param reader 1.400 + * A XMLStreamReader to read from to create. 1.401 + * @return XMLStreamBuffer the created buffer 1.402 + * @see MutableXMLStreamBuffer#createFromXMLStreamReader(XMLStreamReader) 1.403 + */ 1.404 + public static XMLStreamBuffer createNewBufferFromXMLStreamReader(XMLStreamReader reader) 1.405 + throws XMLStreamException { 1.406 + MutableXMLStreamBuffer b = new MutableXMLStreamBuffer(); 1.407 + b.createFromXMLStreamReader(reader); 1.408 + return b; 1.409 + } 1.410 + 1.411 + /** 1.412 + * Create a new buffer from a {@link XMLReader} and {@link InputStream}. 1.413 + * 1.414 + * @param reader 1.415 + * The {@link XMLReader} to use for parsing. 1.416 + * @param in 1.417 + * The {@link InputStream} to be parsed. 1.418 + * @return XMLStreamBuffer the created buffer 1.419 + * @see MutableXMLStreamBuffer#createFromXMLReader(XMLReader, InputStream) 1.420 + */ 1.421 + public static XMLStreamBuffer createNewBufferFromXMLReader(XMLReader reader, InputStream in) throws SAXException, IOException { 1.422 + MutableXMLStreamBuffer b = new MutableXMLStreamBuffer(); 1.423 + b.createFromXMLReader(reader, in); 1.424 + return b; 1.425 + } 1.426 + 1.427 + /** 1.428 + * Create a new buffer from a {@link XMLReader} and {@link InputStream}. 1.429 + * 1.430 + * @param reader 1.431 + * The {@link XMLReader} to use for parsing. 1.432 + * @param in 1.433 + * The {@link InputStream} to be parsed. 1.434 + * @param systemId 1.435 + * The system ID of the input stream. 1.436 + * @return XMLStreamBuffer the created buffer 1.437 + * @see MutableXMLStreamBuffer#createFromXMLReader(XMLReader, InputStream, String) 1.438 + */ 1.439 + public static XMLStreamBuffer createNewBufferFromXMLReader(XMLReader reader, InputStream in, 1.440 + String systemId) throws SAXException, IOException { 1.441 + MutableXMLStreamBuffer b = new MutableXMLStreamBuffer(); 1.442 + b.createFromXMLReader(reader, in, systemId); 1.443 + return b; 1.444 + } 1.445 + 1.446 + protected final FragmentedArray<byte[]> getStructure() { 1.447 + return _structure; 1.448 + } 1.449 + 1.450 + protected final int getStructurePtr() { 1.451 + return _structurePtr; 1.452 + } 1.453 + 1.454 + protected final FragmentedArray<String[]> getStructureStrings() { 1.455 + return _structureStrings; 1.456 + } 1.457 + 1.458 + protected final int getStructureStringsPtr() { 1.459 + return _structureStringsPtr; 1.460 + } 1.461 + 1.462 + protected final FragmentedArray<char[]> getContentCharactersBuffer() { 1.463 + return _contentCharactersBuffer; 1.464 + } 1.465 + 1.466 + protected final int getContentCharactersBufferPtr() { 1.467 + return _contentCharactersBufferPtr; 1.468 + } 1.469 + 1.470 + protected final FragmentedArray<Object[]> getContentObjects() { 1.471 + return _contentObjects; 1.472 + } 1.473 + 1.474 + protected final int getContentObjectsPtr() { 1.475 + return _contentObjectsPtr; 1.476 + } 1.477 +}