001/*
002 * Copyright 2002-2014 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.util.xml;
018
019import javax.xml.stream.XMLEventFactory;
020import javax.xml.stream.XMLEventReader;
021import javax.xml.stream.XMLEventWriter;
022import javax.xml.stream.XMLStreamException;
023import javax.xml.stream.XMLStreamReader;
024import javax.xml.stream.XMLStreamWriter;
025import javax.xml.transform.Result;
026import javax.xml.transform.Source;
027import javax.xml.transform.stax.StAXResult;
028import javax.xml.transform.stax.StAXSource;
029
030import org.xml.sax.ContentHandler;
031import org.xml.sax.XMLReader;
032
033/**
034 * Convenience methods for working with the StAX API. Partly historic due to JAXP 1.3 compatibility;
035 * as of Spring 4.0, relying on JAXP 1.4 as included in JDK 1.6 and higher.
036 *
037 * <p>In particular, methods for using StAX ({@code javax.xml.stream}) in combination with the TrAX API
038 * ({@code javax.xml.transform}), and converting StAX readers/writers into SAX readers/handlers and vice-versa.
039 *
040 * @author Arjen Poutsma
041 * @author Juergen Hoeller
042 * @since 3.0
043 */
044public abstract class StaxUtils {
045
046        /**
047         * Create a JAXP 1.4 {@link StAXSource} for the given {@link XMLStreamReader}.
048         * @param streamReader the StAX stream reader
049         * @return a source wrapping the {@code streamReader}
050         */
051        public static Source createStaxSource(XMLStreamReader streamReader) {
052                return new StAXSource(streamReader);
053        }
054
055        /**
056         * Create a JAXP 1.4 a {@link StAXSource} for the given {@link XMLEventReader}.
057         * @param eventReader the StAX event reader
058         * @return a source wrapping the {@code eventReader}
059         */
060        public static Source createStaxSource(XMLEventReader eventReader) throws XMLStreamException {
061                return new StAXSource(eventReader);
062        }
063
064        /**
065         * Create a custom, non-JAXP 1.4 StAX {@link Source} for the given {@link XMLStreamReader}.
066         * @param streamReader the StAX stream reader
067         * @return a source wrapping the {@code streamReader}
068         */
069        public static Source createCustomStaxSource(XMLStreamReader streamReader) {
070                return new StaxSource(streamReader);
071        }
072
073        /**
074         * Create a custom, non-JAXP 1.4 StAX {@link Source} for the given {@link XMLEventReader}.
075         * @param eventReader the StAX event reader
076         * @return a source wrapping the {@code eventReader}
077         */
078        public static Source createCustomStaxSource(XMLEventReader eventReader) {
079                return new StaxSource(eventReader);
080        }
081
082        /**
083         * Indicate whether the given {@link Source} is a JAXP 1.4 StAX Source or
084         * custom StAX Source.
085         * @return {@code true} if {@code source} is a JAXP 1.4 {@link StAXSource} or
086         * custom StAX Source; {@code false} otherwise
087         */
088        public static boolean isStaxSource(Source source) {
089                return (source instanceof StAXSource || source instanceof StaxSource);
090        }
091
092        /**
093         * Return the {@link XMLStreamReader} for the given StAX Source.
094         * @param source a JAXP 1.4 {@link StAXSource}
095         * @return the {@link XMLStreamReader}
096         * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link StAXSource}
097         * or custom StAX Source
098         */
099        public static XMLStreamReader getXMLStreamReader(Source source) {
100                if (source instanceof StAXSource) {
101                        return ((StAXSource) source).getXMLStreamReader();
102                }
103                else if (source instanceof StaxSource) {
104                        return ((StaxSource) source).getXMLStreamReader();
105                }
106                else {
107                        throw new IllegalArgumentException("Source '" + source + "' is neither StaxSource nor StAXSource");
108                }
109        }
110
111        /**
112         * Return the {@link XMLEventReader} for the given StAX Source.
113         * @param source a JAXP 1.4 {@link StAXSource}
114         * @return the {@link XMLEventReader}
115         * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link StAXSource}
116         * or custom StAX Source
117         */
118        public static XMLEventReader getXMLEventReader(Source source) {
119                if (source instanceof StAXSource) {
120                        return ((StAXSource) source).getXMLEventReader();
121                }
122                else if (source instanceof StaxSource) {
123                        return ((StaxSource) source).getXMLEventReader();
124                }
125                else {
126                        throw new IllegalArgumentException("Source '" + source + "' is neither StaxSource nor StAXSource");
127                }
128        }
129
130        /**
131         * Create a JAXP 1.4 {@link StAXResult} for the given {@link XMLStreamWriter}.
132         * @param streamWriter the StAX stream writer
133         * @return a result wrapping the {@code streamWriter}
134         */
135        public static Result createStaxResult(XMLStreamWriter streamWriter) {
136                return new StAXResult(streamWriter);
137        }
138
139        /**
140         * Create a JAXP 1.4 {@link StAXResult} for the given {@link XMLEventWriter}.
141         * @param eventWriter the StAX event writer
142         * @return a result wrapping {@code streamReader}
143         */
144        public static Result createStaxResult(XMLEventWriter eventWriter) {
145                return new StAXResult(eventWriter);
146        }
147
148        /**
149         * Create a custom, non-JAXP 1.4 StAX {@link Result} for the given {@link XMLStreamWriter}.
150         * @param streamWriter the StAX stream writer
151         * @return a source wrapping the {@code streamWriter}
152         */
153        public static Result createCustomStaxResult(XMLStreamWriter streamWriter) {
154                return new StaxResult(streamWriter);
155        }
156
157        /**
158         * Create a custom, non-JAXP 1.4 StAX {@link Result} for the given {@link XMLEventWriter}.
159         * @param eventWriter the StAX event writer
160         * @return a source wrapping the {@code eventWriter}
161         */
162        public static Result createCustomStaxResult(XMLEventWriter eventWriter) {
163                return new StaxResult(eventWriter);
164        }
165
166        /**
167         * Indicate whether the given {@link Result} is a JAXP 1.4 StAX Result or
168         * custom StAX Result.
169         * @return {@code true} if {@code result} is a JAXP 1.4 {@link StAXResult} or
170         * custom StAX Result; {@code false} otherwise
171         */
172        public static boolean isStaxResult(Result result) {
173                return (result instanceof StAXResult || result instanceof StaxResult);
174        }
175
176        /**
177         * Return the {@link XMLStreamWriter} for the given StAX Result.
178         * @param result a JAXP 1.4 {@link StAXResult}
179         * @return the {@link XMLStreamReader}
180         * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link StAXResult}
181         * or custom StAX Result
182         */
183        public static XMLStreamWriter getXMLStreamWriter(Result result) {
184                if (result instanceof StAXResult) {
185                        return ((StAXResult) result).getXMLStreamWriter();
186                }
187                else if (result instanceof StaxResult) {
188                        return ((StaxResult) result).getXMLStreamWriter();
189                }
190                else {
191                        throw new IllegalArgumentException("Result '" + result + "' is neither StaxResult nor StAXResult");
192                }
193        }
194
195        /**
196         * Return the {@link XMLEventWriter} for the given StAX Result.
197         * @param result a JAXP 1.4 {@link StAXResult}
198         * @return the {@link XMLStreamReader}
199         * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link StAXResult}
200         * or custom StAX Result
201         */
202        public static XMLEventWriter getXMLEventWriter(Result result) {
203                if (result instanceof StAXResult) {
204                        return ((StAXResult) result).getXMLEventWriter();
205                }
206                else if (result instanceof StaxResult) {
207                        return ((StaxResult) result).getXMLEventWriter();
208                }
209                else {
210                        throw new IllegalArgumentException("Result '" + result + "' is neither StaxResult nor StAXResult");
211                }
212        }
213
214        /**
215         * Create a SAX {@link ContentHandler} that writes to the given StAX {@link XMLStreamWriter}.
216         * @param streamWriter the StAX stream writer
217         * @return a content handler writing to the {@code streamWriter}
218         */
219        public static ContentHandler createContentHandler(XMLStreamWriter streamWriter) {
220                return new StaxStreamHandler(streamWriter);
221        }
222
223        /**
224         * Create a SAX {@link ContentHandler} that writes events to the given StAX {@link XMLEventWriter}.
225         * @param eventWriter the StAX event writer
226         * @return a content handler writing to the {@code eventWriter}
227         */
228        public static ContentHandler createContentHandler(XMLEventWriter eventWriter) {
229                return new StaxEventHandler(eventWriter);
230        }
231
232        /**
233         * Create a SAX {@link XMLReader} that reads from the given StAX {@link XMLStreamReader}.
234         * @param streamReader the StAX stream reader
235         * @return a XMLReader reading from the {@code streamWriter}
236         */
237        public static XMLReader createXMLReader(XMLStreamReader streamReader) {
238                return new StaxStreamXMLReader(streamReader);
239        }
240
241        /**
242         * Create a SAX {@link XMLReader} that reads from the given StAX {@link XMLEventReader}.
243         * @param eventReader the StAX event reader
244         * @return a XMLReader reading from the {@code eventWriter}
245         */
246        public static XMLReader createXMLReader(XMLEventReader eventReader) {
247                return new StaxEventXMLReader(eventReader);
248        }
249
250        /**
251         * Return a {@link XMLStreamReader} that reads from a {@link XMLEventReader}.
252         * Useful because the StAX {@code XMLInputFactory} allows one to create an
253         * event reader from a stream reader, but not vice-versa.
254         * @return a stream reader that reads from an event reader
255         */
256        public static XMLStreamReader createEventStreamReader(XMLEventReader eventReader) throws XMLStreamException {
257                return new XMLEventStreamReader(eventReader);
258        }
259
260        /**
261         * Return a {@link XMLStreamWriter} that writes to a {@link XMLEventWriter}.
262         * @return a stream writer that writes to an event writer
263         * @since 3.2
264         */
265        public static XMLStreamWriter createEventStreamWriter(XMLEventWriter eventWriter) {
266                return new XMLEventStreamWriter(eventWriter, XMLEventFactory.newFactory());
267        }
268
269        /**
270         * Return a {@link XMLStreamWriter} that writes to a {@link XMLEventWriter}.
271         * @return a stream writer that writes to an event writer
272         * @since 3.0.5
273         */
274        public static XMLStreamWriter createEventStreamWriter(XMLEventWriter eventWriter, XMLEventFactory eventFactory) {
275                return new XMLEventStreamWriter(eventWriter, eventFactory);
276        }
277
278}