Fri, 23 Aug 2013 09:57:21 +0100
8022885: Update JAX-WS RI integration to 2.2.9-b14140
8013016: Rebase 8009009 against the latest jdk8/jaxws
Reviewed-by: alanb, chegar
1 /*
2 * Copyright (c) 2005, 2013, 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 TransformerFactory trnsformerFactory = TransformerFactory.newInstance();
375 /**
376 * Writes out the contents of this buffer as DOM node and append that to the given node.
377 *
378 * Faster implementation would be desirable.
379 *
380 * @return
381 * The newly added child node.
382 */
383 public final Node writeTo(Node n) throws XMLStreamBufferException {
384 try {
385 Transformer t = trnsformerFactory.newTransformer();
386 t.transform(new XMLStreamBufferSource(this), new DOMResult(n));
387 return n.getLastChild();
388 } catch (TransformerException e) {
389 throw new XMLStreamBufferException(e);
390 }
391 }
393 /**
394 * Create a new buffer from a XMLStreamReader.
395 *
396 * @param reader
397 * A XMLStreamReader to read from to create.
398 * @return XMLStreamBuffer the created buffer
399 * @see MutableXMLStreamBuffer#createFromXMLStreamReader(XMLStreamReader)
400 */
401 public static XMLStreamBuffer createNewBufferFromXMLStreamReader(XMLStreamReader reader)
402 throws XMLStreamException {
403 MutableXMLStreamBuffer b = new MutableXMLStreamBuffer();
404 b.createFromXMLStreamReader(reader);
405 return b;
406 }
408 /**
409 * Create a new buffer from a {@link XMLReader} and {@link InputStream}.
410 *
411 * @param reader
412 * The {@link XMLReader} to use for parsing.
413 * @param in
414 * The {@link InputStream} to be parsed.
415 * @return XMLStreamBuffer the created buffer
416 * @see MutableXMLStreamBuffer#createFromXMLReader(XMLReader, InputStream)
417 */
418 public static XMLStreamBuffer createNewBufferFromXMLReader(XMLReader reader, InputStream in) throws SAXException, IOException {
419 MutableXMLStreamBuffer b = new MutableXMLStreamBuffer();
420 b.createFromXMLReader(reader, in);
421 return b;
422 }
424 /**
425 * Create a new buffer from a {@link XMLReader} and {@link InputStream}.
426 *
427 * @param reader
428 * The {@link XMLReader} to use for parsing.
429 * @param in
430 * The {@link InputStream} to be parsed.
431 * @param systemId
432 * The system ID of the input stream.
433 * @return XMLStreamBuffer the created buffer
434 * @see MutableXMLStreamBuffer#createFromXMLReader(XMLReader, InputStream, String)
435 */
436 public static XMLStreamBuffer createNewBufferFromXMLReader(XMLReader reader, InputStream in,
437 String systemId) throws SAXException, IOException {
438 MutableXMLStreamBuffer b = new MutableXMLStreamBuffer();
439 b.createFromXMLReader(reader, in, systemId);
440 return b;
441 }
443 protected final FragmentedArray<byte[]> getStructure() {
444 return _structure;
445 }
447 protected final int getStructurePtr() {
448 return _structurePtr;
449 }
451 protected final FragmentedArray<String[]> getStructureStrings() {
452 return _structureStrings;
453 }
455 protected final int getStructureStringsPtr() {
456 return _structureStringsPtr;
457 }
459 protected final FragmentedArray<char[]> getContentCharactersBuffer() {
460 return _contentCharactersBuffer;
461 }
463 protected final int getContentCharactersBufferPtr() {
464 return _contentCharactersBufferPtr;
465 }
467 protected final FragmentedArray<Object[]> getContentObjects() {
468 return _contentObjects;
469 }
471 protected final int getContentObjectsPtr() {
472 return _contentObjectsPtr;
473 }
474 }