blob: af72aadeebcbc79cc7984117378c7e08e4c47994 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.jaxws.message.util.impl;
import org.apache.axis2.jaxws.i18n.Messages;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
/**
* XMLStreamReader created from walking a DOM. This is an implementation class used by
* SOAPElementReader.
*
* @see org.apache.axis2.jaxws.util.SOAPElementReader
*/
public class XMLStreamReaderFromDOM implements XMLStreamReader {
private Node cursor;
private Stack<Node> nextCursorStack = new Stack<Node>();
private Node root;
private int event = XMLStreamReader.START_DOCUMENT;
private Node nextCursor = null;
private int nextEvent = -1;
private NamespaceContextFromDOM cacheNCI = null;
private Element cacheNCIKey = null;
private List cacheND = null;
private Element cacheNDKey = null;
/**
* Create the XMLStreamReader with an Envelope
*
* @param envelope Element (probably an SAAJ SOAPEnvelope) representing the Envelope
*/
public XMLStreamReaderFromDOM(Element envelope) {
root = envelope;
cursor = root;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getProperty(java.lang.String)
*/
public Object getProperty(String key) throws IllegalArgumentException {
if (key == null) {
throw new IllegalArgumentException(Messages.getMessage("XMLSRErr1"));
}
return null;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#next()
*/
public int next() throws XMLStreamException {
if (!hasNext()) {
throw new XMLStreamException(Messages.getMessage("XMLSRErr2"));
}
getNext();
cursor = nextCursor;
event = nextEvent;
return event;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#require(int, java.lang.String, java.lang.String)
*/
public void require(int event, String namespace, String localPart)
throws XMLStreamException {
try {
if (event != this.event) {
throw new XMLStreamException(Messages.getMessage("XMLSRErr3", String.valueOf(event),
String.valueOf(this.event)));
}
if (namespace != null &&
!namespace.equals(cursor.getNamespaceURI())) {
throw new XMLStreamException(
Messages.getMessage("XMLSRErr3", namespace, this.cursor.getNamespaceURI()));
}
if (localPart != null &&
!localPart.equals(cursor.getLocalName())) {
throw new XMLStreamException(
Messages.getMessage("XMLSRErr3", localPart, this.cursor.getLocalName()));
}
} catch (XMLStreamException e) {
throw e;
} catch (Exception e) {
throw new XMLStreamException(e);
}
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getElementText()
*/
public String getElementText() throws XMLStreamException {
if (event == XMLStreamReader.START_ELEMENT) {
next();
StringBuffer buffer = new StringBuffer();
while (event != XMLStreamReader.END_ELEMENT) {
if (event == XMLStreamReader.CHARACTERS ||
event == XMLStreamReader.CDATA ||
event == XMLStreamReader.SPACE ||
event == XMLStreamReader.ENTITY_REFERENCE) {
buffer.append(getText());
} else if (event == XMLStreamReader.PROCESSING_INSTRUCTION ||
event == XMLStreamReader.COMMENT) {
// whitespace
} else {
throw new XMLStreamException(
Messages.getMessage("XMLSRErr4", "getElementText()"));
}
next();
}
return buffer.toString();
}
throw new XMLStreamException(Messages.getMessage("XMLSRErr4", "getElementText()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#nextTag()
*/
public int nextTag() throws XMLStreamException {
next();
while (event == XMLStreamReader.CHARACTERS && isWhiteSpace() ||
event == XMLStreamReader.CDATA && isWhiteSpace() ||
event == XMLStreamReader.SPACE ||
event == XMLStreamReader.PROCESSING_INSTRUCTION ||
event == XMLStreamReader.COMMENT) {
event = next();
}
if (event == XMLStreamReader.START_ELEMENT ||
event == XMLStreamReader.END_ELEMENT) {
return event;
}
throw new XMLStreamException(Messages.getMessage("XMLSRErr4", "nextTag()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#hasNext()
*/
public boolean hasNext() throws XMLStreamException {
return (event != XMLStreamReader.END_DOCUMENT);
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#close()
*/
public void close() throws XMLStreamException {
return;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getNamespaceURI(java.lang.String)
*/
public String getNamespaceURI(String prefix) {
if (cursor instanceof Element) {
return getNamespaceContext().getNamespaceURI(prefix);
}
throw new IllegalStateException(
Messages.getMessage("XMLSRErr4", "getNamespaceURI(String)"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#isStartElement()
*/
public boolean isStartElement() {
return (event == XMLStreamReader.START_ELEMENT);
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#isEndElement()
*/
public boolean isEndElement() {
return (event == XMLStreamReader.END_ELEMENT);
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#isCharacters()
*/
public boolean isCharacters() {
return (event == XMLStreamReader.CHARACTERS);
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#isWhiteSpace()
*/
public boolean isWhiteSpace() {
if (event == XMLStreamReader.CHARACTERS ||
event == XMLStreamReader.CDATA) {
String value = ((CharacterData)cursor).getData();
StringTokenizer st = new StringTokenizer(value);
return !(st.hasMoreTokens());
}
return false;
}
/** @return list of attributes that are not namespace declarations */
private List getAttributes() {
if (event == XMLStreamReader.START_ELEMENT) {
List attrs = new ArrayList();
NamedNodeMap map = ((Element)cursor).getAttributes();
if (map != null) {
for (int i = 0; i < map.getLength(); i++) {
Attr attr = (Attr)map.item(i);
if (attr.getName().equals("xmlns") ||
attr.getName().startsWith("xmlns:")) {
// this is a namespace declaration
} else {
attrs.add(attr);
}
}
}
return attrs;
}
throw new IllegalStateException(Messages.getMessage("XMLSRErr4", "getAttributes()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeValue(java.lang.String, java.lang.String)
*/
public String getAttributeValue(String namespace, String localPart) {
if (event == XMLStreamReader.START_ELEMENT) {
return ((Element)cursor).getAttributeNS(namespace, localPart);
}
throw new IllegalStateException(
Messages.getMessage("XMLSRErr4", "getAttributeValue(String, String)"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeCount()
*/
public int getAttributeCount() {
return getAttributes().size();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeName(int)
*/
public QName getAttributeName(int index) {
Attr attr = (Attr)getAttributes().get(index);
return new QName(attr.getNamespaceURI(), attr.getLocalName());
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeNamespace(int)
*/
public String getAttributeNamespace(int index) {
Attr attr = (Attr)getAttributes().get(index);
return attr.getNamespaceURI();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeLocalName(int)
*/
public String getAttributeLocalName(int index) {
Attr attr = (Attr)getAttributes().get(index);
return attr.getLocalName();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributePrefix(int)
*/
public String getAttributePrefix(int index) {
Attr attr = (Attr)getAttributes().get(index);
return attr.getPrefix();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeType(int)
*/
public String getAttributeType(int index) {
Attr attr = (Attr)getAttributes().get(index);
return attr.getSchemaTypeInfo().getTypeName();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getAttributeValue(int)
*/
public String getAttributeValue(int index) {
Attr attr = (Attr)getAttributes().get(index);
return attr.getValue();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#isAttributeSpecified(int)
*/
public boolean isAttributeSpecified(int arg0) {
return true;
}
/*
* @return number of namespace declarations on this element
*/
public int getNamespaceCount() {
if (cursor instanceof Element) {
List list = getNamespaceDeclarations();
return list.size();
}
throw new IllegalStateException(Messages.getMessage("XMLSRErr4", "getNamespaceCount()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getNamespacePrefix(int)
*/
public String getNamespacePrefix(int index) {
if (cursor instanceof Element) {
List list = getNamespaceDeclarations();
return ((NamespaceDeclare)list.get(index)).getPrefix();
}
throw new IllegalStateException(
Messages.getMessage("XMLSRErr4", "getNamespacePrefix(int)"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getNamespaceURI(int)
*/
public String getNamespaceURI(int index) {
if (cursor instanceof Element) {
List list = getNamespaceDeclarations();
return ((NamespaceDeclare)list.get(index)).getURI();
}
throw new IllegalStateException(Messages.getMessage("XMLSRErr4", "getNamespaceURI(int)"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getNamespaceContext()
*/
public NamespaceContext getNamespaceContext() {
Element element = null;
if (cursor instanceof Element) {
element = (Element)cursor;
} else {
Element parent = (Element)cursor.getParentNode();
if (parent == null) {
parent = (Element)nextCursorStack.peek();
}
element = (Element)cursor.getParentNode();
}
if (element == cacheNCIKey) {
return cacheNCI;
}
cacheNCIKey = element;
cacheNCI = new NamespaceContextFromDOM(element);
return cacheNCI;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getEventType()
*/
public int getEventType() {
return event;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getText()
*/
public String getText() {
if (event == XMLStreamReader.CHARACTERS ||
event == XMLStreamReader.CDATA ||
event == XMLStreamReader.COMMENT) {
return ((CharacterData)cursor).getData();
}
throw new IllegalStateException(Messages.getMessage("XMLSRErr4", "getText()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getTextCharacters()
*/
public char[] getTextCharacters() {
return getText().toCharArray();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getTextCharacters(int, char[], int, int)
*/
public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length)
throws XMLStreamException {
String value = getText();
// Calculate the sourceEnd index
int sourceEnd = sourceStart + length;
if (value.length() < sourceEnd) {
sourceEnd = value.length();
}
value.getChars(sourceStart, sourceEnd, target, targetStart);
return sourceEnd - sourceStart;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getTextStart()
*/
public int getTextStart() {
return 0;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getTextLength()
*/
public int getTextLength() {
return getText().length();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getEncoding()
*/
public String getEncoding() {
return null;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#hasText()
*/
public boolean hasText() {
return (event == XMLStreamReader.CHARACTERS ||
event == XMLStreamReader.CDATA ||
event == XMLStreamReader.COMMENT);
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getLocation()
*/
public Location getLocation() {
return dummyLocation;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getName()
*/
public QName getName() {
if (cursor instanceof Element) {
return new QName(cursor.getNamespaceURI(), cursor.getLocalName());
}
throw new IllegalStateException(Messages.getMessage("XMLSRErr4", "getName()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getLocalName()
*/
public String getLocalName() {
if (cursor instanceof Element) {
return cursor.getLocalName();
}
throw new IllegalStateException(Messages.getMessage("XMLSRErr4", "getLocalName()"));
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#hasName()
*/
public boolean hasName() {
return (isStartElement() || isEndElement());
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getNamespaceURI()
*/
public String getNamespaceURI() {
if (cursor instanceof Element) {
return cursor.getNamespaceURI();
} else {
return null;
}
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getPrefix()
*/
public String getPrefix() {
if (cursor instanceof Element) {
return cursor.getPrefix();
} else {
return null;
}
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getVersion()
*/
public String getVersion() {
return null;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#isStandalone()
*/
public boolean isStandalone() {
return false;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#standaloneSet()
*/
public boolean standaloneSet() {
return false;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getCharacterEncodingScheme()
*/
public String getCharacterEncodingScheme() {
return null;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getPITarget()
*/
public String getPITarget() {
return null;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamReader#getPIData()
*/
public String getPIData() {
return null;
}
/** Sets nextCursor and nextEvent from using the current cursor and event. */
private void getNext() throws IllegalStateException {
switch (event) {
case XMLStreamReader.START_DOCUMENT: {
nextCursor = cursor;
nextEvent = XMLStreamReader.START_ELEMENT;
break;
}
case XMLStreamReader.START_ELEMENT: {
if (cursor.getFirstChild() != null) {
nextCursorStack.push(nextCursor);
nextCursor = cursor.getFirstChild();
nextEvent = startEvent(nextCursor);
} else {
nextEvent = XMLStreamReader.END_ELEMENT;
}
break;
}
case XMLStreamReader.ATTRIBUTE: {
throw new IllegalStateException(Messages.getMessage("XMLSRErr5", "ATTRIBUTE"));
}
case XMLStreamReader.NAMESPACE: {
throw new IllegalStateException(Messages.getMessage("XMLSRErr5", "NAMESPACE"));
}
case XMLStreamReader.END_ELEMENT:
case XMLStreamReader.CHARACTERS:
case XMLStreamReader.CDATA:
case XMLStreamReader.COMMENT:
case XMLStreamReader.SPACE:
case XMLStreamReader.PROCESSING_INSTRUCTION:
case XMLStreamReader.ENTITY_REFERENCE:
case XMLStreamReader.DTD: {
if (cursor.getNextSibling() != null) {
nextCursor = cursor.getNextSibling();
nextEvent = startEvent(nextCursor);
} else if (cursor == root) {
nextEvent = XMLStreamReader.END_DOCUMENT;
} else {
// The following does not work with
// Axiom Text nodes
// nextCursor = cursor.getParentNode();
// This is the reason why a stack is used.
nextCursor = nextCursorStack.pop();
nextEvent = XMLStreamReader.END_ELEMENT;
}
break;
}
case XMLStreamReader.END_DOCUMENT: {
nextCursor = null;
nextEvent = -1;
}
default:
throw new IllegalStateException(
Messages.getMessage("XMLSRErr5", String.valueOf(event)));
}
}
/**
* Returns the start event for this particular node
*
* @param node
* @return
*/
private int startEvent(Node node) {
if (node instanceof ProcessingInstruction) {
return XMLStreamReader.PROCESSING_INSTRUCTION;
}
if (node instanceof CDATASection) {
return XMLStreamReader.CDATA;
}
if (node instanceof Comment) {
return XMLStreamReader.COMMENT;
}
if (node instanceof Text) {
if (node instanceof javax.xml.soap.Text) {
javax.xml.soap.Text soapText = (javax.xml.soap.Text)node;
if (soapText.isComment()) {
return XMLStreamReader.COMMENT;
} else {
return XMLStreamReader.CHARACTERS;
}
}
return XMLStreamReader.CHARACTERS;
}
if (node instanceof Element) {
return XMLStreamReader.START_ELEMENT;
}
if (node instanceof Attr) {
return XMLStreamReader.ATTRIBUTE;
}
if (node instanceof Document) {
return XMLStreamReader.START_DOCUMENT;
}
if (node instanceof EntityReference) {
return XMLStreamReader.ENTITY_REFERENCE;
}
if (node instanceof DocumentType) {
return XMLStreamReader.DTD;
}
return -1;
}
// This is the definition of a dummy Location
private DummyLocation dummyLocation = new DummyLocation();
private class DummyLocation implements Location {
public int getLineNumber() {
return -1;
}
public int getColumnNumber() {
return 0;
}
public int getCharacterOffset() {
return 0;
}
public String getPublicId() {
return null;
}
public String getSystemId() {
return null;
}
}
public List getNamespaceDeclarations() {
Element element = null;
if (cursor instanceof Element) {
element = (Element)cursor;
} else {
return new ArrayList();
}
if (element == cacheNDKey) {
return cacheND;
}
cacheNDKey = element;
cacheND = new ArrayList();
NamedNodeMap attrs = element.getAttributes();
if (attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
Attr attr = (Attr)attrs.item(i);
String name = attr.getNodeName();
if (name.startsWith("xmlns")) {
String prefix = "";
if (name.startsWith("xmlns:")) {
prefix = name.substring(6);
}
NamespaceDeclare nd = new NamespaceDeclare(prefix, attr.getNodeValue());
cacheND.add(nd);
}
}
}
return cacheND;
}
class NamespaceDeclare {
String prefix;
String uri;
NamespaceDeclare(String prefix, String uri) {
this.prefix = prefix;
this.uri = uri;
}
String getPrefix() {
return prefix;
}
String getURI() {
return uri;
}
}
Node getNode() {
return cursor;
}
}