View Javadoc
1   /*
2    * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package javax.xml.transform.stax;
27  
28  import javax.xml.stream.XMLEventReader;
29  import javax.xml.stream.XMLStreamConstants;
30  import javax.xml.stream.XMLStreamException;
31  import javax.xml.stream.XMLStreamReader;
32  import javax.xml.stream.events.XMLEvent;
33  import javax.xml.transform.Source;
34  
35  /**
36   * <p>Acts as a holder for an XML {@link Source} in the
37   * form of a StAX reader,i.e.
38   * {@link XMLStreamReader} or {@link XMLEventReader}.
39   * <code>StAXSource</code> can be used in all cases that accept
40   * a <code>Source</code>, e.g. {@link javax.xml.transform.Transformer},
41   * {@link javax.xml.validation.Validator} which accept
42   * <code>Source</code> as input.
43   *
44   * <p><code>StAXSource</code>s are consumed during processing
45   * and are not reusable.</p>
46   *
47   * @author <a href="mailto:Neeraj.Bajaj@Sun.com">Neeraj Bajaj</a>
48   * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
49   *
50   * @see <a href="http://jcp.org/en/jsr/detail?id=173">
51   *  JSR 173: Streaming API for XML</a>
52   * @see XMLStreamReader
53   * @see XMLEventReader
54   *
55   * @since 1.6
56   */
57  public class StAXSource implements Source {
58  
59      /** If {@link javax.xml.transform.TransformerFactory#getFeature(String name)}
60       * returns true when passed this value as an argument,
61       * the Transformer supports Source input of this type.
62       */
63      public static final String FEATURE =
64          "http://javax.xml.transform.stax.StAXSource/feature";
65  
66      /** <p><code>XMLEventReader</code> to be used for source input.</p> */
67      private XMLEventReader xmlEventReader = null;
68  
69      /** <p><code>XMLStreamReader</code> to be used for source input.</p> */
70      private XMLStreamReader xmlStreamReader = null;
71  
72      /** <p>System identifier of source input.</p> */
73      private String systemId = null;
74  
75      /**
76       * <p>Creates a new instance of a <code>StAXSource</code>
77       * by supplying an {@link XMLEventReader}.</p>
78       *
79       * <p><code>XMLEventReader</code> must be a
80       * non-<code>null</code> reference.</p>
81       *
82       * <p><code>XMLEventReader</code> must be in
83       * {@link XMLStreamConstants#START_DOCUMENT} or
84       * {@link XMLStreamConstants#START_ELEMENT} state.</p>
85       *
86       * @param xmlEventReader <code>XMLEventReader</code> used to create
87       *   this <code>StAXSource</code>.
88       *
89       * @throws XMLStreamException If <code>xmlEventReader</code> access
90       *   throws an <code>Exception</code>.
91       * @throws IllegalArgumentException If <code>xmlEventReader</code> ==
92       *   <code>null</code>.
93       * @throws IllegalStateException If <code>xmlEventReader</code>
94       *   is not in <code>XMLStreamConstants.START_DOCUMENT</code> or
95       *   <code>XMLStreamConstants.START_ELEMENT</code> state.
96       */
97      public StAXSource(final XMLEventReader xmlEventReader)
98          throws XMLStreamException {
99  
100         if (xmlEventReader == null) {
101             throw new IllegalArgumentException(
102                     "StAXSource(XMLEventReader) with XMLEventReader == null");
103         }
104 
105         // TODO: This is ugly ...
106         // there is no way to know the current position(event) of
107         // XMLEventReader.  peek() is the only way to know the next event.
108         // The next event on the input stream should be
109         // XMLStreamConstants.START_DOCUMENT or
110         // XMLStreamConstants.START_ELEMENT.
111         XMLEvent event = xmlEventReader.peek();
112         int eventType = event.getEventType();
113         if (eventType != XMLStreamConstants.START_DOCUMENT
114                 && eventType != XMLStreamConstants.START_ELEMENT) {
115             throw new IllegalStateException(
116                 "StAXSource(XMLEventReader) with XMLEventReader "
117                 + "not in XMLStreamConstants.START_DOCUMENT or "
118                 + "XMLStreamConstants.START_ELEMENT state");
119         }
120 
121         this.xmlEventReader = xmlEventReader;
122         systemId = event.getLocation().getSystemId();
123     }
124 
125     /**
126      * <p>Creates a new instance of a <code>StAXSource</code>
127      * by supplying an {@link XMLStreamReader}.</p>
128      *
129      * <p><code>XMLStreamReader</code> must be a
130      * non-<code>null</code> reference.</p>
131      *
132      * <p><code>XMLStreamReader</code> must be in
133      * {@link XMLStreamConstants#START_DOCUMENT} or
134      * {@link XMLStreamConstants#START_ELEMENT} state.</p>
135      *
136      * @param xmlStreamReader <code>XMLStreamReader</code> used to create
137      *   this <code>StAXSource</code>.
138      *
139      * @throws IllegalArgumentException If <code>xmlStreamReader</code> ==
140      *   <code>null</code>.
141      * @throws IllegalStateException If <code>xmlStreamReader</code>
142      *   is not in <code>XMLStreamConstants.START_DOCUMENT</code> or
143      *   <code>XMLStreamConstants.START_ELEMENT</code> state.
144      */
145     public StAXSource(final XMLStreamReader xmlStreamReader) {
146 
147         if (xmlStreamReader == null) {
148             throw new IllegalArgumentException(
149                     "StAXSource(XMLStreamReader) with XMLStreamReader == null");
150         }
151 
152         int eventType = xmlStreamReader.getEventType();
153         if (eventType != XMLStreamConstants.START_DOCUMENT
154                 && eventType != XMLStreamConstants.START_ELEMENT) {
155             throw new IllegalStateException(
156                     "StAXSource(XMLStreamReader) with XMLStreamReader"
157                     + "not in XMLStreamConstants.START_DOCUMENT or "
158                     + "XMLStreamConstants.START_ELEMENT state");
159         }
160 
161         this.xmlStreamReader = xmlStreamReader;
162         systemId = xmlStreamReader.getLocation().getSystemId();
163     }
164 
165     /**
166      * <p>Get the <code>XMLEventReader</code> used by this
167      * <code>StAXSource</code>.</p>
168      *
169      * <p><code>XMLEventReader</code> will be <code>null</code>.
170      * if this <code>StAXSource</code> was created with a
171      * <code>XMLStreamReader</code>.</p>
172      *
173      * @return <code>XMLEventReader</code> used by this
174      *   <code>StAXSource</code>.
175      */
176     public XMLEventReader getXMLEventReader() {
177 
178         return xmlEventReader;
179     }
180 
181     /**
182      * <p>Get the <code>XMLStreamReader</code> used by this
183      * <code>StAXSource</code>.</p>
184      *
185      * <p><code>XMLStreamReader</code> will be <code>null</code>
186      * if this <code>StAXSource</code> was created with a
187      * <code>XMLEventReader</code>.</p>
188      *
189      * @return <code>XMLStreamReader</code> used by this
190      *   <code>StAXSource</code>.
191      */
192     public XMLStreamReader getXMLStreamReader() {
193 
194         return xmlStreamReader;
195     }
196 
197     /**
198      * <p>In the context of a <code>StAXSource</code>, it is not appropriate
199      * to explicitly set the system identifier.
200      * The <code>XMLStreamReader</code> or <code>XMLEventReader</code>
201      * used to construct this <code>StAXSource</code> determines the
202      * system identifier of the XML source.</p>
203      *
204      * <p>An {@link UnsupportedOperationException} is <strong>always</strong>
205      * thrown by this method.</p>
206      *
207      * @param systemId Ignored.
208      *
209      * @throws UnsupportedOperationException Is <strong>always</strong>
210      *   thrown by this method.
211      */
212     public void setSystemId(final String systemId) {
213 
214         throw new UnsupportedOperationException(
215                 "StAXSource#setSystemId(systemId) cannot set the "
216                 + "system identifier for a StAXSource");
217     }
218 
219     /**
220      * <p>Get the system identifier used by this
221      * <code>StAXSource</code>.</p>
222      *
223      * <p>The <code>XMLStreamReader</code> or <code>XMLEventReader</code>
224      * used to construct this <code>StAXSource</code> is queried to determine
225      * the system identifier of the XML source.</p>
226      *
227      * <p>The system identifier may be <code>null</code> or
228      * an empty <code>""</code> <code>String</code>.</p>
229      *
230      * @return System identifier used by this <code>StAXSource</code>.
231      */
232     public String getSystemId() {
233 
234         return systemId;
235     }
236 }