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

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 2005, 2012, 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 */
25
26 package com.sun.xml.internal.stream.buffer.stax;
27
28 import com.sun.xml.internal.stream.buffer.AbstractProcessor;
29 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
30
31 import java.io.IOException;
32 import java.util.Collections;
33 import java.util.HashSet;
34 import java.util.Map;
35 import java.util.Set;
36
37 import com.sun.xml.internal.org.jvnet.staxex.Base64Data;
38 import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx;
39
40 import javax.xml.stream.XMLStreamException;
41 import javax.xml.stream.XMLStreamWriter;
42
43
44 /**
45 * A processor of a {@link XMLStreamBuffer} that writes the XML infoset to a
46 * {@link XMLStreamWriter}.
47 *
48 * @author Paul.Sandoz@Sun.Com
49 * @author K.Venugopal@sun.com
50 */
51 public class StreamWriterBufferProcessor extends AbstractProcessor {
52
53
54 public StreamWriterBufferProcessor() {
55 }
56
57 /**
58 * @deprecated
59 * Use {@link #StreamWriterBufferProcessor(XMLStreamBuffer, boolean)}
60 */
61 public StreamWriterBufferProcessor(XMLStreamBuffer buffer) {
62 setXMLStreamBuffer(buffer,buffer.isFragment());
63 }
64
65 /**
66 * @param produceFragmentEvent
67 * True to generate fragment SAX events without start/endDocument.
68 * False to generate a full document SAX events.
69 */
70 public StreamWriterBufferProcessor(XMLStreamBuffer buffer,boolean produceFragmentEvent) {
71 setXMLStreamBuffer(buffer,produceFragmentEvent);
72 }
73
74 public final void process(XMLStreamBuffer buffer, XMLStreamWriter writer) throws XMLStreamException {
75 setXMLStreamBuffer(buffer,buffer.isFragment());
76 process(writer);
77 }
78
79 public void process(XMLStreamWriter writer) throws XMLStreamException {
80 if(_fragmentMode){
81 writeFragment(writer);
82 }else{
83 write(writer);
84 }
85 }
86
87 /**
88 * @deprecated
89 * Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}
90 */
91 public void setXMLStreamBuffer(XMLStreamBuffer buffer) {
92 setBuffer(buffer);
93 }
94
95 /**
96 * @param produceFragmentEvent
97 * True to generate fragment SAX events without start/endDocument.
98 * False to generate a full document SAX events.
99 */
100 public void setXMLStreamBuffer(XMLStreamBuffer buffer, boolean produceFragmentEvent) {
101 setBuffer(buffer,produceFragmentEvent);
102 }
103
104 /**
105 * Writes a full XML infoset event to the given writer,
106 * including start/end document.
107 * Any inscope namespaces present will be written as namespace
108 * delcarations on each top-level element.
109 */
110 public void write(XMLStreamWriter writer) throws XMLStreamException{
111
112 if(!_fragmentMode) {
113 if(_treeCount>1)
114 throw new IllegalStateException("forest cannot be written as a full infoset");
115 writer.writeStartDocument();
116 }
117
118 while(true) {
119 int item = getEIIState(peekStructure());
120 writer.flush();
121
122 switch(item) {
123 case STATE_DOCUMENT:
124 readStructure(); //skip
125 break;
126 case STATE_ELEMENT_U_LN_QN:
127 case STATE_ELEMENT_P_U_LN:
128 case STATE_ELEMENT_U_LN:
129 case STATE_ELEMENT_LN:
130 writeFragment(writer);
131 break;
132 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: {
133 readStructure();
134 final int length = readStructure();
135 final int start = readContentCharactersBuffer(length);
136 final String comment = new String(_contentCharactersBuffer, start, length);
137 writer.writeComment(comment);
138 break;
139 }
140 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: {
141 readStructure();
142 final int length = readStructure16();
143 final int start = readContentCharactersBuffer(length);
144 final String comment = new String(_contentCharactersBuffer, start, length);
145 writer.writeComment(comment);
146 break;
147 }
148 case STATE_COMMENT_AS_CHAR_ARRAY_COPY: {
149 readStructure();
150 final char[] ch = readContentCharactersCopy();
151 writer.writeComment(new String(ch));
152 break;
153 }
154 case STATE_PROCESSING_INSTRUCTION:
155 readStructure();
156 writer.writeProcessingInstruction(readStructureString(), readStructureString());
157 break;
158 case STATE_END: // done
159 readStructure();
160 writer.writeEndDocument();
161 return;
162 default:
163 throw new XMLStreamException("Invalid State "+item);
164 }
165 }
166
167 }
168
169 /**
170 * Writes the buffer as a fragment, meaning
171 * the writer will not receive start/endDocument events.
172 * Any inscope namespaces present will be written as namespace
173 * delcarations on each top-level element.
174 * <p>
175 * If {@link XMLStreamBuffer} has a forest, this method will write all the forests.
176 */
177 public void writeFragment(XMLStreamWriter writer) throws XMLStreamException {
178 if (writer instanceof XMLStreamWriterEx) {
179 writeFragmentEx((XMLStreamWriterEx)writer);
180 } else {
181 writeFragmentNoEx(writer);
182 }
183 }
184
185 public void writeFragmentEx(XMLStreamWriterEx writer) throws XMLStreamException {
186 int depth = 0; // used to determine when we are done with a tree.
187
188 int item = getEIIState(peekStructure());
189 if(item==STATE_DOCUMENT)
190 readStructure(); // skip STATE_DOCUMENT
191
192 do {
193
194 item = readEiiState();
195
196 switch(item) {
197 case STATE_DOCUMENT:
198 throw new AssertionError();
199 case STATE_ELEMENT_U_LN_QN: {
200 depth ++;
201 final String uri = readStructureString();
202 final String localName = readStructureString();
203 final String prefix = getPrefixFromQName(readStructureString());
204 writer.writeStartElement(prefix,localName,uri);
205 writeAttributes(writer, isInscope(depth));
206 break;
207 }
208 case STATE_ELEMENT_P_U_LN: {
209 depth ++;
210 final String prefix = readStructureString();
211 final String uri = readStructureString();
212 final String localName = readStructureString();
213 writer.writeStartElement(prefix,localName,uri);
214 writeAttributes(writer, isInscope(depth));
215 break;
216 }
217 case STATE_ELEMENT_U_LN: {
218 depth ++;
219 final String uri = readStructureString();
220 final String localName = readStructureString();
221 writer.writeStartElement("",localName,uri);
222 writeAttributes(writer, isInscope(depth));
223 break;
224 }
225 case STATE_ELEMENT_LN: {
226 depth ++;
227 final String localName = readStructureString();
228 writer.writeStartElement(localName);
229 writeAttributes(writer, isInscope(depth));
230 break;
231 }
232 case STATE_TEXT_AS_CHAR_ARRAY_SMALL: {
233 final int length = readStructure();
234 final int start = readContentCharactersBuffer(length);
235 writer.writeCharacters(_contentCharactersBuffer,start,length);
236 break;
237 }
238 case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: {
239 final int length = readStructure16();
240 final int start = readContentCharactersBuffer(length);
241 writer.writeCharacters(_contentCharactersBuffer,start,length);
242 break;
243 }
244 case STATE_TEXT_AS_CHAR_ARRAY_COPY: {
245 char[] c = readContentCharactersCopy();
246 writer.writeCharacters(c,0,c.length);
247 break;
248 }
249 case STATE_TEXT_AS_STRING: {
250 final String s = readContentString();
251 writer.writeCharacters(s);
252 break;
253 }
254 case STATE_TEXT_AS_OBJECT: {
255 final CharSequence c = (CharSequence)readContentObject();
256 writer.writePCDATA(c);
257 break;
258 }
259 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: {
260 final int length = readStructure();
261 final int start = readContentCharactersBuffer(length);
262 final String comment = new String(_contentCharactersBuffer, start, length);
263 writer.writeComment(comment);
264 break;
265 }
266 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: {
267 final int length = readStructure16();
268 final int start = readContentCharactersBuffer(length);
269 final String comment = new String(_contentCharactersBuffer, start, length);
270 writer.writeComment(comment);
271 break;
272 }
273 case STATE_COMMENT_AS_CHAR_ARRAY_COPY: {
274 final char[] ch = readContentCharactersCopy();
275 writer.writeComment(new String(ch));
276 break;
277 }
278 case STATE_PROCESSING_INSTRUCTION:
279 writer.writeProcessingInstruction(readStructureString(), readStructureString());
280 break;
281 case STATE_END:
282 writer.writeEndElement();
283 depth --;
284 if(depth==0)
285 _treeCount--;
286 break;
287 default:
288 throw new XMLStreamException("Invalid State "+item);
289 }
290 } while(depth>0 || _treeCount>0);
291
292 }
293
294 public void writeFragmentNoEx(XMLStreamWriter writer) throws XMLStreamException {
295 int depth = 0;
296
297 int item = getEIIState(peekStructure());
298 if(item==STATE_DOCUMENT)
299 readStructure(); // skip STATE_DOCUMENT
300
301 do {
302 item = readEiiState();
303
304 switch(item) {
305 case STATE_DOCUMENT:
306 throw new AssertionError();
307 case STATE_ELEMENT_U_LN_QN: {
308 depth ++;
309 final String uri = readStructureString();
310 final String localName = readStructureString();
311 final String prefix = getPrefixFromQName(readStructureString());
312 writer.writeStartElement(prefix,localName,uri);
313 writeAttributes(writer, isInscope(depth));
314 break;
315 }
316 case STATE_ELEMENT_P_U_LN: {
317 depth ++;
318 final String prefix = readStructureString();
319 final String uri = readStructureString();
320 final String localName = readStructureString();
321 writer.writeStartElement(prefix,localName,uri);
322 writeAttributes(writer, isInscope(depth));
323 break;
324 }
325 case STATE_ELEMENT_U_LN: {
326 depth ++;
327 final String uri = readStructureString();
328 final String localName = readStructureString();
329 writer.writeStartElement("",localName,uri);
330 writeAttributes(writer, isInscope(depth));
331 break;
332 }
333 case STATE_ELEMENT_LN: {
334 depth ++;
335 final String localName = readStructureString();
336 writer.writeStartElement(localName);
337 writeAttributes(writer, isInscope(depth));
338 break;
339 }
340 case STATE_TEXT_AS_CHAR_ARRAY_SMALL: {
341 final int length = readStructure();
342 final int start = readContentCharactersBuffer(length);
343 writer.writeCharacters(_contentCharactersBuffer,start,length);
344 break;
345 }
346 case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: {
347 final int length = readStructure16();
348 final int start = readContentCharactersBuffer(length);
349 writer.writeCharacters(_contentCharactersBuffer,start,length);
350 break;
351 }
352 case STATE_TEXT_AS_CHAR_ARRAY_COPY: {
353 char[] c = readContentCharactersCopy();
354 writer.writeCharacters(c,0,c.length);
355 break;
356 }
357 case STATE_TEXT_AS_STRING: {
358 final String s = readContentString();
359 writer.writeCharacters(s);
360 break;
361 }
362 case STATE_TEXT_AS_OBJECT: {
363 final CharSequence c = (CharSequence)readContentObject();
364 if (c instanceof Base64Data) {
365 try {
366 Base64Data bd = (Base64Data)c;
367 bd.writeTo(writer);
368 } catch (IOException e) {
369 throw new XMLStreamException(e);
370 }
371 } else {
372 writer.writeCharacters(c.toString());
373 }
374 break;
375 }
376 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: {
377 final int length = readStructure();
378 final int start = readContentCharactersBuffer(length);
379 final String comment = new String(_contentCharactersBuffer, start, length);
380 writer.writeComment(comment);
381 break;
382 }
383 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: {
384 final int length = readStructure16();
385 final int start = readContentCharactersBuffer(length);
386 final String comment = new String(_contentCharactersBuffer, start, length);
387 writer.writeComment(comment);
388 break;
389 }
390 case STATE_COMMENT_AS_CHAR_ARRAY_COPY: {
391 final char[] ch = readContentCharactersCopy();
392 writer.writeComment(new String(ch));
393 break;
394 }
395 case STATE_PROCESSING_INSTRUCTION:
396 writer.writeProcessingInstruction(readStructureString(), readStructureString());
397 break;
398 case STATE_END:
399 writer.writeEndElement();
400 depth --;
401 if(depth==0)
402 _treeCount--;
403 break;
404 default:
405 throw new XMLStreamException("Invalid State "+item);
406 }
407 } while(depth > 0 || _treeCount>0);
408
409 }
410
411 private boolean isInscope(int depth) {
412 return _buffer.getInscopeNamespaces().size() > 0 && depth ==1;
413 }
414
415 /*
416 * @param inscope: true means write inscope namespaces
417 */
418 private void writeAttributes(XMLStreamWriter writer, boolean inscope) throws XMLStreamException {
419 // prefixSet to collect prefixes that are written before writing inscope namespaces
420 Set<String> prefixSet = inscope ? new HashSet<String>() : Collections.<String>emptySet();
421 int item = peekStructure();
422 if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) {
423 // Skip the namespace declarations on the element
424 // they will have been added already
425 item = writeNamespaceAttributes(item, writer, inscope, prefixSet);
426 }
427 if (inscope) {
428 writeInscopeNamespaces(writer, prefixSet);
429 }
430 if ((item & TYPE_MASK) == T_ATTRIBUTE) {
431 writeAttributes(item, writer);
432 }
433 }
434
435 private static String fixNull(String s) {
436 if (s == null) return "";
437 else return s;
438 }
439
440 /*
441 * @param prefixSet: already written prefixes
442 */
443 private void writeInscopeNamespaces(XMLStreamWriter writer, Set<String> prefixSet) throws XMLStreamException {
444 for (Map.Entry<String, String> e : _buffer.getInscopeNamespaces().entrySet()) {
445 String key = fixNull(e.getKey());
446 // If the prefix is already written, do not write the prefix
447 if (!prefixSet.contains(key)) {
448 writer.writeNamespace(key, e.getValue());
449 }
450 }
451 }
452
453 private int writeNamespaceAttributes(int item, XMLStreamWriter writer, boolean collectPrefixes, Set<String> prefixSet) throws XMLStreamException {
454 do {
455 switch(getNIIState(item)){
456 case STATE_NAMESPACE_ATTRIBUTE:
457 // Undeclaration of default namespace
458 writer.writeDefaultNamespace("");
459 if (collectPrefixes) {
460 prefixSet.add("");
461 }
462 break;
463 case STATE_NAMESPACE_ATTRIBUTE_P:
464 // Undeclaration of namespace
465 // Declaration with prefix
466 String prefix = readStructureString();
467 writer.writeNamespace(prefix, "");
468 if (collectPrefixes) {
469 prefixSet.add(prefix);
470 }
471 break;
472 case STATE_NAMESPACE_ATTRIBUTE_P_U:
473 // Declaration with prefix
474 prefix = readStructureString();
475 writer.writeNamespace(prefix, readStructureString());
476 if (collectPrefixes) {
477 prefixSet.add(prefix);
478 }
479 break;
480 case STATE_NAMESPACE_ATTRIBUTE_U:
481 // Default declaration
482 writer.writeDefaultNamespace(readStructureString());
483 if (collectPrefixes) {
484 prefixSet.add("");
485 }
486 break;
487 }
488 readStructure();
489
490 item = peekStructure();
491 } while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE);
492
493 return item;
494 }
495
496 private void writeAttributes(int item, XMLStreamWriter writer) throws XMLStreamException {
497 do {
498 switch(getAIIState(item)) {
499 case STATE_ATTRIBUTE_U_LN_QN: {
500 final String uri = readStructureString();
501 final String localName = readStructureString();
502 final String prefix = getPrefixFromQName(readStructureString());
503 writer.writeAttribute(prefix,uri,localName,readContentString());
504 break;
505 }
506 case STATE_ATTRIBUTE_P_U_LN:
507 writer.writeAttribute(readStructureString(), readStructureString(),
508 readStructureString(), readContentString());
509 break;
510 case STATE_ATTRIBUTE_U_LN:
511 writer.writeAttribute(readStructureString(), readStructureString(), readContentString());
512 break;
513 case STATE_ATTRIBUTE_LN:
514 writer.writeAttribute(readStructureString(), readContentString());
515 break;
516 }
517 // Ignore the attribute type
518 readStructureString();
519
520 readStructure();
521
522 item = peekStructure();
523 } while((item & TYPE_MASK) == T_ATTRIBUTE);
524 }
525 }

mercurial