--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.soap/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java Sun Aug 17 15:52:15 2014 +0100
@@ -0,0 +1,1290 @@
+/*
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.xml.internal.messaging.saaj.soap.impl;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.*;
+
+import org.w3c.dom.*;
+import org.w3c.dom.Node;
+
+import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
+import com.sun.xml.internal.messaging.saaj.soap.SOAPDocument;
+import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl;
+import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
+import com.sun.xml.internal.messaging.saaj.util.*;
+
+public class ElementImpl
+ extends com.sun.org.apache.xerces.internal.dom.ElementNSImpl
+ implements SOAPElement, SOAPBodyElement {
+
+ public static final String DSIG_NS = "http://www.w3.org/2000/09/xmldsig#".intern();
+ public static final String XENC_NS = "http://www.w3.org/2001/04/xmlenc#".intern();
+ public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd".intern();
+
+ private transient AttributeManager encodingStyleAttribute = new AttributeManager();
+
+ protected QName elementQName;
+
+ protected static final Logger log =
+ Logger.getLogger(LogDomainConstants.SOAP_IMPL_DOMAIN,
+ "com.sun.xml.internal.messaging.saaj.soap.impl.LocalStrings");
+
+ /**
+ * XML Information Set REC
+ * all namespace attributes (including those named xmlns,
+ * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/
+ */
+ public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern();
+
+ /**
+ * The XML Namespace ("http://www.w3.org/XML/1998/namespace"). This is
+ * the Namespace URI that is automatically mapped to the "xml" prefix.
+ */
+ public final static String XML_URI = "http://www.w3.org/XML/1998/namespace".intern();
+
+ public ElementImpl(SOAPDocumentImpl ownerDoc, Name name) {
+ super(
+ ownerDoc,
+ name.getURI(),
+ name.getQualifiedName(),
+ name.getLocalName());
+ elementQName = NameImpl.convertToQName(name);
+ }
+
+ public ElementImpl(SOAPDocumentImpl ownerDoc, QName name) {
+ super(
+ ownerDoc,
+ name.getNamespaceURI(),
+ getQualifiedName(name),
+ name.getLocalPart());
+ elementQName = name;
+ }
+
+ public ElementImpl(
+ SOAPDocumentImpl ownerDoc,
+ String uri,
+ String qualifiedName) {
+
+ super(ownerDoc, uri, qualifiedName);
+ elementQName =
+ new QName(uri, getLocalPart(qualifiedName), getPrefix(qualifiedName));
+ }
+
+ public void ensureNamespaceIsDeclared(String prefix, String uri) {
+ String alreadyDeclaredUri = getNamespaceURI(prefix);
+ if (alreadyDeclaredUri == null || !alreadyDeclaredUri.equals(uri)) {
+ try {
+ addNamespaceDeclaration(prefix, uri);
+ } catch (SOAPException e) { /*ignore*/
+ }
+ }
+ }
+
+ public Document getOwnerDocument() {
+ Document doc = super.getOwnerDocument();
+ if (doc instanceof SOAPDocument)
+ return ((SOAPDocument) doc).getDocument();
+ else
+ return doc;
+ }
+
+ public SOAPElement addChildElement(Name name) throws SOAPException {
+ return addElement(name);
+ }
+
+ public SOAPElement addChildElement(QName qname) throws SOAPException {
+ return addElement(qname);
+ }
+
+ public SOAPElement addChildElement(String localName) throws SOAPException {
+ return (SOAPElement) addChildElement(
+ NameImpl.createFromUnqualifiedName(localName));
+ }
+
+ public SOAPElement addChildElement(String localName, String prefix)
+ throws SOAPException {
+ String uri = getNamespaceURI(prefix);
+ if (uri == null) {
+ log.log(
+ Level.SEVERE,
+ "SAAJ0101.impl.parent.of.body.elem.mustbe.body",
+ new String[] { prefix });
+ throw new SOAPExceptionImpl(
+ "Unable to locate namespace for prefix " + prefix);
+ }
+ return addChildElement(localName, prefix, uri);
+ }
+
+ public String getNamespaceURI(String prefix) {
+
+ if ("xmlns".equals(prefix)) {
+ return XMLNS_URI;
+ }
+
+ if("xml".equals(prefix)) {
+ return XML_URI;
+ }
+
+ if ("".equals(prefix)) {
+
+ org.w3c.dom.Node currentAncestor = this;
+ while (currentAncestor != null &&
+ !(currentAncestor instanceof Document)) {
+
+ if (currentAncestor instanceof ElementImpl) {
+ QName name = ((ElementImpl) currentAncestor).getElementQName();
+ /*
+ if (prefix.equals(name.getPrefix())) {
+ String uri = name.getNamespaceURI();
+ if ("".equals(uri)) {
+ return null;
+ }
+ else {
+ return uri;
+ }
+ }*/
+ if (((Element) currentAncestor).hasAttributeNS(
+ XMLNS_URI, "xmlns")) {
+
+ String uri =
+ ((Element) currentAncestor).getAttributeNS(
+ XMLNS_URI, "xmlns");
+ if ("".equals(uri))
+ return null;
+ else {
+ return uri;
+ }
+ }
+ }
+ currentAncestor = currentAncestor.getParentNode();
+ }
+
+ } else if (prefix != null) {
+ // Find if there's an ancester whose name contains this prefix
+ org.w3c.dom.Node currentAncestor = this;
+
+// String uri = currentAncestor.lookupNamespaceURI(prefix);
+// return uri;
+ while (currentAncestor != null &&
+ !(currentAncestor instanceof Document)) {
+
+ /* if (prefix.equals(currentAncestor.getPrefix())) {
+ String uri = currentAncestor.getNamespaceURI();
+ // this is because the javadoc says getNamespaceURI() is not a computed value
+ // and URI for a non-empty prefix cannot be null
+ if (uri != null)
+ return uri;
+ }*/
+ //String uri = currentAncestor.lookupNamespaceURI(prefix);
+ //if (uri != null) {
+ // return uri;
+ //}
+
+ if (((Element) currentAncestor).hasAttributeNS(
+ XMLNS_URI, prefix)) {
+ return ((Element) currentAncestor).getAttributeNS(
+ XMLNS_URI, prefix);
+ }
+
+ currentAncestor = currentAncestor.getParentNode();
+ }
+ }
+
+ return null;
+ }
+
+ public SOAPElement setElementQName(QName newName) throws SOAPException {
+ ElementImpl copy =
+ new ElementImpl((SOAPDocumentImpl) getOwnerDocument(), newName);
+ return replaceElementWithSOAPElement(this,copy);
+ }
+
+ public QName createQName(String localName, String prefix)
+ throws SOAPException {
+ String uri = getNamespaceURI(prefix);
+ if (uri == null) {
+ log.log(Level.SEVERE, "SAAJ0102.impl.cannot.locate.ns",
+ new Object[] {prefix});
+ throw new SOAPException("Unable to locate namespace for prefix "
+ + prefix);
+ }
+ return new QName(uri, localName, prefix);
+ }
+
+ public String getNamespacePrefix(String uri) {
+
+ NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
+ while (eachNamespace.hasNext()) {
+ org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
+ if (namespaceDecl.getNodeValue().equals(uri)) {
+ String candidatePrefix = namespaceDecl.getLocalName();
+ if ("xmlns".equals(candidatePrefix))
+ return "";
+ else
+ return candidatePrefix;
+ }
+ }
+
+ // Find if any of the ancestors' name has this uri
+ org.w3c.dom.Node currentAncestor = this;
+ while (currentAncestor != null &&
+ !(currentAncestor instanceof Document)) {
+
+ if (uri.equals(currentAncestor.getNamespaceURI()))
+ return currentAncestor.getPrefix();
+ currentAncestor = currentAncestor.getParentNode();
+ }
+
+ return null;
+ }
+
+ protected org.w3c.dom.Attr getNamespaceAttr(String prefix) {
+ NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
+ if (!"".equals(prefix))
+ prefix = ":"+prefix;
+ while (eachNamespace.hasNext()) {
+ org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
+ if (!"".equals(prefix)) {
+ if (namespaceDecl.getNodeName().endsWith(prefix))
+ return namespaceDecl;
+ } else {
+ if (namespaceDecl.getNodeName().equals("xmlns"))
+ return namespaceDecl;
+ }
+ }
+ return null;
+ }
+
+ public NamespaceContextIterator getNamespaceContextNodes() {
+ return getNamespaceContextNodes(true);
+ }
+
+ public NamespaceContextIterator getNamespaceContextNodes(boolean traverseStack) {
+ return new NamespaceContextIterator(this, traverseStack);
+ }
+
+ public SOAPElement addChildElement(
+ String localName,
+ String prefix,
+ String uri)
+ throws SOAPException {
+
+ SOAPElement newElement = createElement(NameImpl.create(localName, prefix, uri));
+ addNode(newElement);
+ return convertToSoapElement(newElement);
+ }
+
+ public SOAPElement addChildElement(SOAPElement element)
+ throws SOAPException {
+
+ // check if Element falls in SOAP 1.1 or 1.2 namespace.
+ String elementURI = element.getElementName().getURI();
+ String localName = element.getLocalName();
+
+ if ((SOAPConstants.URI_NS_SOAP_ENVELOPE).equals(elementURI)
+ || (SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE).equals(elementURI)) {
+
+
+ if ("Envelope".equalsIgnoreCase(localName) ||
+ "Header".equalsIgnoreCase(localName) || "Body".equalsIgnoreCase(localName)) {
+ log.severe("SAAJ0103.impl.cannot.add.fragements");
+ throw new SOAPExceptionImpl(
+ "Cannot add fragments which contain elements "
+ + "which are in the SOAP namespace");
+ }
+
+ if ("Fault".equalsIgnoreCase(localName) && !"Body".equalsIgnoreCase(this.getLocalName())) {
+ log.severe("SAAJ0154.impl.adding.fault.to.nonbody");
+ throw new SOAPExceptionImpl("Cannot add a SOAPFault as a child of " + this.getLocalName());
+ }
+
+ if ("Detail".equalsIgnoreCase(localName) && !"Fault".equalsIgnoreCase(this.getLocalName())) {
+ log.severe("SAAJ0155.impl.adding.detail.nonfault");
+ throw new SOAPExceptionImpl("Cannot add a Detail as a child of " + this.getLocalName());
+ }
+
+ if ("Fault".equalsIgnoreCase(localName)) {
+ // if body is not empty throw an exception
+ if (!elementURI.equals(this.getElementName().getURI())) {
+ log.severe("SAAJ0158.impl.version.mismatch.fault");
+ throw new SOAPExceptionImpl("SOAP Version mismatch encountered when trying to add SOAPFault to SOAPBody");
+ }
+ Iterator it = this.getChildElements();
+ if (it.hasNext()) {
+ log.severe("SAAJ0156.impl.adding.fault.error");
+ throw new SOAPExceptionImpl("Cannot add SOAPFault as a child of a non-Empty SOAPBody");
+ }
+ }
+ }
+
+ // preserve the encodingStyle attr as it may get lost in the import
+ String encodingStyle = element.getEncodingStyle();
+
+ ElementImpl importedElement = (ElementImpl) importElement(element);
+ addNode(importedElement);
+
+ if (encodingStyle != null)
+ importedElement.setEncodingStyle(encodingStyle);
+
+ return convertToSoapElement(importedElement);
+ }
+
+ protected Element importElement(Element element) {
+ Document document = getOwnerDocument();
+ Document oldDocument = element.getOwnerDocument();
+ if (!oldDocument.equals(document)) {
+ return (Element) document.importNode(element, true);
+ } else {
+ return element;
+ }
+ }
+
+ protected SOAPElement addElement(Name name) throws SOAPException {
+ SOAPElement newElement = createElement(name);
+ addNode(newElement);
+ return circumventBug5034339(newElement);
+ }
+
+ protected SOAPElement addElement(QName name) throws SOAPException {
+ SOAPElement newElement = createElement(name);
+ addNode(newElement);
+ return circumventBug5034339(newElement);
+ }
+
+ protected SOAPElement createElement(Name name) {
+
+ if (isNamespaceQualified(name)) {
+ return (SOAPElement)
+ getOwnerDocument().createElementNS(
+ name.getURI(),
+ name.getQualifiedName());
+ } else {
+ return (SOAPElement)
+ getOwnerDocument().createElement(name.getQualifiedName());
+ }
+ }
+
+ protected SOAPElement createElement(QName name) {
+
+ if (isNamespaceQualified(name)) {
+ return (SOAPElement)
+ getOwnerDocument().createElementNS(
+ name.getNamespaceURI(),
+ getQualifiedName(name));
+ } else {
+ return (SOAPElement)
+ getOwnerDocument().createElement(getQualifiedName(name));
+ }
+ }
+
+ protected void addNode(org.w3c.dom.Node newElement) throws SOAPException {
+ insertBefore(newElement, null);
+
+ if (getOwnerDocument() instanceof DocumentFragment)
+ return;
+
+ if (newElement instanceof ElementImpl) {
+ ElementImpl element = (ElementImpl) newElement;
+ QName elementName = element.getElementQName();
+ if (!"".equals(elementName.getNamespaceURI())) {
+ element.ensureNamespaceIsDeclared(
+ elementName.getPrefix(), elementName.getNamespaceURI());
+ }
+ }
+
+ }
+
+ Element getFirstChildElement() {
+ Node child = getFirstChild();
+ while (child != null) {
+ if (child instanceof Element) {
+ return ((Element) child);
+ }
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+ protected SOAPElement findChild(NameImpl name) {
+ Node eachChild = getFirstChild();
+ while (eachChild != null) {
+ if (eachChild instanceof SOAPElement) {
+ SOAPElement eachChildSoap = (SOAPElement) eachChild;
+ if (eachChildSoap.getElementName().equals(name)) {
+ return eachChildSoap;
+ }
+ }
+ eachChild = eachChild.getNextSibling();
+ }
+ return null;
+ }
+
+ protected SOAPElement findAndConvertChildElement(NameImpl name) {
+ Iterator eachChild = getChildElementNodes();
+ while (eachChild.hasNext()) {
+ SOAPElement child = (SOAPElement) eachChild.next();
+ if (child.getElementName().equals(name)) {
+ return child;
+ }
+ }
+
+ return null;
+ }
+
+ public SOAPElement addTextNode(String text) throws SOAPException {
+ if (text.startsWith(CDATAImpl.cdataUC)
+ || text.startsWith(CDATAImpl.cdataLC))
+ return addCDATA(
+ text.substring(CDATAImpl.cdataUC.length(), text.length() - 3));
+ return addText(text);
+ }
+
+ protected SOAPElement addCDATA(String text) throws SOAPException {
+ org.w3c.dom.Text cdata =
+ (org.w3c.dom.Text) getOwnerDocument().createCDATASection(text);
+ addNode(cdata);
+ return this;
+ }
+
+ protected SOAPElement addText(String text) throws SOAPException {
+ org.w3c.dom.Text textNode =
+ (org.w3c.dom.Text) getOwnerDocument().createTextNode(text);
+ addNode(textNode);
+ return this;
+ }
+
+ public SOAPElement addAttribute(Name name, String value)
+ throws SOAPException {
+ addAttributeBare(name, value);
+ if (!"".equals(name.getURI())) {
+ ensureNamespaceIsDeclared(name.getPrefix(), name.getURI());
+ }
+ return this;
+ }
+
+ public SOAPElement addAttribute(QName qname, String value)
+ throws SOAPException {
+ addAttributeBare(qname, value);
+ if (!"".equals(qname.getNamespaceURI())) {
+ ensureNamespaceIsDeclared(qname.getPrefix(), qname.getNamespaceURI());
+ }
+ return this;
+ }
+
+ private void addAttributeBare(Name name, String value) {
+ addAttributeBare(
+ name.getURI(),
+ name.getPrefix(),
+ name.getQualifiedName(),
+ value);
+ }
+ private void addAttributeBare(QName name, String value) {
+ addAttributeBare(
+ name.getNamespaceURI(),
+ name.getPrefix(),
+ getQualifiedName(name),
+ value);
+ }
+
+ private void addAttributeBare(
+ String uri,
+ String prefix,
+ String qualifiedName,
+ String value) {
+
+ uri = uri.length() == 0 ? null : uri;
+ if (qualifiedName.equals("xmlns")) {
+ uri = XMLNS_URI;
+ }
+
+ if (uri == null) {
+ setAttribute(qualifiedName, value);
+ } else {
+ setAttributeNS(uri, qualifiedName, value);
+ }
+ }
+
+ public SOAPElement addNamespaceDeclaration(String prefix, String uri)
+ throws SOAPException {
+ if (prefix.length() > 0) {
+ setAttributeNS(XMLNS_URI, "xmlns:" + prefix, uri);
+ } else {
+ setAttributeNS(XMLNS_URI, "xmlns", uri);
+ }
+ //Fix for CR:6474641
+ //tryToFindEncodingStyleAttributeName();
+ return this;
+ }
+
+ public String getAttributeValue(Name name) {
+ return getAttributeValueFrom(this, name);
+ }
+
+ public String getAttributeValue(QName qname) {
+ return getAttributeValueFrom(
+ this,
+ qname.getNamespaceURI(),
+ qname.getLocalPart(),
+ qname.getPrefix(),
+ getQualifiedName(qname));
+ }
+
+ public Iterator getAllAttributes() {
+ Iterator i = getAllAttributesFrom(this);
+ ArrayList list = new ArrayList();
+ while (i.hasNext()) {
+ Name name = (Name) i.next();
+ if (!"xmlns".equalsIgnoreCase(name.getPrefix()))
+ list.add(name);
+ }
+ return list.iterator();
+ }
+
+ public Iterator getAllAttributesAsQNames() {
+ Iterator i = getAllAttributesFrom(this);
+ ArrayList list = new ArrayList();
+ while (i.hasNext()) {
+ Name name = (Name) i.next();
+ if (!"xmlns".equalsIgnoreCase(name.getPrefix())) {
+ list.add(NameImpl.convertToQName(name));
+ }
+ }
+ return list.iterator();
+ }
+
+
+ public Iterator getNamespacePrefixes() {
+ return doGetNamespacePrefixes(false);
+ }
+
+ public Iterator getVisibleNamespacePrefixes() {
+ return doGetNamespacePrefixes(true);
+ }
+
+ protected Iterator doGetNamespacePrefixes(final boolean deep) {
+ return new Iterator() {
+ String next = null;
+ String last = null;
+ NamespaceContextIterator eachNamespace =
+ getNamespaceContextNodes(deep);
+
+ void findNext() {
+ while (next == null && eachNamespace.hasNext()) {
+ String attributeKey =
+ eachNamespace.nextNamespaceAttr().getNodeName();
+ if (attributeKey.startsWith("xmlns:")) {
+ next = attributeKey.substring("xmlns:".length());
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ findNext();
+ return next != null;
+ }
+
+ public Object next() {
+ findNext();
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+
+ last = next;
+ next = null;
+ return last;
+ }
+
+ public void remove() {
+ if (last == null) {
+ throw new IllegalStateException();
+ }
+ eachNamespace.remove();
+ next = null;
+ last = null;
+ }
+ };
+ }
+
+ public Name getElementName() {
+ return NameImpl.convertToName(elementQName);
+ }
+
+ public QName getElementQName() {
+ return elementQName;
+ }
+
+ public boolean removeAttribute(Name name) {
+ return removeAttribute(name.getURI(), name.getLocalName());
+ }
+
+ public boolean removeAttribute(QName name) {
+ return removeAttribute(name.getNamespaceURI(), name.getLocalPart());
+ }
+
+ private boolean removeAttribute(String uri, String localName) {
+ String nonzeroLengthUri =
+ (uri == null || uri.length() == 0) ? null : uri;
+ org.w3c.dom.Attr attribute =
+ getAttributeNodeNS(nonzeroLengthUri, localName);
+ if (attribute == null) {
+ return false;
+ }
+ removeAttributeNode(attribute);
+ return true;
+ }
+
+ public boolean removeNamespaceDeclaration(String prefix) {
+ org.w3c.dom.Attr declaration = getNamespaceAttr(prefix);
+ if (declaration == null) {
+ return false;
+ }
+ try {
+ removeAttributeNode(declaration);
+ } catch (DOMException de) {
+ // ignore
+ }
+ return true;
+ }
+
+ public Iterator getChildElements() {
+ return getChildElementsFrom(this);
+ }
+
+ protected SOAPElement convertToSoapElement(Element element) {
+ if (element instanceof SOAPElement) {
+ return (SOAPElement) element;
+ } else {
+ return replaceElementWithSOAPElement(
+ element,
+ (ElementImpl) createElement(NameImpl.copyElementName(element)));
+ }
+ }
+
+ protected static SOAPElement replaceElementWithSOAPElement(
+ Element element,
+ ElementImpl copy) {
+
+ Iterator eachAttribute = getAllAttributesFrom(element);
+ while (eachAttribute.hasNext()) {
+ Name name = (Name) eachAttribute.next();
+ copy.addAttributeBare(name, getAttributeValueFrom(element, name));
+ }
+
+ Iterator eachChild = getChildElementsFrom(element);
+ while (eachChild.hasNext()) {
+ Node nextChild = (Node) eachChild.next();
+ copy.insertBefore(nextChild, null);
+ }
+
+ Node parent = element.getParentNode();
+ if (parent != null) {
+ parent.replaceChild(copy, element);
+ } // XXX else throw an exception?
+
+ return copy;
+ }
+
+ protected Iterator getChildElementNodes() {
+ return new Iterator() {
+ Iterator eachNode = getChildElements();
+ Node next = null;
+ Node last = null;
+
+ public boolean hasNext() {
+ if (next == null) {
+ while (eachNode.hasNext()) {
+ Node node = (Node) eachNode.next();
+ if (node instanceof SOAPElement) {
+ next = node;
+ break;
+ }
+ }
+ }
+ return next != null;
+ }
+
+ public Object next() {
+ if (hasNext()) {
+ last = next;
+ next = null;
+ return last;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ if (last == null) {
+ throw new IllegalStateException();
+ }
+ Node target = last;
+ last = null;
+ removeChild(target);
+ }
+ };
+ }
+
+ public Iterator getChildElements(final Name name) {
+ return getChildElements(name.getURI(), name.getLocalName());
+ }
+
+ public Iterator getChildElements(final QName qname) {
+ return getChildElements(qname.getNamespaceURI(), qname.getLocalPart());
+ }
+
+ private Iterator getChildElements(final String nameUri, final String nameLocal) {
+ return new Iterator() {
+ Iterator eachElement = getChildElementNodes();
+ Node next = null;
+ Node last = null;
+
+ public boolean hasNext() {
+ if (next == null) {
+ while (eachElement.hasNext()) {
+ Node element = (Node) eachElement.next();
+ String elementUri = element.getNamespaceURI();
+ elementUri = elementUri == null ? "" : elementUri;
+ String elementName = element.getLocalName();
+ if (elementUri.equals(nameUri)
+ && elementName.equals(nameLocal)) {
+ next = element;
+ break;
+ }
+ }
+ }
+ return next != null;
+ }
+
+ public Object next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ last = next;
+ next = null;
+ return last;
+ }
+
+ public void remove() {
+ if (last == null) {
+ throw new IllegalStateException();
+ }
+ Node target = last;
+ last = null;
+ removeChild(target);
+ }
+ };
+ }
+
+ public void removeContents() {
+ Node currentChild = getFirstChild();
+
+ while (currentChild != null) {
+ Node temp = currentChild.getNextSibling();
+ if (currentChild instanceof javax.xml.soap.Node) {
+ ((javax.xml.soap.Node) currentChild).detachNode();
+ } else {
+ Node parent = currentChild.getParentNode();
+ if (parent != null) {
+ parent.removeChild(currentChild);
+ }
+
+ }
+ currentChild = temp;
+ }
+ }
+
+ public void setEncodingStyle(String encodingStyle) throws SOAPException {
+ if (!"".equals(encodingStyle)) {
+ try {
+ new URI(encodingStyle);
+ } catch (URISyntaxException m) {
+ log.log(
+ Level.SEVERE,
+ "SAAJ0105.impl.encoding.style.mustbe.valid.URI",
+ new String[] { encodingStyle });
+ throw new IllegalArgumentException(
+ "Encoding style (" + encodingStyle + ") should be a valid URI");
+ }
+ }
+ encodingStyleAttribute.setValue(encodingStyle);
+ tryToFindEncodingStyleAttributeName();
+ }
+
+ public String getEncodingStyle() {
+ String encodingStyle = encodingStyleAttribute.getValue();
+ if (encodingStyle != null)
+ return encodingStyle;
+ String soapNamespace = getSOAPNamespace();
+ if (soapNamespace != null) {
+ Attr attr = getAttributeNodeNS(soapNamespace, "encodingStyle");
+ if (attr != null) {
+ encodingStyle = attr.getValue();
+ try {
+ setEncodingStyle(encodingStyle);
+ } catch (SOAPException se) {
+ // has to be ignored
+ }
+ return encodingStyle;
+ }
+ }
+ return null;
+ }
+
+ // Node methods
+ public String getValue() {
+ javax.xml.soap.Node valueNode = getValueNode();
+ return valueNode == null ? null : valueNode.getValue();
+ }
+
+ public void setValue(String value) {
+ Node valueNode = getValueNodeStrict();
+ if (valueNode != null) {
+ valueNode.setNodeValue(value);
+ } else {
+ try {
+ addTextNode(value);
+ } catch (SOAPException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ }
+
+ protected Node getValueNodeStrict() {
+ Node node = getFirstChild();
+ if (node != null) {
+ if (node.getNextSibling() == null
+ && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
+ return node;
+ } else {
+ log.severe("SAAJ0107.impl.elem.child.not.single.text");
+ throw new IllegalStateException();
+ }
+ }
+
+ return null;
+ }
+
+ protected javax.xml.soap.Node getValueNode() {
+ Iterator i = getChildElements();
+ while (i.hasNext()) {
+ javax.xml.soap.Node n = (javax.xml.soap.Node) i.next();
+ if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE ||
+ n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
+ // TODO: Hack to fix text node split into multiple lines.
+ normalize();
+ // Should remove the normalization step when this gets fixed in
+ // DOM/Xerces.
+ return (javax.xml.soap.Node) n;
+ }
+ }
+ return null;
+ }
+
+ public void setParentElement(SOAPElement element) throws SOAPException {
+ if (element == null) {
+ log.severe("SAAJ0106.impl.no.null.to.parent.elem");
+ throw new SOAPException("Cannot pass NULL to setParentElement");
+ }
+ element.addChildElement(this);
+ findEncodingStyleAttributeName();
+ }
+
+ protected void findEncodingStyleAttributeName() throws SOAPException {
+ String soapNamespace = getSOAPNamespace();
+ if (soapNamespace != null) {
+ String soapNamespacePrefix = getNamespacePrefix(soapNamespace);
+ if (soapNamespacePrefix != null) {
+ setEncodingStyleNamespace(soapNamespace, soapNamespacePrefix);
+ }
+ }
+ }
+
+ protected void setEncodingStyleNamespace(
+ String soapNamespace,
+ String soapNamespacePrefix)
+ throws SOAPException {
+ Name encodingStyleAttributeName =
+ NameImpl.create(
+ "encodingStyle",
+ soapNamespacePrefix,
+ soapNamespace);
+ encodingStyleAttribute.setName(encodingStyleAttributeName);
+ }
+
+ public SOAPElement getParentElement() {
+ Node parentNode = getParentNode();
+ if (parentNode instanceof SOAPDocument) {
+ return null;
+ }
+ return (SOAPElement) parentNode;
+ }
+
+ protected String getSOAPNamespace() {
+ String soapNamespace = null;
+
+ SOAPElement antecedent = this;
+ while (antecedent != null) {
+ Name antecedentName = antecedent.getElementName();
+ String antecedentNamespace = antecedentName.getURI();
+
+ if (NameImpl.SOAP11_NAMESPACE.equals(antecedentNamespace)
+ || NameImpl.SOAP12_NAMESPACE.equals(antecedentNamespace)) {
+
+ soapNamespace = antecedentNamespace;
+ break;
+ }
+
+ antecedent = antecedent.getParentElement();
+ }
+
+ return soapNamespace;
+ }
+
+ public void detachNode() {
+ Node parent = getParentNode();
+ if (parent != null) {
+ parent.removeChild(this);
+ }
+ encodingStyleAttribute.clearNameAndValue();
+ // Fix for CR: 6474641
+ //tryToFindEncodingStyleAttributeName();
+ }
+
+ public void tryToFindEncodingStyleAttributeName() {
+ try {
+ findEncodingStyleAttributeName();
+ } catch (SOAPException e) { /*okay to fail*/
+ }
+ }
+
+ public void recycleNode() {
+ detachNode();
+ // TBD
+ // - add this to the factory so subsequent
+ // creations can reuse this object.
+ }
+
+ class AttributeManager {
+ Name attributeName = null;
+ String attributeValue = null;
+
+ public void setName(Name newName) throws SOAPException {
+ clearAttribute();
+ attributeName = newName;
+ reconcileAttribute();
+ }
+ public void clearName() {
+ clearAttribute();
+ attributeName = null;
+ }
+ public void setValue(String value) throws SOAPException {
+ attributeValue = value;
+ reconcileAttribute();
+ }
+ public Name getName() {
+ return attributeName;
+ }
+ public String getValue() {
+ return attributeValue;
+ }
+
+ /** Note: to be used only in detachNode method */
+ public void clearNameAndValue() {
+ attributeName = null;
+ attributeValue = null;
+ }
+
+ private void reconcileAttribute() throws SOAPException {
+ if (attributeName != null) {
+ removeAttribute(attributeName);
+ if (attributeValue != null) {
+ addAttribute(attributeName, attributeValue);
+ }
+ }
+ }
+ private void clearAttribute() {
+ if (attributeName != null) {
+ removeAttribute(attributeName);
+ }
+ }
+ }
+
+ protected static org.w3c.dom.Attr getNamespaceAttrFrom(
+ Element element,
+ String prefix) {
+ NamespaceContextIterator eachNamespace =
+ new NamespaceContextIterator(element);
+ while (eachNamespace.hasNext()) {
+ org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
+ String declaredPrefix =
+ NameImpl.getLocalNameFromTagName(namespaceDecl.getNodeName());
+ if (declaredPrefix.equals(prefix)) {
+ return namespaceDecl;
+ }
+ }
+ return null;
+ }
+
+ protected static Iterator getAllAttributesFrom(final Element element) {
+ final NamedNodeMap attributes = element.getAttributes();
+
+ return new Iterator() {
+ int attributesLength = attributes.getLength();
+ int attributeIndex = 0;
+ String currentName;
+
+ public boolean hasNext() {
+ return attributeIndex < attributesLength;
+ }
+
+ public Object next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ Node current = attributes.item(attributeIndex++);
+ currentName = current.getNodeName();
+
+ String prefix = NameImpl.getPrefixFromTagName(currentName);
+ if (prefix.length() == 0) {
+ return NameImpl.createFromUnqualifiedName(currentName);
+ } else {
+ Name attributeName =
+ NameImpl.createFromQualifiedName(
+ currentName,
+ current.getNamespaceURI());
+ return attributeName;
+ }
+ }
+
+ public void remove() {
+ if (currentName == null) {
+ throw new IllegalStateException();
+ }
+ attributes.removeNamedItem(currentName);
+ }
+ };
+ }
+
+ protected static String getAttributeValueFrom(Element element, Name name) {
+ return getAttributeValueFrom(
+ element,
+ name.getURI(),
+ name.getLocalName(),
+ name.getPrefix(),
+ name.getQualifiedName());
+ }
+
+ private static String getAttributeValueFrom(
+ Element element,
+ String uri,
+ String localName,
+ String prefix,
+ String qualifiedName) {
+
+ String nonzeroLengthUri =
+ (uri == null || uri.length() == 0) ? null : uri;
+
+ boolean mustUseGetAttributeNodeNS = (nonzeroLengthUri != null);
+
+ if (mustUseGetAttributeNodeNS) {
+
+ if (!element.hasAttributeNS(uri, localName)) {
+ return null;
+ }
+
+ String attrValue =
+ element.getAttributeNS(nonzeroLengthUri, localName);
+
+ return attrValue;
+ }
+
+ Attr attribute = null;
+ attribute = element.getAttributeNode(qualifiedName);
+
+ return attribute == null ? null : attribute.getValue();
+ }
+
+ protected static Iterator getChildElementsFrom(final Element element) {
+ return new Iterator() {
+ Node next = element.getFirstChild();
+ Node nextNext = null;
+ Node last = null;
+
+ public boolean hasNext() {
+ if (next != null) {
+ return true;
+ }
+ if (next == null && nextNext != null) {
+ next = nextNext;
+ }
+
+ return next != null;
+ }
+
+ public Object next() {
+ if (hasNext()) {
+ last = next;
+ next = null;
+
+ if ((element instanceof ElementImpl)
+ && (last instanceof Element)) {
+ last =
+ ((ElementImpl) element).convertToSoapElement(
+ (Element) last);
+ }
+
+ nextNext = last.getNextSibling();
+ return last;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ if (last == null) {
+ throw new IllegalStateException();
+ }
+ Node target = last;
+ last = null;
+ element.removeChild(target);
+ }
+ };
+ }
+
+ public static String getQualifiedName(QName name) {
+ String prefix = name.getPrefix();
+ String localName = name.getLocalPart();
+ String qualifiedName = null;
+
+ if (prefix != null && prefix.length() > 0) {
+ qualifiedName = prefix + ":" + localName;
+ } else {
+ qualifiedName = localName;
+ }
+ return qualifiedName;
+ }
+
+ public static String getLocalPart(String qualifiedName) {
+ if (qualifiedName == null) {
+ // Log
+ throw new IllegalArgumentException("Cannot get local name for a \"null\" qualified name");
+ }
+
+ int index = qualifiedName.indexOf(':');
+ if (index < 0)
+ return qualifiedName;
+ else
+ return qualifiedName.substring(index + 1);
+ }
+
+ public static String getPrefix(String qualifiedName) {
+ if (qualifiedName == null) {
+ // Log
+ throw new IllegalArgumentException("Cannot get prefix for a \"null\" qualified name");
+ }
+
+ int index = qualifiedName.indexOf(':');
+ if (index < 0)
+ return "";
+ else
+ return qualifiedName.substring(0, index);
+ }
+
+ protected boolean isNamespaceQualified(Name name) {
+ return !"".equals(name.getURI());
+ }
+
+ protected boolean isNamespaceQualified(QName name) {
+ return !"".equals(name.getNamespaceURI());
+ }
+
+ protected SOAPElement circumventBug5034339(SOAPElement element) {
+
+ Name elementName = element.getElementName();
+ if (!isNamespaceQualified(elementName)) {
+ String prefix = elementName.getPrefix();
+ String defaultNamespace = getNamespaceURI(prefix);
+ if (defaultNamespace != null) {
+ Name newElementName =
+ NameImpl.create(
+ elementName.getLocalName(),
+ elementName.getPrefix(),
+ defaultNamespace);
+ SOAPElement newElement = createElement(newElementName);
+ replaceChild(newElement, element);
+ return newElement;
+ }
+ }
+ return element;
+ }
+
+ //TODO: This is a temporary SAAJ workaround for optimizing XWS
+ // should be removed once the corresponding JAXP bug is fixed
+ // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
+ public void setAttributeNS(
+ String namespaceURI,String qualifiedName, String value) {
+ int index = qualifiedName.indexOf(':');
+ String localName;
+ if (index < 0)
+ localName = qualifiedName;
+ else
+ localName = qualifiedName.substring(index + 1);
+
+ // Workaround for bug 6467808 - This needs to be fixed in JAXP
+
+ // Rolling back this fix, this is a wrong fix, infact its causing other regressions in JAXWS tck and
+ // other tests, because of this change the namespace declarations on soapenv:Fault element are never
+ // picked up. The fix for bug 6467808 should be in JAXP.
+// if(elementQName.getLocalPart().equals("Fault") &&
+// (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(value) ||
+// SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(value)))
+// return;
+
+ super.setAttributeNS(namespaceURI,qualifiedName,value);
+ //String tmpLocalName = this.getLocalName();
+ String tmpURI = this.getNamespaceURI();
+ boolean isIDNS = false;
+ if( tmpURI != null && (tmpURI.equals(DSIG_NS) || tmpURI.equals(XENC_NS))){
+ isIDNS = true;
+ }
+ //No need to check for Signature/encryption element
+ //just check for namespace.
+ if(localName.equals("Id")){
+ if(namespaceURI == null || namespaceURI.equals("")){
+ setIdAttribute(localName,true);
+ }else if(isIDNS || WSU_NS.equals(namespaceURI)){
+ setIdAttributeNS(namespaceURI,localName,true);
+ }
+ }
+
+ }
+
+}