1 /* 2 * Copyright (c) 2005, 2016, 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 Neeraj Bajaj 48 * @author Jeff Suttor 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 @Override 213 public void setSystemId(final String systemId) { 214 215 throw new UnsupportedOperationException( 216 "StAXSource#setSystemId(systemId) cannot set the " 217 + "system identifier for a StAXSource"); 218 } 219 220 /** 221 * <p>Get the system identifier used by this 222 * <code>StAXSource</code>.</p> 223 * 224 * <p>The <code>XMLStreamReader</code> or <code>XMLEventReader</code> 225 * used to construct this <code>StAXSource</code> is queried to determine 226 * the system identifier of the XML source.</p> 227 * 228 * <p>The system identifier may be <code>null</code> or 229 * an empty <code>""</code> <code>String</code>.</p> 230 * 231 * @return System identifier used by this <code>StAXSource</code>. 232 */ 233 @Override 234 public String getSystemId() { 235 236 return systemId; 237 } 238 239 /** 240 * Indicates whether the {@code StAXSource} object is empty. Since a 241 * {@code StAXSource} object can never be empty, this method always returns 242 * false. 243 * 244 * @return unconditionally false 245 */ 246 @Override 247 public boolean isEmpty() { 248 return false; 249 } 250 }