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