001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.xml;
014
015import static org.apache.juneau.common.internal.ThrowableUtils.*;
016
017import java.io.*;
018
019import javax.xml.namespace.*;
020import javax.xml.stream.*;
021import javax.xml.stream.util.*;
022
023import org.apache.juneau.parser.*;
024
025/**
026 * Wrapper class around a {@link XMLStreamReader}.
027 *
028 * <p>
029 * The purpose is to encapsulate the reader with the {@link ParserPipe} object so that it can be retrieved for
030 * debugging purposes.
031 *
032 * <h5 class='section'>See Also:</h5><ul>
033 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlDetails">XML Details</a>
034 * </ul>
035 */
036public final class XmlReader implements XMLStreamReader, Positionable {
037
038   private final ParserPipe pipe;
039   private final XMLStreamReader sr;
040
041   /**
042    * Constructor.
043    *
044    * @param pipe The parser input.
045    * @param validating The value for the {@link XMLInputFactory#IS_VALIDATING} setting.
046    * @param reporter The value for the {@link XMLInputFactory#REPORTER} setting.
047    * @param resolver The value for the {@link XMLInputFactory#RESOLVER} setting.
048    * @param eventAllocator The value for the {@link XMLInputFactory#ALLOCATOR} setting.
049    * @throws IOException Thrown by underling
050    * @throws XMLStreamException Thrown by underlying XML stream.
051    */
052   protected XmlReader(ParserPipe pipe, boolean validating, XMLReporter reporter, XMLResolver resolver, XMLEventAllocator eventAllocator) throws IOException, XMLStreamException {
053      this.pipe = pipe;
054      try {
055         @SuppressWarnings("resource")
056         Reader r = pipe.getBufferedReader();
057         XMLInputFactory factory = XMLInputFactory.newInstance();
058         factory.setProperty(XMLInputFactory.IS_VALIDATING, validating);
059         factory.setProperty(XMLInputFactory.IS_COALESCING, true);
060         factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
061         factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
062         if (factory.isPropertySupported(XMLInputFactory.REPORTER) && reporter != null)
063            factory.setProperty(XMLInputFactory.REPORTER, reporter);
064         if (factory.isPropertySupported(XMLInputFactory.RESOLVER) && resolver != null)
065            factory.setProperty(XMLInputFactory.RESOLVER, resolver);
066         if (factory.isPropertySupported(XMLInputFactory.ALLOCATOR) && eventAllocator != null)
067            factory.setProperty(XMLInputFactory.ALLOCATOR, eventAllocator);
068         sr = factory.createXMLStreamReader(r);
069         sr.nextTag();
070         pipe.setPositionable(this);
071      } catch (Error e) {
072         throw cast(IOException.class, e);
073      }
074   }
075
076   /**
077    * Returns the pipe passed into the constructor.
078    *
079    * @return The pipe passed into the constructor.
080    */
081   public ParserPipe getPipe() {
082      return pipe;
083   }
084
085   @Override /* XMLStreamReader */
086   public void close() throws XMLStreamException {
087      sr.close();
088   }
089
090   @Override /* XMLStreamReader */
091   public int getAttributeCount() {
092      return sr.getAttributeCount();
093   }
094
095   @Override /* XMLStreamReader */
096   public String getAttributeLocalName(int index) {
097      return sr.getAttributeLocalName(index);
098   }
099
100   @Override /* XMLStreamReader */
101   public QName getAttributeName(int index) {
102      return sr.getAttributeName(index);
103   }
104
105   @Override /* XMLStreamReader */
106   public String getAttributeNamespace(int index) {
107      return sr.getAttributeNamespace(index);
108   }
109
110   @Override /* XMLStreamReader */
111   public String getAttributePrefix(int index) {
112      return sr.getAttributePrefix(index);
113   }
114
115   @Override /* XMLStreamReader */
116   public String getAttributeType(int index) {
117      return sr.getAttributeType(index);
118   }
119
120   @Override /* XMLStreamReader */
121   public String getAttributeValue(int index) {
122      return sr.getAttributeValue(index);
123   }
124
125   @Override /* XMLStreamReader */
126   public String getAttributeValue(String namespaceURI, String localName) {
127      return sr.getAttributeValue(namespaceURI, localName);
128   }
129
130   @Override /* XMLStreamReader */
131   public String getCharacterEncodingScheme() {
132      return sr.getCharacterEncodingScheme();
133   }
134
135   @Override /* XMLStreamReader */
136   public String getElementText() throws XMLStreamException {
137      return sr.getElementText();
138   }
139
140   @Override /* XMLStreamReader */
141   public String getEncoding() {
142      return sr.getEncoding();
143   }
144
145   @Override /* XMLStreamReader */
146   public int getEventType() {
147      return sr.getEventType();
148   }
149
150   @Override /* XMLStreamReader */
151   public String getLocalName() {
152      return sr.getLocalName();
153   }
154
155   @Override /* XMLStreamReader */
156   public Location getLocation() {
157      return sr.getLocation();
158   }
159
160   @Override /* XMLStreamReader */
161   public QName getName() {
162      return sr.getName();
163   }
164
165   @Override /* XMLStreamReader */
166   public NamespaceContext getNamespaceContext() {
167      return sr.getNamespaceContext();
168   }
169
170   @Override /* XMLStreamReader */
171   public int getNamespaceCount() {
172      return sr.getNamespaceCount();
173   }
174
175   @Override /* XMLStreamReader */
176   public String getNamespacePrefix(int index) {
177      return sr.getNamespacePrefix(index);
178   }
179
180   @Override /* XMLStreamReader */
181   public String getNamespaceURI() {
182      return sr.getNamespaceURI();
183   }
184
185   @Override /* XMLStreamReader */
186   public String getNamespaceURI(String prefix) {
187      return sr.getNamespaceURI(prefix);
188   }
189
190   @Override /* XMLStreamReader */
191   public String getNamespaceURI(int index) {
192      return sr.getNamespaceURI(index);
193   }
194
195   @Override /* XMLStreamReader */
196   public String getPIData() {
197      return sr.getPIData();
198   }
199
200   @Override /* XMLStreamReader */
201   public String getPITarget() {
202      return sr.getPITarget();
203   }
204
205   @Override /* XMLStreamReader */
206   public String getPrefix() {
207      return sr.getPrefix();
208   }
209
210   @Override /* XMLStreamReader */
211   public Object getProperty(String name) throws IllegalArgumentException {
212      return sr.getProperty(name);
213   }
214
215   @Override /* XMLStreamReader */
216   public String getText() {
217      return sr.getText();
218   }
219
220   @Override /* XMLStreamReader */
221   public char[] getTextCharacters() {
222      return sr.getTextCharacters();
223   }
224
225   @Override /* XMLStreamReader */
226   public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) throws XMLStreamException {
227      return sr.getTextCharacters(sourceStart, target, targetStart, length);
228   }
229
230   @Override /* XMLStreamReader */
231   public int getTextLength() {
232      return sr.getTextLength();
233   }
234
235   @Override /* XMLStreamReader */
236   public int getTextStart() {
237      return sr.getTextStart();
238   }
239
240   @Override /* XMLStreamReader */
241   public String getVersion() {
242      return sr.getVersion();
243   }
244
245   @Override /* XMLStreamReader */
246   public boolean hasName() {
247      return sr.hasName();
248   }
249
250   @Override /* XMLStreamReader */
251   public boolean hasNext() throws XMLStreamException {
252      return sr.hasNext();
253   }
254
255   @Override /* XMLStreamReader */
256   public boolean hasText() {
257      return sr.hasText();
258   }
259
260   @Override /* XMLStreamReader */
261   public boolean isAttributeSpecified(int index) {
262      return sr.isAttributeSpecified(index);
263   }
264
265   @Override /* XMLStreamReader */
266   public boolean isCharacters() {
267      return sr.isCharacters();
268   }
269
270   @Override /* XMLStreamReader */
271   public boolean isEndElement() {
272      return sr.isEndElement();
273   }
274
275   @Override /* XMLStreamReader */
276   public boolean isStandalone() {
277      return sr.isStandalone();
278   }
279
280   @Override /* XMLStreamReader */
281   public boolean isStartElement() {
282      return sr.isStartElement();
283   }
284
285   @Override /* XMLStreamReader */
286   public boolean isWhiteSpace() {
287      return sr.isWhiteSpace();
288   }
289
290   @Override /* XMLStreamReader */
291   public int next() throws XMLStreamException {
292      return sr.next();
293   }
294
295   @Override /* XMLStreamReader */
296   public int nextTag() throws XMLStreamException {
297      return sr.nextTag();
298   }
299
300   @Override /* XMLStreamReader */
301   public void require(int type, String namespaceURI, String localName) throws XMLStreamException {
302      sr.require(type, namespaceURI, localName);
303   }
304
305   @Override /* XMLStreamReader */
306   public boolean standaloneSet() {
307      return sr.standaloneSet();
308   }
309
310   @Override /* Positionable */
311   public Position getPosition() {
312      Location l = getLocation();
313      return new Position(l.getLineNumber(), l.getColumnNumber());
314   }
315}