001: /*
002: * Copyright (c) 2006, John Kristian
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: *
011: * * Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: *
015: * * Neither the name of StAX-Utils nor the names of its contributors
016: * may be used to endorse or promote products derived from this
017: * software without specific prior written permission.
018: *
019: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
023: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
024: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
025: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
026: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
027: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
029: * POSSIBILITY OF SUCH DAMAGE.
030: *
031: */
032: package javanet.staxutils;
033:
034: import java.util.ArrayList;
035: import java.util.Collection;
036: import java.util.Iterator;
037: import javax.xml.namespace.NamespaceContext;
038: import javax.xml.namespace.QName;
039: import javax.xml.stream.XMLEventFactory;
040: import javax.xml.stream.XMLEventWriter;
041: import javax.xml.stream.XMLStreamException;
042: import javax.xml.stream.XMLStreamWriter;
043: import javax.xml.stream.events.EndElement;
044: import javax.xml.stream.events.Namespace;
045: import javax.xml.stream.events.StartElement;
046:
047: /**
048: * An {@link javax.xml.stream.XMLStreamWriter} that writes events to a
049: * {@link javax.xml.stream.XMLEventWriter}.
050: *
051: * @author <a href="mailto:jk2006@engineer.com">John Kristian</a>
052: */
053: public class XMLEventStreamWriter implements XMLStreamWriter {
054:
055: public XMLEventStreamWriter(XMLEventWriter out) {
056: this (out, XMLEventFactory.newInstance());
057: }
058:
059: public XMLEventStreamWriter(XMLEventWriter out,
060: XMLEventFactory factory) {
061: this .out = out;
062: this .factory = factory;
063: }
064:
065: private XMLEventWriter out;
066:
067: private XMLEventFactory factory;
068:
069: private static final String DEFAULT_ENCODING = "UTF-8";
070:
071: /** The number of elements that have been started but not ended. */
072: private int depth = 0;
073:
074: /**
075: * Markup that matches previously started elements. stack[depth - 1] matches
076: * the element that was started most recently.
077: */
078: private EndElement[] stack = { null, null, null, null };
079:
080: private void write(StartElement start) throws XMLStreamException {
081: if (stack.length <= depth) {
082: // Grow the stack:
083: EndElement[] newStack = new EndElement[stack.length * 2];
084: System.arraycopy(stack, 0, newStack, 0, stack.length);
085: stack = newStack;
086: }
087: out.add(start);
088: // If that succeeded:
089: stack[depth++] = factory
090: .createEndElement(start.getName(), null);
091: }
092:
093: private void write(Namespace space) throws XMLStreamException {
094: EndElement end;
095: {
096: Collection spaces = new ArrayList();
097: EndElement oldEnd = stack[depth - 1];
098: Iterator oldSpaces = oldEnd.getNamespaces();
099: if (oldSpaces != null) {
100: while (oldSpaces.hasNext()) {
101: spaces.add(oldSpaces.next());
102: }
103: }
104: spaces.add(space);
105: end = factory.createEndElement(oldEnd.getName(), spaces
106: .iterator());
107: }
108: out.add(space);
109: // If that succeeded:
110: stack[depth - 1] = end;
111: }
112:
113: public Object getProperty(String name)
114: throws IllegalArgumentException {
115: throw new IllegalArgumentException(); // not supported
116: }
117:
118: public void setNamespaceContext(NamespaceContext context)
119: throws XMLStreamException {
120: out.setNamespaceContext(context);
121: }
122:
123: public NamespaceContext getNamespaceContext() {
124: return out.getNamespaceContext();
125: }
126:
127: public void setDefaultNamespace(String uri)
128: throws XMLStreamException {
129: out.setDefaultNamespace(uri);
130: }
131:
132: public String getPrefix(String uri) throws XMLStreamException {
133: return out.getPrefix(uri);
134: }
135:
136: public void setPrefix(String prefix, String uri)
137: throws XMLStreamException {
138: out.setPrefix(prefix, uri);
139: }
140:
141: public void writeStartDocument() throws XMLStreamException {
142: out.add(factory.createStartDocument(DEFAULT_ENCODING));
143: }
144:
145: public void writeStartDocument(String version)
146: throws XMLStreamException {
147: writeStartDocument(DEFAULT_ENCODING, version);
148: }
149:
150: public void writeStartDocument(String encoding, String version)
151: throws XMLStreamException {
152: out.add(factory.createStartDocument(encoding, version));
153: }
154:
155: public void writeDTD(String dtd) throws XMLStreamException {
156: out.add(factory.createDTD(dtd));
157: }
158:
159: public void writeComment(String data) throws XMLStreamException {
160: out.add(factory.createComment(data));
161: }
162:
163: public void writeProcessingInstruction(String target)
164: throws XMLStreamException {
165: writeProcessingInstruction(target, "");
166: }
167:
168: public void writeProcessingInstruction(String target, String data)
169: throws XMLStreamException {
170: out.add(factory.createProcessingInstruction(target, data));
171: }
172:
173: public void writeEmptyElement(String localName)
174: throws XMLStreamException {
175: writeStartElement(localName);
176: writeEndElement();
177: }
178:
179: public void writeEmptyElement(String namespaceURI, String localName)
180: throws XMLStreamException {
181: writeStartElement(namespaceURI, localName);
182: writeEndElement();
183: }
184:
185: public void writeEmptyElement(String prefix, String localName,
186: String namespaceURI) throws XMLStreamException {
187: writeStartElement(prefix, localName, namespaceURI);
188: writeEndElement();
189: }
190:
191: public void writeStartElement(String localName)
192: throws XMLStreamException {
193: write(factory.createStartElement(new QName(localName), null,
194: null));
195: }
196:
197: public void writeStartElement(String namespaceURI, String localName)
198: throws XMLStreamException {
199: write(factory.createStartElement(new QName(namespaceURI,
200: localName), null, null));
201: }
202:
203: public void writeStartElement(String prefix, String localName,
204: String namespaceURI) throws XMLStreamException {
205: write(factory.createStartElement(new QName(namespaceURI,
206: localName, prefix), null, null));
207: }
208:
209: public void writeAttribute(String localName, String value)
210: throws XMLStreamException {
211: out.add(factory.createAttribute(localName, value));
212: }
213:
214: public void writeAttribute(String namespaceURI, String localName,
215: String value) throws XMLStreamException {
216: out.add(factory.createAttribute(new QName(namespaceURI,
217: localName), value));
218: }
219:
220: public void writeAttribute(String prefix, String namespaceURI,
221: String localName, String value) throws XMLStreamException {
222: out.add(factory.createAttribute(prefix, namespaceURI,
223: localName, value));
224: }
225:
226: public void writeDefaultNamespace(String namespaceURI)
227: throws XMLStreamException {
228: write(factory.createNamespace(namespaceURI));
229: }
230:
231: public void writeNamespace(String prefix, String namespaceURI)
232: throws XMLStreamException {
233: write(factory.createNamespace(prefix, namespaceURI));
234: }
235:
236: public void writeCharacters(String text) throws XMLStreamException {
237: out.add(factory.createCharacters(text));
238: }
239:
240: public void writeCharacters(char[] text, int start, int len)
241: throws XMLStreamException {
242: writeCharacters(new String(text, start, len));
243: }
244:
245: public void writeCData(String data) throws XMLStreamException {
246: out.add(factory.createCData(data));
247: }
248:
249: public void writeEntityRef(String name) throws XMLStreamException {
250: out
251: .add(factory
252: .createEntityReference(name, null /* EventDeclaration */));
253: }
254:
255: public void writeEndElement() throws XMLStreamException {
256: if (depth <= 0) { // erroneous
257: // Let this.out throw the exception:
258: out.add(factory
259: .createEndElement(new QName("unknown"), null));
260: } else {
261: out.add(stack[depth - 1]);
262: // If that succeeded:
263: --depth;
264: stack[depth] = null; // to enable garbage collection
265: }
266: }
267:
268: public void writeEndDocument() throws XMLStreamException {
269: try {
270: while (depth > 0) {
271: writeEndElement();
272: }
273: } catch (Exception ignored) {
274: }
275: out.add(factory.createEndDocument());
276: // If that succeeded:
277: depth = 0;
278: }
279:
280: public void flush() throws XMLStreamException {
281: out.flush();
282: }
283:
284: public void close() throws XMLStreamException {
285: out.close();
286: }
287:
288: }
|