ohair@286: /* alanb@368: * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package com.sun.xml.internal.ws.streaming; ohair@286: ohair@286: import javax.xml.namespace.QName; ohair@286: import static javax.xml.stream.XMLStreamConstants.*; ohair@286: import javax.xml.stream.XMLStreamException; ohair@286: import javax.xml.stream.XMLStreamReader; ohair@286: import javax.xml.stream.XMLStreamConstants; ohair@286: ohair@286: /** ohair@286: *

XMLStreamReaderUtil provides some utility methods intended to be used ohair@286: * in conjunction with a StAX XMLStreamReader.

ohair@286: * ohair@286: * @author WS Development Team ohair@286: */ ohair@286: public class XMLStreamReaderUtil { ohair@286: ohair@286: private XMLStreamReaderUtil() { ohair@286: } ohair@286: ohair@286: public static void close(XMLStreamReader reader) { ohair@286: try { ohair@286: reader.close(); ohair@286: } catch (XMLStreamException e) { ohair@286: throw wrapException(e); ohair@286: } ohair@286: } ohair@286: ohair@286: public static void readRest(XMLStreamReader reader) { ohair@286: try { ohair@286: while(reader.getEventType() != XMLStreamConstants.END_DOCUMENT) { ohair@286: reader.next(); ohair@286: } ohair@286: } catch (XMLStreamException e) { ohair@286: throw wrapException(e); ohair@286: } ohair@286: } ohair@286: ohair@286: public static int next(XMLStreamReader reader) { ohair@286: try { ohair@286: int readerEvent = reader.next(); ohair@286: ohair@286: while (readerEvent != END_DOCUMENT) { ohair@286: switch (readerEvent) { ohair@286: case START_ELEMENT: ohair@286: case END_ELEMENT: ohair@286: case CDATA: ohair@286: case CHARACTERS: ohair@286: case PROCESSING_INSTRUCTION: ohair@286: return readerEvent; ohair@286: default: ohair@286: // falls through ignoring event ohair@286: } ohair@286: readerEvent = reader.next(); ohair@286: } ohair@286: ohair@286: return readerEvent; ohair@286: } ohair@286: catch (XMLStreamException e) { ohair@286: throw wrapException(e); ohair@286: } ohair@286: } ohair@286: ohair@286: public static int nextElementContent(XMLStreamReader reader) { ohair@286: int state = nextContent(reader); ohair@286: if (state == CHARACTERS) { ohair@286: throw new XMLStreamReaderException( ohair@286: "xmlreader.unexpectedCharacterContent", reader.getText()); ohair@286: } ohair@286: return state; ohair@286: } ohair@286: alanb@368: public static void toNextTag(XMLStreamReader reader, QName name) { alanb@368: // skip any whitespace alanb@368: if (reader.getEventType() != XMLStreamConstants.START_ELEMENT && alanb@368: reader.getEventType() != XMLStreamConstants.END_ELEMENT) { alanb@368: XMLStreamReaderUtil.nextElementContent(reader); alanb@368: } alanb@368: if(reader.getEventType() == XMLStreamConstants.END_ELEMENT && name.equals(reader.getName())) { alanb@368: XMLStreamReaderUtil.nextElementContent(reader); alanb@368: } alanb@368: } alanb@368: ohair@286: /** ohair@286: * Moves next and read spaces from the reader as long as to the next element. ohair@286: * Comments are ignored ohair@286: * @param reader ohair@286: * @return ohair@286: */ ohair@286: public static String nextWhiteSpaceContent(XMLStreamReader reader) { ohair@286: next(reader); ohair@286: return currentWhiteSpaceContent(reader); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Read spaces from the reader as long as to the next element, starting from ohair@286: * current position. Comments are ignored. ohair@286: * @param reader ohair@286: * @return ohair@286: */ ohair@286: public static String currentWhiteSpaceContent(XMLStreamReader reader) { ohair@286: ohair@286: // since the there might be several valid chunks (spaces/comment/spaces) ohair@286: // StringBuilder must be used; it's initialized lazily, only when needed ohair@286: StringBuilder whiteSpaces = null; ohair@286: ohair@286: for (;;) { ohair@286: switch (reader.getEventType()) { ohair@286: case START_ELEMENT: ohair@286: case END_ELEMENT: ohair@286: case END_DOCUMENT: ohair@286: return whiteSpaces == null ? null : whiteSpaces.toString(); ohair@286: case CHARACTERS: ohair@286: if (reader.isWhiteSpace()) { ohair@286: if (whiteSpaces == null) { ohair@286: whiteSpaces = new StringBuilder(); ohair@286: } ohair@286: whiteSpaces.append(reader.getText()); ohair@286: } else { ohair@286: throw new XMLStreamReaderException( ohair@286: "xmlreader.unexpectedCharacterContent", reader.getText()); ohair@286: } ohair@286: } ohair@286: next(reader); ohair@286: } ohair@286: } ohair@286: ohair@286: public static int nextContent(XMLStreamReader reader) { ohair@286: for (;;) { ohair@286: int state = next(reader); ohair@286: switch (state) { ohair@286: case START_ELEMENT: ohair@286: case END_ELEMENT: ohair@286: case END_DOCUMENT: ohair@286: return state; ohair@286: case CHARACTERS: ohair@286: if (!reader.isWhiteSpace()) { ohair@286: return CHARACTERS; ohair@286: } ohair@286: } ohair@286: } ohair@286: } ohair@286: ohair@286: /** ohair@286: * Skip current element, leaving the cursor at END_ELEMENT of ohair@286: * current element. ohair@286: */ ohair@286: public static void skipElement(XMLStreamReader reader) { ohair@286: assert reader.getEventType() == START_ELEMENT; ohair@286: skipTags(reader, true); ohair@286: assert reader.getEventType() == END_ELEMENT; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Skip following siblings, leaving cursor at END_ELEMENT of ohair@286: * parent element. ohair@286: */ ohair@286: public static void skipSiblings(XMLStreamReader reader, QName parent) { ohair@286: skipTags(reader, reader.getName().equals(parent)); ohair@286: assert reader.getEventType() == END_ELEMENT; ohair@286: } ohair@286: ohair@286: private static void skipTags(XMLStreamReader reader, boolean exitCondition) { ohair@286: try { ohair@286: int state, tags = 0; ohair@286: while ((state = reader.next()) != END_DOCUMENT) { ohair@286: if (state == START_ELEMENT) { ohair@286: tags++; ohair@286: } ohair@286: else if (state == END_ELEMENT) { ohair@286: if (tags == 0 && exitCondition) return; ohair@286: tags--; ohair@286: } ohair@286: } ohair@286: } ohair@286: catch (XMLStreamException e) { ohair@286: throw wrapException(e); ohair@286: } ohair@286: } ohair@286: ohair@286: /* ohair@286: * Get the text of an element ohair@286: */ ohair@286: public static String getElementText(XMLStreamReader reader) { ohair@286: try { ohair@286: return reader.getElementText(); ohair@286: } catch (XMLStreamException e) { ohair@286: throw wrapException(e); ohair@286: } ohair@286: } ohair@286: ohair@286: /* ohair@286: * Get a QName with 'someUri' and 'localname' from an ohair@286: * element of qname type: ohair@286: * ns1:localname ohair@286: */ ohair@286: public static QName getElementQName(XMLStreamReader reader) { ohair@286: try { ohair@286: String text = reader.getElementText().trim(); ohair@286: String prefix = text.substring(0,text.indexOf(':')); ohair@286: String namespaceURI = reader.getNamespaceContext().getNamespaceURI(prefix); ohair@286: if (namespaceURI == null) { ohair@286: namespaceURI = ""; ohair@286: } ohair@286: String localPart = text.substring( ohair@286: text.indexOf(':') + 1, text.length()); ohair@286: return new QName(namespaceURI, localPart); ohair@286: } catch (XMLStreamException e) { ohair@286: throw wrapException(e); ohair@286: } ohair@286: } ohair@286: ohair@286: /** ohair@286: * Read all attributes into an data structure. Note that this method cannot ohair@286: * be called multiple times to get the same list of attributes. ohair@286: */ ohair@286: public static Attributes getAttributes(XMLStreamReader reader) { ohair@286: return (reader.getEventType() == START_ELEMENT || ohair@286: reader.getEventType() == ATTRIBUTE) ? ohair@286: new AttributesImpl(reader) : null; ohair@286: } ohair@286: ohair@286: public static void verifyReaderState(XMLStreamReader reader, int expectedState) { ohair@286: int state = reader.getEventType(); ohair@286: if (state != expectedState) { ohair@286: throw new XMLStreamReaderException( ohair@286: "xmlreader.unexpectedState", ohair@286: getStateName(expectedState), getStateName(state)); ohair@286: } ohair@286: } ohair@286: ohair@286: public static void verifyTag(XMLStreamReader reader, String namespaceURI, String localName) { ohair@286: if (!localName.equals(reader.getLocalName()) || !namespaceURI.equals(reader.getNamespaceURI())) { ohair@286: throw new XMLStreamReaderException( ohair@286: "xmlreader.unexpectedState.tag", ohair@286: "{" + namespaceURI + "}" + localName, ohair@286: "{" + reader.getNamespaceURI() + "}" + reader.getLocalName()); ohair@286: } ohair@286: } ohair@286: ohair@286: public static void verifyTag(XMLStreamReader reader, QName name) { ohair@286: verifyTag(reader, name.getNamespaceURI(), name.getLocalPart()); ohair@286: } ohair@286: ohair@286: public static String getStateName(XMLStreamReader reader) { ohair@286: return getStateName(reader.getEventType()); ohair@286: } ohair@286: ohair@286: public static String getStateName(int state) { ohair@286: switch (state) { ohair@286: case ATTRIBUTE: ohair@286: return "ATTRIBUTE"; ohair@286: case CDATA: ohair@286: return "CDATA"; ohair@286: case CHARACTERS: ohair@286: return "CHARACTERS"; ohair@286: case COMMENT: ohair@286: return "COMMENT"; ohair@286: case DTD: ohair@286: return "DTD"; ohair@286: case END_DOCUMENT: ohair@286: return "END_DOCUMENT"; ohair@286: case END_ELEMENT: ohair@286: return "END_ELEMENT"; ohair@286: case ENTITY_DECLARATION: ohair@286: return "ENTITY_DECLARATION"; ohair@286: case ENTITY_REFERENCE: ohair@286: return "ENTITY_REFERENCE"; ohair@286: case NAMESPACE: ohair@286: return "NAMESPACE"; ohair@286: case NOTATION_DECLARATION: ohair@286: return "NOTATION_DECLARATION"; ohair@286: case PROCESSING_INSTRUCTION: ohair@286: return "PROCESSING_INSTRUCTION"; ohair@286: case SPACE: ohair@286: return "SPACE"; ohair@286: case START_DOCUMENT: ohair@286: return "START_DOCUMENT"; ohair@286: case START_ELEMENT: ohair@286: return "START_ELEMENT"; ohair@286: default : ohair@286: return "UNKNOWN"; ohair@286: } ohair@286: } ohair@286: ohair@286: private static XMLStreamReaderException wrapException(XMLStreamException e) { ohair@286: return new XMLStreamReaderException("xmlreader.ioException",e); ohair@286: } ohair@286: ohair@286: // -- Auxiliary classes ---------------------------------------------- ohair@286: ohair@286: /** ohair@286: * AttributesImpl class copied from old StAXReader. This class is used to implement ohair@286: * getAttributes() on a StAX Reader. ohair@286: */ ohair@286: public static class AttributesImpl implements Attributes { ohair@286: ohair@286: static final String XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/"; ohair@286: ohair@286: static class AttributeInfo { ohair@286: ohair@286: private QName name; ohair@286: private String value; ohair@286: ohair@286: public AttributeInfo(QName name, String value) { ohair@286: this.name = name; ohair@286: if (value == null) { ohair@286: // e.g., -- stax returns null ohair@286: this.value = ""; ohair@286: } else { ohair@286: this.value = value; ohair@286: } ohair@286: } ohair@286: ohair@286: QName getName() { ohair@286: return name; ohair@286: } ohair@286: ohair@286: String getValue() { ohair@286: return value; ohair@286: } ohair@286: ohair@286: /* ohair@286: * Return "xmlns:" as part of name if namespace. ohair@286: */ ohair@286: String getLocalName() { ohair@286: if (isNamespaceDeclaration()) { ohair@286: if (name.getLocalPart().equals("")) { ohair@286: return "xmlns"; ohair@286: } ohair@286: return "xmlns:" + name.getLocalPart(); ohair@286: } ohair@286: return name.getLocalPart(); ohair@286: } ohair@286: ohair@286: boolean isNamespaceDeclaration() { ohair@286: return (name.getNamespaceURI() == XMLNS_NAMESPACE_URI); ohair@286: } ohair@286: } ohair@286: ohair@286: // stores qname and value for each attribute ohair@286: AttributeInfo [] atInfos; ohair@286: ohair@286: /* ohair@286: * Will create a list that contains the namespace declarations ohair@286: * as well as the other attributes. ohair@286: */ ohair@286: public AttributesImpl(XMLStreamReader reader) { ohair@286: if (reader == null) { ohair@286: ohair@286: // this is the case when we call getAttributes() on the ohair@286: // reader when it is not on a start tag ohair@286: atInfos = new AttributeInfo[0]; ohair@286: } else { ohair@286: ohair@286: // this is the normal case ohair@286: int index = 0; ohair@286: int namespaceCount = reader.getNamespaceCount(); ohair@286: int attributeCount = reader.getAttributeCount(); ohair@286: atInfos = new AttributeInfo[namespaceCount + attributeCount]; ohair@286: for (int i=0; i= 0 && index < atInfos.length) { ohair@286: return atInfos[index].getLocalName(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public QName getName(int index) { ohair@286: if (index >= 0 && index < atInfos.length) { ohair@286: return atInfos[index].getName(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public String getPrefix(int index) { ohair@286: if (index >= 0 && index < atInfos.length) { ohair@286: return atInfos[index].getName().getPrefix(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public String getURI(int index) { ohair@286: if (index >= 0 && index < atInfos.length) { ohair@286: return atInfos[index].getName().getNamespaceURI(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public String getValue(int index) { ohair@286: if (index >= 0 && index < atInfos.length) { ohair@286: return atInfos[index].getValue(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public String getValue(QName name) { ohair@286: int index = getIndex(name); ohair@286: if (index != -1) { ohair@286: return atInfos[index].getValue(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public String getValue(String localName) { ohair@286: int index = getIndex(localName); ohair@286: if (index != -1) { ohair@286: return atInfos[index].getValue(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public String getValue(String uri, String localName) { ohair@286: int index = getIndex(uri, localName); ohair@286: if (index != -1) { ohair@286: return atInfos[index].getValue(); ohair@286: } ohair@286: return null; ohair@286: } ohair@286: ohair@286: public boolean isNamespaceDeclaration(int index) { ohair@286: if (index >= 0 && index < atInfos.length) { ohair@286: return atInfos[index].isNamespaceDeclaration(); ohair@286: } ohair@286: return false; ohair@286: } ohair@286: ohair@286: public int getIndex(QName name) { ohair@286: for (int i=0; i