src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLStreamReaderUtil.java

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

mercurial