/** * 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.cxf.aegis.util.stax; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import org.apache.cxf.staxutils.AbstractDOMStreamReader; import org.apache.cxf.staxutils.FastStack; import org.jdom.Attribute; import org.jdom.CDATA; import org.jdom.Comment; import org.jdom.Content; import org.jdom.Document; import org.jdom.Element; import org.jdom.EntityRef; import org.jdom.Namespace; import org.jdom.Text; /** * Facade for DOMStreamReader using JDOM implmentation. */ public class JDOMStreamReader extends AbstractDOMStreamReader<Element, Integer> { private Content content; private FastStack<Map<String, Namespace>> namespaceStack = new FastStack<Map<String, Namespace>>(); private List<Namespace> namespaces = new ArrayList<>(); private Map<String, Namespace> prefix2decNs; private JDOMNamespaceContext namespaceContext; /** * @param element */ public JDOMStreamReader(Element element) { super(new ElementFrame<Element, Integer>(element, null, -1)); namespaceContext = new JDOMNamespaceContext(); setupNamespaces(element); } /** * @param document */ public JDOMStreamReader(Document document) { this(document.getRootElement()); } public static String toStaxType(int jdom) { String val; switch (jdom) { case Attribute.CDATA_TYPE: val = "CDATA"; break; case Attribute.ID_TYPE: val = "ID"; break; case Attribute.IDREF_TYPE: val = "IDREF"; break; case Attribute.IDREFS_TYPE: val = "IDREFS"; break; case Attribute.ENTITY_TYPE: val = "ENTITY"; break; case Attribute.ENTITIES_TYPE: val = "ENTITIES"; break; case Attribute.ENUMERATED_TYPE: val = "ENUMERATED"; break; case Attribute.NMTOKEN_TYPE: val = "NMTOKEN"; break; case Attribute.NMTOKENS_TYPE: val = "NMTOKENS"; break; case Attribute.NOTATION_TYPE: val = "NOTATION"; break; default: val = null; } return val; } private void setupNamespaces(Element element) { namespaceContext.setElement(element); if (prefix2decNs != null) { namespaceStack.push(prefix2decNs); } prefix2decNs = new HashMap<>(); namespaces.clear(); for (Iterator<?> itr = element.getAdditionalNamespaces().iterator(); itr.hasNext();) { declare((Namespace)itr.next()); } Namespace ns = element.getNamespace(); if (shouldDeclare(ns)) { declare(ns); } for (Iterator<?> itr = element.getAttributes().iterator(); itr.hasNext();) { ns = ((Attribute)itr.next()).getNamespace(); if (shouldDeclare(ns)) { declare(ns); } } } private void declare(Namespace ns) { prefix2decNs.put(ns.getPrefix(), ns); namespaces.add(ns); } private boolean shouldDeclare(Namespace ns) { if (ns == Namespace.XML_NAMESPACE) { return false; } if (ns == Namespace.NO_NAMESPACE && getDeclaredURI("") == null) { return false; } String decUri = getDeclaredURI(ns.getPrefix()); return !(decUri != null && decUri.equals(ns.getURI())); } private String getDeclaredURI(String string) { for (int i = namespaceStack.size() - 1; i == 0; i--) { Map<String, Namespace> nmspaces = namespaceStack.get(i); Namespace dec = nmspaces.get(string); if (dec != null) { return dec.getURI(); } } return null; } @Override protected void endElement() { if (!namespaceStack.isEmpty()) { prefix2decNs = namespaceStack.pop(); } } public Element getCurrentElement() { return getCurrentFrame().getElement(); } @Override protected ElementFrame<Element, Integer> getChildFrame() { int currentChild = getCurrentFrame().getCurrentChild(); return new ElementFrame<Element, Integer>((Element)getCurrentElement().getContent(currentChild), getCurrentFrame(), -1); } @Override protected boolean hasMoreChildren() { int currentChild = getCurrentFrame().getCurrentChild(); return currentChild < (getCurrentElement().getContentSize() - 1); } @Override protected int nextChild() { int currentChild = getCurrentFrame().getCurrentChild(); currentChild++; getCurrentFrame().setCurrentChild(currentChild); this.content = getCurrentElement().getContent(currentChild); if (content instanceof Text) { return CHARACTERS; } else if (content instanceof Element) { setupNamespaces((Element)content); return START_ELEMENT; } else if (content instanceof CDATA) { return CHARACTERS; } else if (content instanceof Comment) { return CHARACTERS; } else if (content instanceof EntityRef) { return ENTITY_REFERENCE; } throw new IllegalStateException(); } @Override public String getElementText() throws XMLStreamException { return ((Text)content).getText(); } @Override public String getNamespaceURI(String prefix) { return getCurrentElement().getNamespace(prefix).getURI(); } public String getAttributeValue(String ns, String local) { return getCurrentElement().getAttributeValue(local, Namespace.getNamespace(ns)); } public int getAttributeCount() { return getCurrentElement().getAttributes().size(); } Attribute getAttribute(int i) { return (Attribute)getCurrentElement().getAttributes().get(i); } public QName getAttributeName(int i) { Attribute at = getAttribute(i); return new QName(at.getNamespaceURI(), at.getName(), at.getNamespacePrefix()); } public String getAttributeNamespace(int i) { return getAttribute(i).getNamespaceURI(); } public String getAttributeLocalName(int i) { return getAttribute(i).getName(); } public String getAttributePrefix(int i) { return getAttribute(i).getNamespacePrefix(); } public String getAttributeType(int i) { return toStaxType(getAttribute(i).getAttributeType()); } public String getAttributeValue(int i) { return getAttribute(i).getValue(); } public boolean isAttributeSpecified(int i) { return getAttribute(i).getValue() != null; } public int getNamespaceCount() { return namespaces.size(); } Namespace getNamespace(int i) { return namespaces.get(i); } public String getNamespacePrefix(int i) { return getNamespace(i).getPrefix(); } public String getNamespaceURI(int i) { return getNamespace(i).getURI(); } public NamespaceContext getNamespaceContext() { return namespaceContext; } public String getText() { return content.getValue(); } 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() { Element el = getCurrentElement(); return new QName(el.getNamespaceURI(), el.getName(), el.getNamespacePrefix()); } public String getLocalName() { return getCurrentElement().getName(); } public String getNamespaceURI() { return getCurrentElement().getNamespaceURI(); } public String getPrefix() { return getCurrentElement().getNamespacePrefix(); } public String getPITarget() { throw new UnsupportedOperationException(); } public String getPIData() { throw new UnsupportedOperationException(); } }