001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020:
021: package com.sun.xml.stream.buffer.stax;
022:
023: import com.sun.xml.stream.buffer.AbstractProcessor;
024: import com.sun.xml.stream.buffer.XMLStreamBuffer;
025: import org.jvnet.staxex.XMLStreamWriterEx;
026:
027: import javax.xml.stream.XMLStreamException;
028: import javax.xml.stream.XMLStreamWriter;
029:
030: /**
031: * A processor of a {@link XMLStreamBuffer} that writes the XML infoset to a
032: * {@link XMLStreamWriter}.
033: *
034: * @author Paul.Sandoz@Sun.Com
035: * @author K.Venugopal@sun.com
036: */
037: public class StreamWriterBufferProcessor extends AbstractProcessor {
038:
039: public StreamWriterBufferProcessor() {
040: }
041:
042: /**
043: * @deprecated
044: * Use {@link #StreamWriterBufferProcessor(XMLStreamBuffer, boolean)}
045: */
046: public StreamWriterBufferProcessor(XMLStreamBuffer buffer) {
047: setXMLStreamBuffer(buffer, buffer.isFragment());
048: }
049:
050: /**
051: * @param produceFragmentEvent
052: * True to generate fragment SAX events without start/endDocument.
053: * False to generate a full document SAX events.
054: */
055: public StreamWriterBufferProcessor(XMLStreamBuffer buffer,
056: boolean produceFragmentEvent) {
057: setXMLStreamBuffer(buffer, produceFragmentEvent);
058: }
059:
060: public final void process(XMLStreamBuffer buffer,
061: XMLStreamWriter writer) throws XMLStreamException {
062: setXMLStreamBuffer(buffer, buffer.isFragment());
063: process(writer);
064: }
065:
066: public void process(XMLStreamWriter writer)
067: throws XMLStreamException {
068: if (_fragmentMode) {
069: writeFragment(writer);
070: } else {
071: write(writer);
072: }
073: }
074:
075: /**
076: * @deprecated
077: * Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}
078: */
079: public void setXMLStreamBuffer(XMLStreamBuffer buffer) {
080: setBuffer(buffer);
081: }
082:
083: /**
084: * @param produceFragmentEvent
085: * True to generate fragment SAX events without start/endDocument.
086: * False to generate a full document SAX events.
087: */
088: public void setXMLStreamBuffer(XMLStreamBuffer buffer,
089: boolean produceFragmentEvent) {
090: setBuffer(buffer, produceFragmentEvent);
091: }
092:
093: /**
094: * Writes a full XML infoset event to the given writer,
095: * including start/end document.
096: */
097: public void write(XMLStreamWriter writer) throws XMLStreamException {
098:
099: if (!_fragmentMode) {
100: if (_treeCount > 1)
101: throw new IllegalStateException(
102: "forest cannot be written as a full infoset");
103: writer.writeStartDocument();
104: }
105:
106: // TODO: if we are writing a fragment XMLStreamBuffer as a full document,
107: // we need to put in-scope namespaces as top-level ns decls.
108:
109: while (true) {
110: int item = _eiiStateTable[peekStructure()];
111: writer.flush();
112:
113: switch (item) {
114: case STATE_DOCUMENT:
115: readStructure(); //skip
116: break;
117: case STATE_ELEMENT_U_LN_QN:
118: case STATE_ELEMENT_P_U_LN:
119: case STATE_ELEMENT_U_LN:
120: case STATE_ELEMENT_LN:
121: writeFragment(writer);
122: break;
123: case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: {
124: readStructure();
125: final int length = readStructure();
126: final int start = readContentCharactersBuffer(length);
127: final String comment = new String(
128: _contentCharactersBuffer, start, length);
129: writer.writeComment(comment);
130: break;
131: }
132: case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: {
133: readStructure();
134: final int length = readStructure16();
135: final int start = readContentCharactersBuffer(length);
136: final String comment = new String(
137: _contentCharactersBuffer, start, length);
138: writer.writeComment(comment);
139: break;
140: }
141: case STATE_COMMENT_AS_CHAR_ARRAY_COPY: {
142: readStructure();
143: final char[] ch = readContentCharactersCopy();
144: writer.writeComment(new String(ch));
145: break;
146: }
147: case STATE_PROCESSING_INSTRUCTION:
148: readStructure();
149: writer.writeProcessingInstruction(
150: readStructureString(), readStructureString());
151: break;
152: case STATE_END: // done
153: readStructure();
154: writer.writeEndDocument();
155: return;
156: default:
157: throw new XMLStreamException("Invalid State " + item);
158: }
159: }
160:
161: }
162:
163: /**
164: * Writes the buffer as a fragment, meaning
165: * the writer will not receive start/endDocument events.
166: *
167: * <p>
168: * If {@link XMLStreamBuffer} has a forest, this method will write all the forests.
169: */
170: public void writeFragment(XMLStreamWriter writer)
171: throws XMLStreamException {
172: if (writer instanceof XMLStreamWriterEx) {
173: writeFragmentEx((XMLStreamWriterEx) writer);
174: } else {
175: writeFragmentNoEx(writer);
176: }
177: }
178:
179: public void writeFragmentEx(XMLStreamWriterEx writer)
180: throws XMLStreamException {
181: int depth = 0; // used to determine when we are done with a tree.
182:
183: int item = _eiiStateTable[peekStructure()];
184: if (item == STATE_DOCUMENT)
185: readStructure(); // skip STATE_DOCUMENT
186:
187: do {
188:
189: item = readEiiState();
190:
191: switch (item) {
192: case STATE_DOCUMENT:
193: throw new AssertionError();
194: case STATE_ELEMENT_U_LN_QN: {
195: depth++;
196: final String uri = readStructureString();
197: final String localName = readStructureString();
198: final String prefix = getPrefixFromQName(readStructureString());
199: writer.writeStartElement(prefix, localName, uri);
200: writeAttributes(writer);
201: break;
202: }
203: case STATE_ELEMENT_P_U_LN: {
204: depth++;
205: final String prefix = readStructureString();
206: final String uri = readStructureString();
207: final String localName = readStructureString();
208: writer.writeStartElement(prefix, localName, uri);
209: writeAttributes(writer);
210: break;
211: }
212: case STATE_ELEMENT_U_LN: {
213: depth++;
214: final String uri = readStructureString();
215: final String localName = readStructureString();
216: writer.writeStartElement("", localName, uri);
217: writeAttributes(writer);
218: break;
219: }
220: case STATE_ELEMENT_LN: {
221: depth++;
222: final String localName = readStructureString();
223: writer.writeStartElement(localName);
224: writeAttributes(writer);
225: break;
226: }
227: case STATE_TEXT_AS_CHAR_ARRAY_SMALL: {
228: final int length = readStructure();
229: final int start = readContentCharactersBuffer(length);
230: writer.writeCharacters(_contentCharactersBuffer, start,
231: length);
232: break;
233: }
234: case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: {
235: final int length = readStructure16();
236: final int start = readContentCharactersBuffer(length);
237: writer.writeCharacters(_contentCharactersBuffer, start,
238: length);
239: break;
240: }
241: case STATE_TEXT_AS_CHAR_ARRAY_COPY: {
242: char[] c = readContentCharactersCopy();
243: writer.writeCharacters(c, 0, c.length);
244: break;
245: }
246: case STATE_TEXT_AS_STRING: {
247: final String s = readContentString();
248: writer.writeCharacters(s);
249: break;
250: }
251: case STATE_TEXT_AS_OBJECT: {
252: final CharSequence c = (CharSequence) readContentObject();
253: writer.writePCDATA(c);
254: break;
255: }
256: case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: {
257: final int length = readStructure();
258: final int start = readContentCharactersBuffer(length);
259: final String comment = new String(
260: _contentCharactersBuffer, start, length);
261: writer.writeComment(comment);
262: break;
263: }
264: case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: {
265: final int length = readStructure16();
266: final int start = readContentCharactersBuffer(length);
267: final String comment = new String(
268: _contentCharactersBuffer, start, length);
269: writer.writeComment(comment);
270: break;
271: }
272: case STATE_COMMENT_AS_CHAR_ARRAY_COPY: {
273: final char[] ch = readContentCharactersCopy();
274: writer.writeComment(new String(ch));
275: break;
276: }
277: case STATE_PROCESSING_INSTRUCTION:
278: writer.writeProcessingInstruction(
279: 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)
295: throws XMLStreamException {
296: int depth = 0;
297:
298: int item = _eiiStateTable[peekStructure()];
299: if (item == STATE_DOCUMENT)
300: readStructure(); // skip STATE_DOCUMENT
301:
302: do {
303: item = readEiiState();
304:
305: switch (item) {
306: case STATE_DOCUMENT:
307: throw new AssertionError();
308: case STATE_ELEMENT_U_LN_QN: {
309: depth++;
310: final String uri = readStructureString();
311: final String localName = readStructureString();
312: final String prefix = getPrefixFromQName(readStructureString());
313: writer.writeStartElement(prefix, localName, uri);
314: writeAttributes(writer);
315: break;
316: }
317: case STATE_ELEMENT_P_U_LN: {
318: depth++;
319: final String prefix = readStructureString();
320: final String uri = readStructureString();
321: final String localName = readStructureString();
322: writer.writeStartElement(prefix, localName, uri);
323: writeAttributes(writer);
324: break;
325: }
326: case STATE_ELEMENT_U_LN: {
327: depth++;
328: final String uri = readStructureString();
329: final String localName = readStructureString();
330: writer.writeStartElement("", localName, uri);
331: writeAttributes(writer);
332: break;
333: }
334: case STATE_ELEMENT_LN: {
335: depth++;
336: final String localName = readStructureString();
337: writer.writeStartElement(localName);
338: writeAttributes(writer);
339: break;
340: }
341: case STATE_TEXT_AS_CHAR_ARRAY_SMALL: {
342: final int length = readStructure();
343: final int start = readContentCharactersBuffer(length);
344: writer.writeCharacters(_contentCharactersBuffer, start,
345: length);
346: break;
347: }
348: case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: {
349: final int length = readStructure16();
350: final int start = readContentCharactersBuffer(length);
351: writer.writeCharacters(_contentCharactersBuffer, start,
352: length);
353: break;
354: }
355: case STATE_TEXT_AS_CHAR_ARRAY_COPY: {
356: char[] c = readContentCharactersCopy();
357: writer.writeCharacters(c, 0, c.length);
358: break;
359: }
360: case STATE_TEXT_AS_STRING: {
361: final String s = readContentString();
362: writer.writeCharacters(s);
363: break;
364: }
365: case STATE_TEXT_AS_OBJECT: {
366: final CharSequence c = (CharSequence) readContentObject();
367: writer.writeCharacters(c.toString());
368: break;
369: }
370: case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: {
371: final int length = readStructure();
372: final int start = readContentCharactersBuffer(length);
373: final String comment = new String(
374: _contentCharactersBuffer, start, length);
375: writer.writeComment(comment);
376: break;
377: }
378: case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: {
379: final int length = readStructure16();
380: final int start = readContentCharactersBuffer(length);
381: final String comment = new String(
382: _contentCharactersBuffer, start, length);
383: writer.writeComment(comment);
384: break;
385: }
386: case STATE_COMMENT_AS_CHAR_ARRAY_COPY: {
387: final char[] ch = readContentCharactersCopy();
388: writer.writeComment(new String(ch));
389: break;
390: }
391: case STATE_PROCESSING_INSTRUCTION:
392: writer.writeProcessingInstruction(
393: readStructureString(), readStructureString());
394: break;
395: case STATE_END:
396: writer.writeEndElement();
397: depth--;
398: if (depth == 0)
399: _treeCount--;
400: break;
401: default:
402: throw new XMLStreamException("Invalid State " + item);
403: }
404: } while (depth > 0 && _treeCount > 0);
405:
406: }
407:
408: private void writeAttributes(XMLStreamWriter writer)
409: throws XMLStreamException {
410: int item = peekStructure();
411: if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) {
412: // Skip the namespace declarations on the element
413: // they will have been added already
414: item = writeNamespaceAttributes(item, writer);
415: }
416: if ((item & TYPE_MASK) == T_ATTRIBUTE) {
417: writeAttributes(item, writer);
418: }
419: }
420:
421: private int writeNamespaceAttributes(int item,
422: XMLStreamWriter writer) throws XMLStreamException {
423: do {
424: switch (_niiStateTable[item]) {
425: case STATE_NAMESPACE_ATTRIBUTE:
426: // Undeclaration of default namespace
427: writer.writeDefaultNamespace("");
428: break;
429: case STATE_NAMESPACE_ATTRIBUTE_P:
430: // Undeclaration of namespace
431: // Declaration with prefix
432: writer.writeNamespace(readStructureString(), "");
433: break;
434: case STATE_NAMESPACE_ATTRIBUTE_P_U:
435: // Declaration with prefix
436: writer.writeNamespace(readStructureString(),
437: readStructureString());
438: break;
439: case STATE_NAMESPACE_ATTRIBUTE_U:
440: // Default declaration
441: writer.writeDefaultNamespace(readStructureString());
442: break;
443: }
444: readStructure();
445:
446: item = peekStructure();
447: } while ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE);
448:
449: return item;
450: }
451:
452: private void writeAttributes(int item, XMLStreamWriter writer)
453: throws XMLStreamException {
454: do {
455: switch (_aiiStateTable[item]) {
456: case STATE_ATTRIBUTE_U_LN_QN: {
457: final String uri = readStructureString();
458: final String localName = readStructureString();
459: final String prefix = getPrefixFromQName(readStructureString());
460: writer.writeAttribute(prefix, uri, localName,
461: readContentString());
462: break;
463: }
464: case STATE_ATTRIBUTE_P_U_LN:
465: writer.writeAttribute(readStructureString(),
466: readStructureString(), readStructureString(),
467: readContentString());
468: break;
469: case STATE_ATTRIBUTE_U_LN:
470: writer.writeAttribute(readStructureString(),
471: readStructureString(), readContentString());
472: break;
473: case STATE_ATTRIBUTE_LN:
474: writer.writeAttribute(readStructureString(),
475: readContentString());
476: break;
477: }
478: // Ignore the attribute type
479: readStructureString();
480:
481: readStructure();
482:
483: item = peekStructure();
484: } while ((item & TYPE_MASK) == T_ATTRIBUTE);
485: }
486: }
|