1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/XMLStreamReaderUtil.java Tue Mar 06 16:09:35 2012 -0800 1.3 @@ -0,0 +1,496 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.streaming; 1.30 + 1.31 +import javax.xml.namespace.QName; 1.32 +import static javax.xml.stream.XMLStreamConstants.*; 1.33 +import javax.xml.stream.XMLStreamException; 1.34 +import javax.xml.stream.XMLStreamReader; 1.35 +import javax.xml.stream.XMLStreamConstants; 1.36 + 1.37 +/** 1.38 + * <p> XMLStreamReaderUtil provides some utility methods intended to be used 1.39 + * in conjunction with a StAX XMLStreamReader. </p> 1.40 + * 1.41 + * @author WS Development Team 1.42 + */ 1.43 +public class XMLStreamReaderUtil { 1.44 + 1.45 + private XMLStreamReaderUtil() { 1.46 + } 1.47 + 1.48 + public static void close(XMLStreamReader reader) { 1.49 + try { 1.50 + reader.close(); 1.51 + } catch (XMLStreamException e) { 1.52 + throw wrapException(e); 1.53 + } 1.54 + } 1.55 + 1.56 + public static void readRest(XMLStreamReader reader) { 1.57 + try { 1.58 + while(reader.getEventType() != XMLStreamConstants.END_DOCUMENT) { 1.59 + reader.next(); 1.60 + } 1.61 + } catch (XMLStreamException e) { 1.62 + throw wrapException(e); 1.63 + } 1.64 + } 1.65 + 1.66 + public static int next(XMLStreamReader reader) { 1.67 + try { 1.68 + int readerEvent = reader.next(); 1.69 + 1.70 + while (readerEvent != END_DOCUMENT) { 1.71 + switch (readerEvent) { 1.72 + case START_ELEMENT: 1.73 + case END_ELEMENT: 1.74 + case CDATA: 1.75 + case CHARACTERS: 1.76 + case PROCESSING_INSTRUCTION: 1.77 + return readerEvent; 1.78 + default: 1.79 + // falls through ignoring event 1.80 + } 1.81 + readerEvent = reader.next(); 1.82 + } 1.83 + 1.84 + return readerEvent; 1.85 + } 1.86 + catch (XMLStreamException e) { 1.87 + throw wrapException(e); 1.88 + } 1.89 + } 1.90 + 1.91 + public static int nextElementContent(XMLStreamReader reader) { 1.92 + int state = nextContent(reader); 1.93 + if (state == CHARACTERS) { 1.94 + throw new XMLStreamReaderException( 1.95 + "xmlreader.unexpectedCharacterContent", reader.getText()); 1.96 + } 1.97 + return state; 1.98 + } 1.99 + 1.100 + /** 1.101 + * Moves next and read spaces from the reader as long as to the next element. 1.102 + * Comments are ignored 1.103 + * @param reader 1.104 + * @return 1.105 + */ 1.106 + public static String nextWhiteSpaceContent(XMLStreamReader reader) { 1.107 + next(reader); 1.108 + return currentWhiteSpaceContent(reader); 1.109 + } 1.110 + 1.111 + /** 1.112 + * Read spaces from the reader as long as to the next element, starting from 1.113 + * current position. Comments are ignored. 1.114 + * @param reader 1.115 + * @return 1.116 + */ 1.117 + public static String currentWhiteSpaceContent(XMLStreamReader reader) { 1.118 + 1.119 + // since the there might be several valid chunks (spaces/comment/spaces) 1.120 + // StringBuilder must be used; it's initialized lazily, only when needed 1.121 + StringBuilder whiteSpaces = null; 1.122 + 1.123 + for (;;) { 1.124 + switch (reader.getEventType()) { 1.125 + case START_ELEMENT: 1.126 + case END_ELEMENT: 1.127 + case END_DOCUMENT: 1.128 + return whiteSpaces == null ? null : whiteSpaces.toString(); 1.129 + case CHARACTERS: 1.130 + if (reader.isWhiteSpace()) { 1.131 + if (whiteSpaces == null) { 1.132 + whiteSpaces = new StringBuilder(); 1.133 + } 1.134 + whiteSpaces.append(reader.getText()); 1.135 + } else { 1.136 + throw new XMLStreamReaderException( 1.137 + "xmlreader.unexpectedCharacterContent", reader.getText()); 1.138 + } 1.139 + } 1.140 + next(reader); 1.141 + } 1.142 + } 1.143 + 1.144 + public static int nextContent(XMLStreamReader reader) { 1.145 + for (;;) { 1.146 + int state = next(reader); 1.147 + switch (state) { 1.148 + case START_ELEMENT: 1.149 + case END_ELEMENT: 1.150 + case END_DOCUMENT: 1.151 + return state; 1.152 + case CHARACTERS: 1.153 + if (!reader.isWhiteSpace()) { 1.154 + return CHARACTERS; 1.155 + } 1.156 + } 1.157 + } 1.158 + } 1.159 + 1.160 + /** 1.161 + * Skip current element, leaving the cursor at END_ELEMENT of 1.162 + * current element. 1.163 + */ 1.164 + public static void skipElement(XMLStreamReader reader) { 1.165 + assert reader.getEventType() == START_ELEMENT; 1.166 + skipTags(reader, true); 1.167 + assert reader.getEventType() == END_ELEMENT; 1.168 + } 1.169 + 1.170 + /** 1.171 + * Skip following siblings, leaving cursor at END_ELEMENT of 1.172 + * parent element. 1.173 + */ 1.174 + public static void skipSiblings(XMLStreamReader reader, QName parent) { 1.175 + skipTags(reader, reader.getName().equals(parent)); 1.176 + assert reader.getEventType() == END_ELEMENT; 1.177 + } 1.178 + 1.179 + private static void skipTags(XMLStreamReader reader, boolean exitCondition) { 1.180 + try { 1.181 + int state, tags = 0; 1.182 + while ((state = reader.next()) != END_DOCUMENT) { 1.183 + if (state == START_ELEMENT) { 1.184 + tags++; 1.185 + } 1.186 + else if (state == END_ELEMENT) { 1.187 + if (tags == 0 && exitCondition) return; 1.188 + tags--; 1.189 + } 1.190 + } 1.191 + } 1.192 + catch (XMLStreamException e) { 1.193 + throw wrapException(e); 1.194 + } 1.195 + } 1.196 + 1.197 + /* 1.198 + * Get the text of an element 1.199 + */ 1.200 + public static String getElementText(XMLStreamReader reader) { 1.201 + try { 1.202 + return reader.getElementText(); 1.203 + } catch (XMLStreamException e) { 1.204 + throw wrapException(e); 1.205 + } 1.206 + } 1.207 + 1.208 + /* 1.209 + * Get a QName with 'someUri' and 'localname' from an 1.210 + * element of qname type: 1.211 + * <xyz xmlns:ns1="someUri">ns1:localname</xyz> 1.212 + */ 1.213 + public static QName getElementQName(XMLStreamReader reader) { 1.214 + try { 1.215 + String text = reader.getElementText().trim(); 1.216 + String prefix = text.substring(0,text.indexOf(':')); 1.217 + String namespaceURI = reader.getNamespaceContext().getNamespaceURI(prefix); 1.218 + if (namespaceURI == null) { 1.219 + namespaceURI = ""; 1.220 + } 1.221 + String localPart = text.substring( 1.222 + text.indexOf(':') + 1, text.length()); 1.223 + return new QName(namespaceURI, localPart); 1.224 + } catch (XMLStreamException e) { 1.225 + throw wrapException(e); 1.226 + } 1.227 + } 1.228 + 1.229 + /** 1.230 + * Read all attributes into an data structure. Note that this method cannot 1.231 + * be called multiple times to get the same list of attributes. 1.232 + */ 1.233 + public static Attributes getAttributes(XMLStreamReader reader) { 1.234 + return (reader.getEventType() == START_ELEMENT || 1.235 + reader.getEventType() == ATTRIBUTE) ? 1.236 + new AttributesImpl(reader) : null; 1.237 + } 1.238 + 1.239 + public static void verifyReaderState(XMLStreamReader reader, int expectedState) { 1.240 + int state = reader.getEventType(); 1.241 + if (state != expectedState) { 1.242 + throw new XMLStreamReaderException( 1.243 + "xmlreader.unexpectedState", 1.244 + getStateName(expectedState), getStateName(state)); 1.245 + } 1.246 + } 1.247 + 1.248 + public static void verifyTag(XMLStreamReader reader, String namespaceURI, String localName) { 1.249 + if (!localName.equals(reader.getLocalName()) || !namespaceURI.equals(reader.getNamespaceURI())) { 1.250 + throw new XMLStreamReaderException( 1.251 + "xmlreader.unexpectedState.tag", 1.252 + "{" + namespaceURI + "}" + localName, 1.253 + "{" + reader.getNamespaceURI() + "}" + reader.getLocalName()); 1.254 + } 1.255 + } 1.256 + 1.257 + public static void verifyTag(XMLStreamReader reader, QName name) { 1.258 + verifyTag(reader, name.getNamespaceURI(), name.getLocalPart()); 1.259 + } 1.260 + 1.261 + public static String getStateName(XMLStreamReader reader) { 1.262 + return getStateName(reader.getEventType()); 1.263 + } 1.264 + 1.265 + public static String getStateName(int state) { 1.266 + switch (state) { 1.267 + case ATTRIBUTE: 1.268 + return "ATTRIBUTE"; 1.269 + case CDATA: 1.270 + return "CDATA"; 1.271 + case CHARACTERS: 1.272 + return "CHARACTERS"; 1.273 + case COMMENT: 1.274 + return "COMMENT"; 1.275 + case DTD: 1.276 + return "DTD"; 1.277 + case END_DOCUMENT: 1.278 + return "END_DOCUMENT"; 1.279 + case END_ELEMENT: 1.280 + return "END_ELEMENT"; 1.281 + case ENTITY_DECLARATION: 1.282 + return "ENTITY_DECLARATION"; 1.283 + case ENTITY_REFERENCE: 1.284 + return "ENTITY_REFERENCE"; 1.285 + case NAMESPACE: 1.286 + return "NAMESPACE"; 1.287 + case NOTATION_DECLARATION: 1.288 + return "NOTATION_DECLARATION"; 1.289 + case PROCESSING_INSTRUCTION: 1.290 + return "PROCESSING_INSTRUCTION"; 1.291 + case SPACE: 1.292 + return "SPACE"; 1.293 + case START_DOCUMENT: 1.294 + return "START_DOCUMENT"; 1.295 + case START_ELEMENT: 1.296 + return "START_ELEMENT"; 1.297 + default : 1.298 + return "UNKNOWN"; 1.299 + } 1.300 + } 1.301 + 1.302 + private static XMLStreamReaderException wrapException(XMLStreamException e) { 1.303 + return new XMLStreamReaderException("xmlreader.ioException",e); 1.304 + } 1.305 + 1.306 + // -- Auxiliary classes ---------------------------------------------- 1.307 + 1.308 + /** 1.309 + * AttributesImpl class copied from old StAXReader. This class is used to implement 1.310 + * getAttributes() on a StAX Reader. 1.311 + */ 1.312 + public static class AttributesImpl implements Attributes { 1.313 + 1.314 + static final String XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/"; 1.315 + 1.316 + static class AttributeInfo { 1.317 + 1.318 + private QName name; 1.319 + private String value; 1.320 + 1.321 + public AttributeInfo(QName name, String value) { 1.322 + this.name = name; 1.323 + if (value == null) { 1.324 + // e.g., <return xmlns=""> -- stax returns null 1.325 + this.value = ""; 1.326 + } else { 1.327 + this.value = value; 1.328 + } 1.329 + } 1.330 + 1.331 + QName getName() { 1.332 + return name; 1.333 + } 1.334 + 1.335 + String getValue() { 1.336 + return value; 1.337 + } 1.338 + 1.339 + /* 1.340 + * Return "xmlns:" as part of name if namespace. 1.341 + */ 1.342 + String getLocalName() { 1.343 + if (isNamespaceDeclaration()) { 1.344 + if (name.getLocalPart().equals("")) { 1.345 + return "xmlns"; 1.346 + } 1.347 + return "xmlns:" + name.getLocalPart(); 1.348 + } 1.349 + return name.getLocalPart(); 1.350 + } 1.351 + 1.352 + boolean isNamespaceDeclaration() { 1.353 + return (name.getNamespaceURI() == XMLNS_NAMESPACE_URI); 1.354 + } 1.355 + } 1.356 + 1.357 + // stores qname and value for each attribute 1.358 + AttributeInfo [] atInfos; 1.359 + 1.360 + /* 1.361 + * Will create a list that contains the namespace declarations 1.362 + * as well as the other attributes. 1.363 + */ 1.364 + public AttributesImpl(XMLStreamReader reader) { 1.365 + if (reader == null) { 1.366 + 1.367 + // this is the case when we call getAttributes() on the 1.368 + // reader when it is not on a start tag 1.369 + atInfos = new AttributeInfo[0]; 1.370 + } else { 1.371 + 1.372 + // this is the normal case 1.373 + int index = 0; 1.374 + int namespaceCount = reader.getNamespaceCount(); 1.375 + int attributeCount = reader.getAttributeCount(); 1.376 + atInfos = new AttributeInfo[namespaceCount + attributeCount]; 1.377 + for (int i=0; i<namespaceCount; i++) { 1.378 + String namespacePrefix = reader.getNamespacePrefix(i); 1.379 + 1.380 + // will be null if default prefix. QName can't take null 1.381 + if (namespacePrefix == null) { 1.382 + namespacePrefix = ""; 1.383 + } 1.384 + atInfos[index++] = new AttributeInfo( 1.385 + new QName(XMLNS_NAMESPACE_URI, 1.386 + namespacePrefix, 1.387 + "xmlns"), 1.388 + reader.getNamespaceURI(i)); 1.389 + } 1.390 + for (int i=0; i<attributeCount; i++) { 1.391 + atInfos[index++] = new AttributeInfo( 1.392 + reader.getAttributeName(i), 1.393 + reader.getAttributeValue(i)); 1.394 + } 1.395 + } 1.396 + } 1.397 + 1.398 + public int getLength() { 1.399 + return atInfos.length; 1.400 + } 1.401 + 1.402 + public String getLocalName(int index) { 1.403 + if (index >= 0 && index < atInfos.length) { 1.404 + return atInfos[index].getLocalName(); 1.405 + } 1.406 + return null; 1.407 + } 1.408 + 1.409 + public QName getName(int index) { 1.410 + if (index >= 0 && index < atInfos.length) { 1.411 + return atInfos[index].getName(); 1.412 + } 1.413 + return null; 1.414 + } 1.415 + 1.416 + public String getPrefix(int index) { 1.417 + if (index >= 0 && index < atInfos.length) { 1.418 + return atInfos[index].getName().getPrefix(); 1.419 + } 1.420 + return null; 1.421 + } 1.422 + 1.423 + public String getURI(int index) { 1.424 + if (index >= 0 && index < atInfos.length) { 1.425 + return atInfos[index].getName().getNamespaceURI(); 1.426 + } 1.427 + return null; 1.428 + } 1.429 + 1.430 + public String getValue(int index) { 1.431 + if (index >= 0 && index < atInfos.length) { 1.432 + return atInfos[index].getValue(); 1.433 + } 1.434 + return null; 1.435 + } 1.436 + 1.437 + public String getValue(QName name) { 1.438 + int index = getIndex(name); 1.439 + if (index != -1) { 1.440 + return atInfos[index].getValue(); 1.441 + } 1.442 + return null; 1.443 + } 1.444 + 1.445 + public String getValue(String localName) { 1.446 + int index = getIndex(localName); 1.447 + if (index != -1) { 1.448 + return atInfos[index].getValue(); 1.449 + } 1.450 + return null; 1.451 + } 1.452 + 1.453 + public String getValue(String uri, String localName) { 1.454 + int index = getIndex(uri, localName); 1.455 + if (index != -1) { 1.456 + return atInfos[index].getValue(); 1.457 + } 1.458 + return null; 1.459 + } 1.460 + 1.461 + public boolean isNamespaceDeclaration(int index) { 1.462 + if (index >= 0 && index < atInfos.length) { 1.463 + return atInfos[index].isNamespaceDeclaration(); 1.464 + } 1.465 + return false; 1.466 + } 1.467 + 1.468 + public int getIndex(QName name) { 1.469 + for (int i=0; i<atInfos.length; i++) { 1.470 + if (atInfos[i].getName().equals(name)) { 1.471 + return i; 1.472 + } 1.473 + } 1.474 + return -1; 1.475 + } 1.476 + 1.477 + public int getIndex(String localName) { 1.478 + for (int i=0; i<atInfos.length; i++) { 1.479 + if (atInfos[i].getName().getLocalPart().equals(localName)) { 1.480 + return i; 1.481 + } 1.482 + } 1.483 + return -1; 1.484 + } 1.485 + 1.486 + public int getIndex(String uri, String localName) { 1.487 + QName qName; 1.488 + for (int i=0; i<atInfos.length; i++) { 1.489 + qName = atInfos[i].getName(); 1.490 + if (qName.getNamespaceURI().equals(uri) && 1.491 + qName.getLocalPart().equals(localName)) { 1.492 + 1.493 + return i; 1.494 + } 1.495 + } 1.496 + return -1; 1.497 + } 1.498 + } 1.499 +}