Thu, 31 Aug 2017 15:18:52 +0800
merge
1 /*
2 * Copyright (c) 1997, 2012, 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 */
26 package com.sun.xml.internal.ws.streaming;
28 import javax.xml.namespace.QName;
29 import static javax.xml.stream.XMLStreamConstants.*;
30 import javax.xml.stream.XMLStreamException;
31 import javax.xml.stream.XMLStreamReader;
32 import javax.xml.stream.XMLStreamConstants;
34 /**
35 * <p> XMLStreamReaderUtil provides some utility methods intended to be used
36 * in conjunction with a StAX XMLStreamReader. </p>
37 *
38 * @author WS Development Team
39 */
40 public class XMLStreamReaderUtil {
42 private XMLStreamReaderUtil() {
43 }
45 public static void close(XMLStreamReader reader) {
46 try {
47 reader.close();
48 } catch (XMLStreamException e) {
49 throw wrapException(e);
50 }
51 }
53 public static void readRest(XMLStreamReader reader) {
54 try {
55 while(reader.getEventType() != XMLStreamConstants.END_DOCUMENT) {
56 reader.next();
57 }
58 } catch (XMLStreamException e) {
59 throw wrapException(e);
60 }
61 }
63 public static int next(XMLStreamReader reader) {
64 try {
65 int readerEvent = reader.next();
67 while (readerEvent != END_DOCUMENT) {
68 switch (readerEvent) {
69 case START_ELEMENT:
70 case END_ELEMENT:
71 case CDATA:
72 case CHARACTERS:
73 case PROCESSING_INSTRUCTION:
74 return readerEvent;
75 default:
76 // falls through ignoring event
77 }
78 readerEvent = reader.next();
79 }
81 return readerEvent;
82 }
83 catch (XMLStreamException e) {
84 throw wrapException(e);
85 }
86 }
88 public static int nextElementContent(XMLStreamReader reader) {
89 int state = nextContent(reader);
90 if (state == CHARACTERS) {
91 throw new XMLStreamReaderException(
92 "xmlreader.unexpectedCharacterContent", reader.getText());
93 }
94 return state;
95 }
97 public static void toNextTag(XMLStreamReader reader, QName name) {
98 // skip any whitespace
99 if (reader.getEventType() != XMLStreamConstants.START_ELEMENT &&
100 reader.getEventType() != XMLStreamConstants.END_ELEMENT) {
101 XMLStreamReaderUtil.nextElementContent(reader);
102 }
103 if(reader.getEventType() == XMLStreamConstants.END_ELEMENT && name.equals(reader.getName())) {
104 XMLStreamReaderUtil.nextElementContent(reader);
105 }
106 }
108 /**
109 * Moves next and read spaces from the reader as long as to the next element.
110 * Comments are ignored
111 * @param reader
112 * @return
113 */
114 public static String nextWhiteSpaceContent(XMLStreamReader reader) {
115 next(reader);
116 return currentWhiteSpaceContent(reader);
117 }
119 /**
120 * Read spaces from the reader as long as to the next element, starting from
121 * current position. Comments are ignored.
122 * @param reader
123 * @return
124 */
125 public static String currentWhiteSpaceContent(XMLStreamReader reader) {
127 // since the there might be several valid chunks (spaces/comment/spaces)
128 // StringBuilder must be used; it's initialized lazily, only when needed
129 StringBuilder whiteSpaces = null;
131 for (;;) {
132 switch (reader.getEventType()) {
133 case START_ELEMENT:
134 case END_ELEMENT:
135 case END_DOCUMENT:
136 return whiteSpaces == null ? null : whiteSpaces.toString();
137 case CHARACTERS:
138 if (reader.isWhiteSpace()) {
139 if (whiteSpaces == null) {
140 whiteSpaces = new StringBuilder();
141 }
142 whiteSpaces.append(reader.getText());
143 } else {
144 throw new XMLStreamReaderException(
145 "xmlreader.unexpectedCharacterContent", reader.getText());
146 }
147 }
148 next(reader);
149 }
150 }
152 public static int nextContent(XMLStreamReader reader) {
153 for (;;) {
154 int state = next(reader);
155 switch (state) {
156 case START_ELEMENT:
157 case END_ELEMENT:
158 case END_DOCUMENT:
159 return state;
160 case CHARACTERS:
161 if (!reader.isWhiteSpace()) {
162 return CHARACTERS;
163 }
164 }
165 }
166 }
168 /**
169 * Skip current element, leaving the cursor at END_ELEMENT of
170 * current element.
171 */
172 public static void skipElement(XMLStreamReader reader) {
173 assert reader.getEventType() == START_ELEMENT;
174 skipTags(reader, true);
175 assert reader.getEventType() == END_ELEMENT;
176 }
178 /**
179 * Skip following siblings, leaving cursor at END_ELEMENT of
180 * parent element.
181 */
182 public static void skipSiblings(XMLStreamReader reader, QName parent) {
183 skipTags(reader, reader.getName().equals(parent));
184 assert reader.getEventType() == END_ELEMENT;
185 }
187 private static void skipTags(XMLStreamReader reader, boolean exitCondition) {
188 try {
189 int state, tags = 0;
190 while ((state = reader.next()) != END_DOCUMENT) {
191 if (state == START_ELEMENT) {
192 tags++;
193 }
194 else if (state == END_ELEMENT) {
195 if (tags == 0 && exitCondition) return;
196 tags--;
197 }
198 }
199 }
200 catch (XMLStreamException e) {
201 throw wrapException(e);
202 }
203 }
205 /*
206 * Get the text of an element
207 */
208 public static String getElementText(XMLStreamReader reader) {
209 try {
210 return reader.getElementText();
211 } catch (XMLStreamException e) {
212 throw wrapException(e);
213 }
214 }
216 /*
217 * Get a QName with 'someUri' and 'localname' from an
218 * element of qname type:
219 * <xyz xmlns:ns1="someUri">ns1:localname</xyz>
220 */
221 public static QName getElementQName(XMLStreamReader reader) {
222 try {
223 String text = reader.getElementText().trim();
224 String prefix = text.substring(0,text.indexOf(':'));
225 String namespaceURI = reader.getNamespaceContext().getNamespaceURI(prefix);
226 if (namespaceURI == null) {
227 namespaceURI = "";
228 }
229 String localPart = text.substring(
230 text.indexOf(':') + 1, text.length());
231 return new QName(namespaceURI, localPart);
232 } catch (XMLStreamException e) {
233 throw wrapException(e);
234 }
235 }
237 /**
238 * Read all attributes into an data structure. Note that this method cannot
239 * be called multiple times to get the same list of attributes.
240 */
241 public static Attributes getAttributes(XMLStreamReader reader) {
242 return (reader.getEventType() == START_ELEMENT ||
243 reader.getEventType() == ATTRIBUTE) ?
244 new AttributesImpl(reader) : null;
245 }
247 public static void verifyReaderState(XMLStreamReader reader, int expectedState) {
248 int state = reader.getEventType();
249 if (state != expectedState) {
250 throw new XMLStreamReaderException(
251 "xmlreader.unexpectedState",
252 getStateName(expectedState), getStateName(state));
253 }
254 }
256 public static void verifyTag(XMLStreamReader reader, String namespaceURI, String localName) {
257 if (!localName.equals(reader.getLocalName()) || !namespaceURI.equals(reader.getNamespaceURI())) {
258 throw new XMLStreamReaderException(
259 "xmlreader.unexpectedState.tag",
260 "{" + namespaceURI + "}" + localName,
261 "{" + reader.getNamespaceURI() + "}" + reader.getLocalName());
262 }
263 }
265 public static void verifyTag(XMLStreamReader reader, QName name) {
266 verifyTag(reader, name.getNamespaceURI(), name.getLocalPart());
267 }
269 public static String getStateName(XMLStreamReader reader) {
270 return getStateName(reader.getEventType());
271 }
273 public static String getStateName(int state) {
274 switch (state) {
275 case ATTRIBUTE:
276 return "ATTRIBUTE";
277 case CDATA:
278 return "CDATA";
279 case CHARACTERS:
280 return "CHARACTERS";
281 case COMMENT:
282 return "COMMENT";
283 case DTD:
284 return "DTD";
285 case END_DOCUMENT:
286 return "END_DOCUMENT";
287 case END_ELEMENT:
288 return "END_ELEMENT";
289 case ENTITY_DECLARATION:
290 return "ENTITY_DECLARATION";
291 case ENTITY_REFERENCE:
292 return "ENTITY_REFERENCE";
293 case NAMESPACE:
294 return "NAMESPACE";
295 case NOTATION_DECLARATION:
296 return "NOTATION_DECLARATION";
297 case PROCESSING_INSTRUCTION:
298 return "PROCESSING_INSTRUCTION";
299 case SPACE:
300 return "SPACE";
301 case START_DOCUMENT:
302 return "START_DOCUMENT";
303 case START_ELEMENT:
304 return "START_ELEMENT";
305 default :
306 return "UNKNOWN";
307 }
308 }
310 private static XMLStreamReaderException wrapException(XMLStreamException e) {
311 return new XMLStreamReaderException("xmlreader.ioException",e);
312 }
314 // -- Auxiliary classes ----------------------------------------------
316 /**
317 * AttributesImpl class copied from old StAXReader. This class is used to implement
318 * getAttributes() on a StAX Reader.
319 */
320 public static class AttributesImpl implements Attributes {
322 static final String XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/";
324 static class AttributeInfo {
326 private QName name;
327 private String value;
329 public AttributeInfo(QName name, String value) {
330 this.name = name;
331 if (value == null) {
332 // e.g., <return xmlns=""> -- stax returns null
333 this.value = "";
334 } else {
335 this.value = value;
336 }
337 }
339 QName getName() {
340 return name;
341 }
343 String getValue() {
344 return value;
345 }
347 /*
348 * Return "xmlns:" as part of name if namespace.
349 */
350 String getLocalName() {
351 if (isNamespaceDeclaration()) {
352 if (name.getLocalPart().equals("")) {
353 return "xmlns";
354 }
355 return "xmlns:" + name.getLocalPart();
356 }
357 return name.getLocalPart();
358 }
360 boolean isNamespaceDeclaration() {
361 return (name.getNamespaceURI() == XMLNS_NAMESPACE_URI);
362 }
363 }
365 // stores qname and value for each attribute
366 AttributeInfo [] atInfos;
368 /*
369 * Will create a list that contains the namespace declarations
370 * as well as the other attributes.
371 */
372 public AttributesImpl(XMLStreamReader reader) {
373 if (reader == null) {
375 // this is the case when we call getAttributes() on the
376 // reader when it is not on a start tag
377 atInfos = new AttributeInfo[0];
378 } else {
380 // this is the normal case
381 int index = 0;
382 int namespaceCount = reader.getNamespaceCount();
383 int attributeCount = reader.getAttributeCount();
384 atInfos = new AttributeInfo[namespaceCount + attributeCount];
385 for (int i=0; i<namespaceCount; i++) {
386 String namespacePrefix = reader.getNamespacePrefix(i);
388 // will be null if default prefix. QName can't take null
389 if (namespacePrefix == null) {
390 namespacePrefix = "";
391 }
392 atInfos[index++] = new AttributeInfo(
393 new QName(XMLNS_NAMESPACE_URI,
394 namespacePrefix,
395 "xmlns"),
396 reader.getNamespaceURI(i));
397 }
398 for (int i=0; i<attributeCount; i++) {
399 atInfos[index++] = new AttributeInfo(
400 reader.getAttributeName(i),
401 reader.getAttributeValue(i));
402 }
403 }
404 }
406 public int getLength() {
407 return atInfos.length;
408 }
410 public String getLocalName(int index) {
411 if (index >= 0 && index < atInfos.length) {
412 return atInfos[index].getLocalName();
413 }
414 return null;
415 }
417 public QName getName(int index) {
418 if (index >= 0 && index < atInfos.length) {
419 return atInfos[index].getName();
420 }
421 return null;
422 }
424 public String getPrefix(int index) {
425 if (index >= 0 && index < atInfos.length) {
426 return atInfos[index].getName().getPrefix();
427 }
428 return null;
429 }
431 public String getURI(int index) {
432 if (index >= 0 && index < atInfos.length) {
433 return atInfos[index].getName().getNamespaceURI();
434 }
435 return null;
436 }
438 public String getValue(int index) {
439 if (index >= 0 && index < atInfos.length) {
440 return atInfos[index].getValue();
441 }
442 return null;
443 }
445 public String getValue(QName name) {
446 int index = getIndex(name);
447 if (index != -1) {
448 return atInfos[index].getValue();
449 }
450 return null;
451 }
453 public String getValue(String localName) {
454 int index = getIndex(localName);
455 if (index != -1) {
456 return atInfos[index].getValue();
457 }
458 return null;
459 }
461 public String getValue(String uri, String localName) {
462 int index = getIndex(uri, localName);
463 if (index != -1) {
464 return atInfos[index].getValue();
465 }
466 return null;
467 }
469 public boolean isNamespaceDeclaration(int index) {
470 if (index >= 0 && index < atInfos.length) {
471 return atInfos[index].isNamespaceDeclaration();
472 }
473 return false;
474 }
476 public int getIndex(QName name) {
477 for (int i=0; i<atInfos.length; i++) {
478 if (atInfos[i].getName().equals(name)) {
479 return i;
480 }
481 }
482 return -1;
483 }
485 public int getIndex(String localName) {
486 for (int i=0; i<atInfos.length; i++) {
487 if (atInfos[i].getName().getLocalPart().equals(localName)) {
488 return i;
489 }
490 }
491 return -1;
492 }
494 public int getIndex(String uri, String localName) {
495 QName qName;
496 for (int i=0; i<atInfos.length; i++) {
497 qName = atInfos[i].getName();
498 if (qName.getNamespaceURI().equals(uri) &&
499 qName.getLocalPart().equals(localName)) {
501 return i;
502 }
503 }
504 return -1;
505 }
506 }
507 }