| /** |
| * 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(); |
| } |
| |
| |
| } |