blob: 9596d74b75660e3a82343826bbf722a61623ebca [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.xml.security.staxutils;
import java.util.ArrayList;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.TypeInfo;
public class W3CDOMStreamReader extends AbstractDOMStreamReader<Node, Node> {
private Node content;
private Document document;
private W3CNamespaceContext context;
private String sysId;
/**
* @param element
*/
public W3CDOMStreamReader(Element element) {
super(new ElementFrame<Node, Node>(element, null));
content = element;
newFrame(getCurrentFrame());
this.document = element.getOwnerDocument();
}
public W3CDOMStreamReader(Element element, String systemId) {
this(element);
sysId = systemId;
}
public W3CDOMStreamReader(Document doc) {
super(new ElementFrame<Node, Node>(doc, false) {
public boolean isDocument() {
return true;
}
});
this.document = doc;
}
public W3CDOMStreamReader(DocumentFragment docfrag) {
super(new ElementFrame<Node, Node>(docfrag, true) {
public boolean isDocumentFragment() {
return true;
}
});
this.document = docfrag.getOwnerDocument();
}
/**
* Get the document associated with this stream.
*/
public Document getDocument() {
return document;
}
public String getSystemId() {
try {
return sysId == null ? document.getDocumentURI() : sysId;
} catch (Throwable ex) {
//ignore, probably not DOM level 3
}
return sysId;
}
/**
* Find name spaces declaration in atrributes and move them to separate
* collection.
*/
@Override
protected final void newFrame(ElementFrame<Node, Node> frame) {
Node element = getCurrentNode();
frame.uris = new ArrayList<>();
frame.prefixes = new ArrayList<>();
frame.attributes = new ArrayList<>();
if (context == null) {
context = new W3CNamespaceContext();
}
if (element instanceof Element) {
context.setElement((Element)element);
}
NamedNodeMap nodes = element.getAttributes();
String ePrefix = element.getPrefix();
if (ePrefix == null) {
ePrefix = "";
}
if (nodes != null) {
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String prefix = node.getPrefix();
String localName = node.getLocalName();
String value = node.getNodeValue();
String name = node.getNodeName();
if (prefix == null) {
prefix = "";
}
if (name != null && "xmlns".equals(name)) {
frame.uris.add(value);
frame.prefixes.add("");
} else if (prefix.length() > 0 && "xmlns".equals(prefix)) {
frame.uris.add(value);
frame.prefixes.add(localName);
} else if (name.startsWith("xmlns:")) {
prefix = name.substring(6);
frame.uris.add(value);
frame.prefixes.add(prefix);
} else {
frame.attributes.add(node);
}
}
}
}
public final Node getCurrentNode() {
return getCurrentFrame().element;
}
public final Element getCurrentElement() {
return (Element)getCurrentFrame().element;
}
@Override
protected ElementFrame<Node, Node> getChildFrame() {
return new ElementFrame<Node, Node>(getCurrentFrame().currentChild,
getCurrentFrame());
}
@Override
protected boolean hasMoreChildren() {
if (getCurrentFrame().currentChild == null) {
return getCurrentNode().getFirstChild() != null;
}
return getCurrentFrame().currentChild.getNextSibling() != null;
}
@Override
protected int nextChild() {
ElementFrame<Node, Node> frame = getCurrentFrame();
if (frame.currentChild == null) {
content = getCurrentNode().getFirstChild();
} else {
content = frame.currentChild.getNextSibling();
}
frame.currentChild = content;
switch (content.getNodeType()) {
case Node.ELEMENT_NODE:
return START_ELEMENT;
case Node.TEXT_NODE:
return CHARACTERS;
case Node.COMMENT_NODE:
return COMMENT;
case Node.CDATA_SECTION_NODE:
return CDATA;
case Node.ENTITY_REFERENCE_NODE:
return ENTITY_REFERENCE;
case Node.PROCESSING_INSTRUCTION_NODE:
return PROCESSING_INSTRUCTION;
default:
throw new IllegalStateException("Found type: " + content.getClass().getName());
}
}
@Override
public String getElementText() throws XMLStreamException {
String result = DOMUtils.getRawContent(content);
ElementFrame<Node, Node> frame = getCurrentFrame();
frame.ended = true;
currentEvent = END_ELEMENT;
endElement();
// we should not return null according to the StAx API javadoc
return result != null ? result : "";
}
@Override
public String getNamespaceURI(String prefix) {
ElementFrame<Node, Node> frame = getCurrentFrame();
while (null != frame) {
int index = frame.prefixes.indexOf(prefix);
if (index != -1) {
return frame.uris.get(index);
}
if (frame.parent == null && frame.getElement() instanceof Element) {
return ((Element)frame.getElement()).lookupNamespaceURI(prefix);
}
frame = frame.parent;
}
return null;
}
public String getAttributeValue(String ns, String local) {
Attr at;
if (ns == null || ns.equals("")) {
at = getCurrentElement().getAttributeNode(local);
} else {
at = getCurrentElement().getAttributeNodeNS(ns, local);
}
if (at == null) {
return null;
}
return at.getNodeValue();
}
public int getAttributeCount() {
return getCurrentFrame().attributes.size();
}
Attr getAttribute(int i) {
return (Attr)getCurrentFrame().attributes.get(i);
}
private String getLocalName(Attr attr) {
String name = attr.getLocalName();
if (name == null) {
name = attr.getNodeName();
}
return name;
}
public QName getAttributeName(int i) {
Attr at = getAttribute(i);
String prefix = at.getPrefix();
String ln = getLocalName(at);
// at.getNodeName();
String ns = at.getNamespaceURI();
if (prefix == null) {
return new QName(ns, ln);
}
return new QName(ns, ln, prefix);
}
public String getAttributeNamespace(int i) {
return getAttribute(i).getNamespaceURI();
}
public String getAttributeLocalName(int i) {
Attr attr = getAttribute(i);
return getLocalName(attr);
}
public String getAttributePrefix(int i) {
return getAttribute(i).getPrefix();
}
public String getAttributeType(int i) {
Attr attr = getAttribute(i);
if (attr.isId()) {
return "ID";
}
TypeInfo schemaType = null;
try {
schemaType = attr.getSchemaTypeInfo();
} catch (Throwable t) {
//DOM level 2?
schemaType = null;
}
return (schemaType == null) ? "CDATA"
: schemaType.getTypeName() == null ? "CDATA" : schemaType.getTypeName();
}
public String getAttributeValue(int i) {
return getAttribute(i).getValue();
}
public boolean isAttributeSpecified(int i) {
return getAttribute(i).getValue() != null;
}
public int getNamespaceCount() {
return getCurrentFrame().prefixes.size();
}
public String getNamespacePrefix(int i) {
return getCurrentFrame().prefixes.get(i);
}
public String getNamespaceURI(int i) {
return getCurrentFrame().uris.get(i);
}
public NamespaceContext getNamespaceContext() {
return context;
}
public String getText() {
if (content instanceof Text) {
return ((Text)content).getData();
} else if (content instanceof Comment) {
return ((Comment)content).getData();
}
return DOMUtils.getRawContent(getCurrentNode());
}
public char[] getTextCharacters() {
return getText().toCharArray();
}
public int getTextStart() {
return 0;
}
public int getTextLength() {
return getText().length();
}
public String getEncoding() {
return null;
}
public QName getName() {
Node el = getCurrentNode();
String prefix = getPrefix();
String ln = getLocalName();
return new QName(el.getNamespaceURI(), ln, prefix);
}
public String getLocalName() {
String ln = getCurrentNode().getLocalName();
if (ln == null) {
ln = getCurrentNode().getNodeName();
if (ln.indexOf(":") != -1) {
ln = ln.substring(ln.indexOf(":") + 1);
}
}
return ln;
}
public String getNamespaceURI() {
String ln = getCurrentNode().getLocalName();
if (ln == null) {
ln = getCurrentNode().getNodeName();
if (ln.indexOf(":") == -1) {
ln = getNamespaceURI("");
} else {
ln = getNamespaceURI(ln.substring(0, ln.indexOf(":")));
}
return ln;
}
return getCurrentNode().getNamespaceURI();
}
public String getPrefix() {
String prefix = getCurrentNode().getPrefix();
if (prefix == null) {
String nodeName = getCurrentNode().getNodeName();
if (nodeName.indexOf(":") != -1) {
prefix = nodeName.substring(0, nodeName.indexOf(":"));
} else {
prefix = "";
}
}
return prefix;
}
public String getPITarget() {
return ((ProcessingInstruction)content).getTarget();
}
public String getPIData() {
return ((ProcessingInstruction)content).getData();
}
public Location getLocation() {
try {
Object o = getCurrentNode().getUserData("location");
if (o instanceof Location) {
return (Location)o;
}
} catch (Throwable ex) {
//ignore, probably not DOM level 3
}
return super.getLocation();
}
}