1 /*
2  * Copyright 2002-2010 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.util.xml;
18 
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import javax.xml.namespace.NamespaceContext;
23 import javax.xml.namespace.QName;
24 import javax.xml.stream.XMLEventFactory;
25 import javax.xml.stream.XMLEventWriter;
26 import javax.xml.stream.XMLStreamException;
27 import javax.xml.stream.XMLStreamWriter;
28 import javax.xml.stream.events.EndElement;
29 import javax.xml.stream.events.Namespace;
30 import javax.xml.stream.events.StartElement;
31 
32 import org.springframework.util.Assert;
33 
34 /**
35  * Implementation of the {@link javax.xml.stream.XMLStreamWriter} interface that wraps a {@link XMLEventWriter}.
36  *
37  * @author Arjen Poutsma
38  * @since 3.0.5
39  * @see StaxUtils#createEventStreamWriter(javax.xml.stream.XMLEventWriter, javax.xml.stream.XMLEventFactory)
40  */
41 class XMLEventStreamWriter implements XMLStreamWriter {
42 
43 	private static final String DEFAULT_ENCODING = "UTF-8";
44 
45 	private final XMLEventWriter eventWriter;
46 
47 	private final XMLEventFactory eventFactory;
48 
49 	private List<EndElement> endElements = new ArrayList<EndElement>();
50 
XMLEventStreamWriter(XMLEventWriter eventWriter, XMLEventFactory eventFactory)51 	public XMLEventStreamWriter(XMLEventWriter eventWriter, XMLEventFactory eventFactory) {
52 		Assert.notNull(eventWriter, "'eventWriter' must not be null");
53 		Assert.notNull(eventFactory, "'eventFactory' must not be null");
54 
55 		this.eventWriter = eventWriter;
56 		this.eventFactory = eventFactory;
57 	}
58 
getNamespaceContext()59 	public NamespaceContext getNamespaceContext() {
60 		return eventWriter.getNamespaceContext();
61 	}
62 
getPrefix(String uri)63 	public String getPrefix(String uri) throws XMLStreamException {
64 		return eventWriter.getPrefix(uri);
65 	}
66 
setPrefix(String prefix, String uri)67 	public void setPrefix(String prefix, String uri) throws XMLStreamException {
68 		eventWriter.setPrefix(prefix, uri);
69 	}
70 
setDefaultNamespace(String uri)71 	public void setDefaultNamespace(String uri) throws XMLStreamException {
72 		eventWriter.setDefaultNamespace(uri);
73 	}
74 
setNamespaceContext(NamespaceContext context)75 	public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
76 		eventWriter.setNamespaceContext(context);
77 	}
78 
writeStartDocument()79 	public void writeStartDocument() throws XMLStreamException {
80 		eventWriter.add(eventFactory.createStartDocument());
81 	}
82 
writeStartDocument(String version)83 	public void writeStartDocument(String version) throws XMLStreamException {
84 		eventWriter.add(eventFactory.createStartDocument(DEFAULT_ENCODING, version));
85 	}
86 
writeStartDocument(String encoding, String version)87 	public void writeStartDocument(String encoding, String version) throws XMLStreamException {
88 		eventWriter.add(eventFactory.createStartDocument(encoding, version));
89 	}
90 
writeStartElement(String localName)91 	public void writeStartElement(String localName) throws XMLStreamException {
92 		writeStartElement(eventFactory.createStartElement(new QName(localName), null, null));
93 	}
94 
writeStartElement(String namespaceURI, String localName)95 	public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
96 		writeStartElement(eventFactory.createStartElement(new QName(namespaceURI, localName), null, null));
97 	}
98 
writeStartElement(String prefix, String localName, String namespaceURI)99 	public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
100 		writeStartElement(eventFactory.createStartElement(new QName(namespaceURI, localName, prefix), null, null));
101 	}
102 
writeEmptyElement(String localName)103 	public void writeEmptyElement(String localName) throws XMLStreamException {
104 		writeStartElement(localName);
105 		writeEndElement();
106 	}
107 
writeEmptyElement(String namespaceURI, String localName)108 	public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
109 		writeStartElement(namespaceURI, localName);
110 		writeEndElement();
111 	}
112 
writeEmptyElement(String prefix, String localName, String namespaceURI)113 	public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
114 		writeStartElement(prefix, localName, namespaceURI);
115 		writeEndElement();
116 	}
117 
writeEndElement()118 	public void writeEndElement() throws XMLStreamException {
119 		int last = endElements.size() - 1;
120 		EndElement lastEndElement = endElements.get(last);
121 		eventWriter.add(lastEndElement);
122 		endElements.remove(last);
123 	}
124 
writeAttribute(String localName, String value)125 	public void writeAttribute(String localName, String value) throws XMLStreamException {
126 		eventWriter.add(eventFactory.createAttribute(localName, value));
127 	}
128 
writeAttribute(String namespaceURI, String localName, String value)129 	public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
130 		eventWriter.add(eventFactory.createAttribute(new QName(namespaceURI, localName), value));
131 	}
132 
writeAttribute(String prefix, String namespaceURI, String localName, String value)133 	public void writeAttribute(String prefix, String namespaceURI, String localName, String value)
134 			throws XMLStreamException {
135 		eventWriter.add(eventFactory.createAttribute(prefix, namespaceURI, localName, value));
136 	}
137 
writeNamespace(String prefix, String namespaceURI)138 	public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
139 		writeNamespace(eventFactory.createNamespace(prefix, namespaceURI));
140 	}
141 
writeDefaultNamespace(String namespaceURI)142 	public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
143 		writeNamespace(eventFactory.createNamespace(namespaceURI));
144 	}
145 
writeCharacters(String text)146 	public void writeCharacters(String text) throws XMLStreamException {
147 		eventWriter.add(eventFactory.createCharacters(text));
148 	}
149 
writeCharacters(char[] text, int start, int len)150 	public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
151 		eventWriter.add(eventFactory.createCharacters(new String(text, start, len)));
152 	}
153 
writeCData(String data)154 	public void writeCData(String data) throws XMLStreamException {
155 		eventWriter.add(eventFactory.createCData(data));
156 	}
157 
writeComment(String data)158 	public void writeComment(String data) throws XMLStreamException {
159 		eventWriter.add(eventFactory.createComment(data));
160 	}
161 
writeProcessingInstruction(String target)162 	public void writeProcessingInstruction(String target) throws XMLStreamException {
163 		eventWriter.add(eventFactory.createProcessingInstruction(target, ""));
164 	}
165 
writeProcessingInstruction(String target, String data)166 	public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
167 		eventWriter.add(eventFactory.createProcessingInstruction(target, data));
168 	}
169 
writeDTD(String dtd)170 	public void writeDTD(String dtd) throws XMLStreamException {
171 		eventWriter.add(eventFactory.createDTD(dtd));
172 	}
173 
writeEntityRef(String name)174 	public void writeEntityRef(String name) throws XMLStreamException {
175 		eventWriter.add(eventFactory.createEntityReference(name, null));
176 	}
177 
writeEndDocument()178 	public void writeEndDocument() throws XMLStreamException {
179 		eventWriter.add(eventFactory.createEndDocument());
180 	}
181 
getProperty(String name)182 	public Object getProperty(String name) throws IllegalArgumentException {
183 		throw new IllegalArgumentException();
184 	}
185 
flush()186 	public void flush() throws XMLStreamException {
187 		eventWriter.flush();
188 	}
189 
close()190 	public void close() throws XMLStreamException {
191 		eventWriter.close();
192 	}
193 
writeStartElement(StartElement startElement)194 	private void writeStartElement(StartElement startElement) throws XMLStreamException {
195 		eventWriter.add(startElement);
196 		endElements.add(eventFactory.createEndElement(startElement.getName(), null));
197 	}
198 
writeNamespace(Namespace namespace)199 	private void writeNamespace(Namespace namespace) throws XMLStreamException {
200 		int last = endElements.size() - 1;
201 		EndElement oldEndElement = endElements.get(last);
202 		Iterator oldNamespaces = oldEndElement.getNamespaces();
203 		List<Namespace> newNamespaces = new ArrayList<Namespace>();
204 		while (oldNamespaces.hasNext()) {
205 			Namespace oldNamespace = (Namespace) oldNamespaces.next();
206 			newNamespaces.add(oldNamespace);
207 		}
208 		newNamespaces.add(namespace);
209 		EndElement newEndElement = eventFactory.createEndElement(oldEndElement.getName(), newNamespaces.iterator());
210 		eventWriter.add(namespace);
211 		endElements.set(last, newEndElement);
212 	}
213 }
214