1 /*
   2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.messaging.saaj.soap.impl;
  27 
  28 import java.net.URI;
  29 import java.net.URISyntaxException;
  30 import java.util.logging.Level;
  31 import java.util.logging.Logger;
  32 
  33 import javax.xml.namespace.QName;
  34 
  35 import org.w3c.dom.Node;
  36 
  37 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
  38 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocument;
  39 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl;
  40 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
  41 import com.sun.xml.internal.messaging.saaj.util.LogDomainConstants;
  42 import com.sun.xml.internal.messaging.saaj.util.NamespaceContextIterator;
  43 import java.util.ArrayList;
  44 import java.util.Iterator;
  45 import java.util.NoSuchElementException;
  46 import javax.xml.soap.Name;
  47 import javax.xml.soap.SOAPBodyElement;
  48 import javax.xml.soap.SOAPConstants;
  49 import javax.xml.soap.SOAPElement;
  50 import javax.xml.soap.SOAPException;
  51 import org.w3c.dom.Attr;
  52 import org.w3c.dom.CharacterData;
  53 import org.w3c.dom.DOMException;
  54 import org.w3c.dom.Document;
  55 import org.w3c.dom.DocumentFragment;
  56 import org.w3c.dom.Element;
  57 import org.w3c.dom.NamedNodeMap;
  58 import org.w3c.dom.NodeList;
  59 import org.w3c.dom.TypeInfo;
  60 import org.w3c.dom.UserDataHandler;
  61 
  62 public class ElementImpl implements SOAPElement, SOAPBodyElement {
  63 
  64     public static final String DSIG_NS = "http://www.w3.org/2000/09/xmldsig#".intern();
  65     public static final String XENC_NS = "http://www.w3.org/2001/04/xmlenc#".intern();
  66     public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd".intern();
  67 
  68     private transient AttributeManager encodingStyleAttribute = new AttributeManager();
  69 
  70     protected QName elementQName;
  71 
  72     private Element element;
  73 
  74     private SOAPDocumentImpl soapDocument;
  75 
  76     @Override
  77     public String getTagName() {
  78         return element.getTagName();
  79     }
  80 
  81     @Override
  82     public String getAttribute(String name) {
  83         return element.getAttribute(name);
  84     }
  85 
  86     @Override
  87     public void setAttribute(String name, String value) throws DOMException {
  88         boolean isQualifiedName = (name.indexOf(":") > 0);
  89         //this is because of BugfixTest#testCR7020991, after removal internal dependencies
  90         //SOAPDocumentImpl#createAttribute is not called anymore from xerces parent
  91         if (isQualifiedName) {
  92             String nsUri = null;
  93             String prefix = name.substring(0, name.indexOf(":"));
  94             //cannot do anything to resolve the URI if prefix is not
  95             //XMLNS.
  96             if (XMLNS.equals(prefix)) {
  97                 nsUri = ElementImpl.XMLNS_URI;
  98                 setAttributeNS(nsUri, name, value);
  99                 return;
 100             }
 101         }
 102         element.setAttribute(name, value);
 103     }
 104 
 105     @Override
 106     public void removeAttribute(String name) throws DOMException {
 107         element.removeAttribute(name);
 108     }
 109 
 110     @Override
 111     public Attr getAttributeNode(String name) {
 112         return element.getAttributeNode(name);
 113     }
 114 
 115     @Override
 116     public Attr setAttributeNode(Attr newAttr) throws DOMException {
 117         return element.setAttributeNode(newAttr);
 118     }
 119 
 120     @Override
 121     public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
 122         return element.removeAttributeNode(oldAttr);
 123     }
 124 
 125     @Override
 126     public NodeList getElementsByTagName(String name) {
 127         return new NodeListImpl(soapDocument, element.getElementsByTagName(name));
 128     }
 129 
 130     @Override
 131     public String getAttributeNS(String namespaceURI, String localName) throws DOMException {
 132         return element.getAttributeNS(namespaceURI, localName);
 133     }
 134 
 135     protected static final Logger log =
 136         Logger.getLogger(LogDomainConstants.SOAP_IMPL_DOMAIN,
 137                          "com.sun.xml.internal.messaging.saaj.soap.impl.LocalStrings");
 138 
 139     /**
 140      * XML Information Set REC
 141      * all namespace attributes (including those named xmlns,
 142      * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/
 143      */
 144     public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern();
 145 
 146     /**
 147      * The XML Namespace ("http://www.w3.org/XML/1998/namespace"). This is
 148      * the Namespace URI that is automatically mapped to the "xml" prefix.
 149      */
 150     public final static String XML_URI = "http://www.w3.org/XML/1998/namespace".intern();
 151 
 152     private final static String XMLNS = "xmlns".intern();
 153 
 154     public ElementImpl(SOAPDocumentImpl ownerDoc, Name name) {
 155         this.soapDocument = ownerDoc;
 156         this.element = ownerDoc.getDomDocument().createElementNS(name.getURI(), name.getQualifiedName());
 157         elementQName = NameImpl.convertToQName(name);
 158         soapDocument.register(this);
 159     }
 160 
 161     public ElementImpl(SOAPDocumentImpl ownerDoc, QName name) {
 162         this.soapDocument = ownerDoc;
 163         this.element = ownerDoc.getDomDocument().createElementNS(name.getNamespaceURI(), getQualifiedName(name));
 164         elementQName = name;
 165         soapDocument.register(this);
 166     }
 167 
 168     public ElementImpl(SOAPDocumentImpl ownerDoc, Element domElement) {
 169         this.element = domElement;
 170         this.soapDocument = ownerDoc;
 171         this.elementQName = new QName(domElement.getNamespaceURI(), domElement.getLocalName());
 172         soapDocument.register(this);
 173     }
 174 
 175     public ElementImpl(
 176         SOAPDocumentImpl ownerDoc,
 177         String uri,
 178         String qualifiedName) {
 179 
 180         this.soapDocument = ownerDoc;
 181         this.element = ownerDoc.getDomDocument().createElementNS(uri, qualifiedName);
 182         elementQName =
 183             new QName(uri, getLocalPart(qualifiedName), getPrefix(qualifiedName));
 184         soapDocument.register(this);
 185     }
 186 
 187     public void ensureNamespaceIsDeclared(String prefix, String uri) {
 188         String alreadyDeclaredUri = getNamespaceURI(prefix);
 189         if (alreadyDeclaredUri == null || !alreadyDeclaredUri.equals(uri)) {
 190             try {
 191                 addNamespaceDeclaration(prefix, uri);
 192             } catch (SOAPException e) { /*ignore*/
 193             }
 194         }
 195     }
 196 
 197     @Override
 198     public Document getOwnerDocument() {
 199         return soapDocument;
 200     }
 201 
 202     @Override
 203     public Node insertBefore(Node newChild, Node refChild) throws DOMException {
 204         return soapDocument.findIfPresent(element.insertBefore(soapDocument.getDomNode(newChild), soapDocument.getDomNode(refChild)));
 205     }
 206 
 207     @Override
 208     public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
 209         return soapDocument.findIfPresent(element.replaceChild(soapDocument.getDomNode(newChild), soapDocument.getDomNode(oldChild)));
 210     }
 211 
 212     @Override
 213     public Node removeChild(Node oldChild) throws DOMException {
 214         return soapDocument.findIfPresent(element.removeChild(soapDocument.getDomNode(oldChild)));
 215     }
 216 
 217     @Override
 218     public Node appendChild(Node newChild) throws DOMException {
 219         return soapDocument.findIfPresent(element.appendChild(soapDocument.getDomNode(newChild)));
 220     }
 221 
 222     @Override
 223     public boolean hasChildNodes() {
 224         return element.hasChildNodes();
 225     }
 226 
 227     @Override
 228     public Node cloneNode(boolean deep) {
 229         Node elementNSNode = element.cloneNode(deep);
 230         soapDocument.registerChildNodes(elementNSNode, deep);
 231         return soapDocument.findIfPresent(soapDocument.getDomNode(elementNSNode));
 232     }
 233 
 234     @Override
 235     public void normalize() {
 236         element.normalize();
 237     }
 238 
 239     @Override
 240     public boolean isSupported(String feature, String version) {
 241         return element.isSupported(feature, version);
 242     }
 243 
 244     @Override
 245     public String getNamespaceURI() {
 246         return element.getNamespaceURI();
 247     }
 248 
 249     @Override
 250     public String getPrefix() {
 251         return element.getPrefix();
 252     }
 253 
 254     @Override
 255     public void setPrefix(String prefix) throws DOMException {
 256         element.setPrefix(prefix);
 257     }
 258 
 259     @Override
 260     public String getLocalName() {
 261         return element.getLocalName();
 262     }
 263 
 264     @Override
 265     public boolean hasAttributes() {
 266         return element.hasAttributes();
 267     }
 268 
 269     @Override
 270     public String getBaseURI() {
 271         return element.getBaseURI();
 272     }
 273 
 274     @Override
 275     public short compareDocumentPosition(Node other) throws DOMException {
 276         return element.compareDocumentPosition(soapDocument.getDomNode(other));
 277     }
 278 
 279     @Override
 280     public String getTextContent() throws DOMException {
 281         return element.getTextContent();
 282     }
 283 
 284     @Override
 285     public void setTextContent(String textContent) throws DOMException {
 286         element.setTextContent(textContent);
 287     }
 288 
 289     @Override
 290     public boolean isSameNode(Node other) {
 291         return element.isSameNode(soapDocument.getDomNode(other));
 292     }
 293 
 294     @Override
 295     public String lookupPrefix(String namespaceURI) {
 296         return element.lookupPrefix(namespaceURI);
 297     }
 298 
 299     @Override
 300     public boolean isDefaultNamespace(String namespaceURI) {
 301         return element.isDefaultNamespace(namespaceURI);
 302     }
 303 
 304     @Override
 305     public String lookupNamespaceURI(String prefix) {
 306         return element.lookupNamespaceURI(prefix);
 307     }
 308 
 309     @Override
 310     public boolean isEqualNode(Node arg) {
 311         return element.isEqualNode(soapDocument.getDomNode(arg));
 312     }
 313 
 314     @Override
 315     public Object getFeature(String feature, String version) {
 316         return element.getFeature(feature, version);
 317     }
 318 
 319     @Override
 320     public Object setUserData(String key, Object data, UserDataHandler handler) {
 321         return element.setUserData(key, data, handler);
 322     }
 323 
 324     @Override
 325     public Object getUserData(String key) {
 326         return element.getUserData(key);
 327     }
 328 
 329     @Override
 330     public SOAPElement addChildElement(Name name) throws SOAPException {
 331         return  addElement(name);
 332     }
 333 
 334     @Override
 335     public SOAPElement addChildElement(QName qname) throws SOAPException {
 336         return  addElement(qname);
 337     }
 338 
 339     @Override
 340     public SOAPElement addChildElement(String localName) throws SOAPException {
 341         String nsUri = getNamespaceURI("");
 342         Name name = (nsUri == null || nsUri.isEmpty())
 343                 ?  NameImpl.createFromUnqualifiedName(localName)
 344                 :  NameImpl.createFromQualifiedName(localName, nsUri);
 345         return addChildElement(name);
 346     }
 347 
 348     @Override
 349     public SOAPElement addChildElement(String localName, String prefix)
 350         throws SOAPException {
 351         String uri = getNamespaceURI(prefix);
 352         if (uri == null) {
 353             log.log(
 354                 Level.SEVERE,
 355                 "SAAJ0101.impl.parent.of.body.elem.mustbe.body",
 356                 new String[] { prefix });
 357             throw new SOAPExceptionImpl(
 358                 "Unable to locate namespace for prefix " + prefix);
 359         }
 360         return addChildElement(localName, prefix, uri);
 361     }
 362 
 363     @Override
 364     public String getNamespaceURI(String prefix) {
 365 
 366         if ("xmlns".equals(prefix)) {
 367             return XMLNS_URI;
 368         }
 369 
 370         if("xml".equals(prefix)) {
 371             return XML_URI;
 372         }
 373 
 374         if ("".equals(prefix)) {
 375 
 376             org.w3c.dom.Node currentAncestor = this;
 377             while (currentAncestor != null &&
 378                    !(currentAncestor instanceof Document)) {
 379 
 380                 if (currentAncestor instanceof ElementImpl) {
 381                     /*
 382                     QName name = ((ElementImpl) currentAncestor).getElementQName();
 383                     if (prefix.equals(name.getPrefix())) {
 384                         String uri = name.getNamespaceURI();
 385                         if ("".equals(uri)) {
 386                             return null;
 387                         }
 388                         else {
 389                             return uri;
 390                         }
 391                     }*/
 392                     if (((Element) currentAncestor).hasAttributeNS(
 393                             XMLNS_URI, "xmlns")) {
 394 
 395                         String uri =
 396                             ((Element) currentAncestor).getAttributeNS(
 397                                 XMLNS_URI, "xmlns");
 398                         if ("".equals(uri))
 399                             return null;
 400                         else {
 401                             return uri;
 402                         }
 403                     }
 404                 }
 405                 currentAncestor = currentAncestor.getParentNode();
 406             }
 407 
 408         } else if (prefix != null) {
 409             // Find if there's an ancester whose name contains this prefix
 410             org.w3c.dom.Node currentAncestor = this;
 411 
 412 //            String uri = currentAncestor.lookupNamespaceURI(prefix);
 413 //            return uri;
 414             while (currentAncestor != null &&
 415                    !(currentAncestor instanceof Document)) {
 416 
 417                /* if (prefix.equals(currentAncestor.getPrefix())) {
 418                     String uri = currentAncestor.getNamespaceURI();
 419                     // this is because the javadoc says getNamespaceURI() is not a computed value
 420                     // and URI for a non-empty prefix cannot be null
 421                     if (uri != null)
 422                         return uri;
 423                 }*/
 424                 //String uri = currentAncestor.lookupNamespaceURI(prefix);
 425                 //if (uri != null) {
 426                 //    return uri;
 427                 //}
 428 
 429                 if (((Element) currentAncestor).hasAttributeNS(
 430                         XMLNS_URI, prefix)) {
 431                     return ((Element) currentAncestor).getAttributeNS(
 432                                XMLNS_URI, prefix);
 433                 }
 434 
 435                 currentAncestor = currentAncestor.getParentNode();
 436             }
 437         }
 438 
 439         return null;
 440     }
 441 
 442     @Override
 443     public SOAPElement setElementQName(QName newName) throws SOAPException {
 444         ElementImpl copy =
 445             new ElementImpl((SOAPDocumentImpl) getOwnerDocument(), newName);
 446         return replaceElementWithSOAPElement(this,copy);
 447     }
 448 
 449     @Override
 450     public QName createQName(String localName, String prefix)
 451         throws SOAPException {
 452         String uri = getNamespaceURI(prefix);
 453         if (uri == null) {
 454             log.log(Level.SEVERE, "SAAJ0102.impl.cannot.locate.ns",
 455                     new Object[] {prefix});
 456             throw new SOAPException("Unable to locate namespace for prefix "
 457                                     + prefix);
 458         }
 459         return new QName(uri, localName, prefix);
 460     }
 461 
 462     public String getNamespacePrefix(String uri) {
 463 
 464         NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
 465         while (eachNamespace.hasNext()) {
 466             org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
 467             if (namespaceDecl.getNodeValue().equals(uri)) {
 468                 String candidatePrefix = namespaceDecl.getLocalName();
 469                 if ("xmlns".equals(candidatePrefix))
 470                     return "";
 471                 else
 472                     return candidatePrefix;
 473             }
 474         }
 475 
 476         // Find if any of the ancestors' name has this uri
 477         org.w3c.dom.Node currentAncestor = this;
 478         while (currentAncestor != null &&
 479                !(currentAncestor instanceof Document)) {
 480 
 481             if (uri.equals(currentAncestor.getNamespaceURI()))
 482                 return currentAncestor.getPrefix();
 483             currentAncestor = currentAncestor.getParentNode();
 484         }
 485 
 486         return null;
 487     }
 488 
 489     protected org.w3c.dom.Attr getNamespaceAttr(String prefix) {
 490         NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
 491         if (!"".equals(prefix))
 492             prefix = ":"+prefix;
 493         while (eachNamespace.hasNext()) {
 494             org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
 495             if (!"".equals(prefix)) {
 496                 if (namespaceDecl.getNodeName().endsWith(prefix))
 497                     return namespaceDecl;
 498             } else {
 499                 if (namespaceDecl.getNodeName().equals("xmlns"))
 500                     return namespaceDecl;
 501             }
 502         }
 503         return null;
 504     }
 505 
 506     public NamespaceContextIterator getNamespaceContextNodes() {
 507         return getNamespaceContextNodes(true);
 508     }
 509 
 510     public NamespaceContextIterator getNamespaceContextNodes(boolean traverseStack) {
 511         return new NamespaceContextIterator(this, traverseStack);
 512     }
 513 
 514     @Override
 515     public SOAPElement addChildElement(
 516         String localName,
 517         String prefix,
 518         String uri)
 519         throws SOAPException {
 520 
 521         SOAPElement newElement = createElement(NameImpl.create(localName, prefix, uri));
 522         addNode(newElement);
 523         return convertToSoapElement(newElement);
 524     }
 525 
 526     @Override
 527     public SOAPElement addChildElement(SOAPElement element)
 528         throws SOAPException {
 529 
 530         // check if Element falls in SOAP 1.1 or 1.2 namespace.
 531         String elementURI = element.getElementName().getURI();
 532         String localName = element.getLocalName();
 533 
 534         if ((SOAPConstants.URI_NS_SOAP_ENVELOPE).equals(elementURI)
 535             || (SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE).equals(elementURI)) {
 536 
 537 
 538             if ("Envelope".equalsIgnoreCase(localName) ||
 539                 "Header".equalsIgnoreCase(localName) || "Body".equalsIgnoreCase(localName)) {
 540                 log.severe("SAAJ0103.impl.cannot.add.fragements");
 541                 throw new SOAPExceptionImpl(
 542                     "Cannot add fragments which contain elements "
 543                         + "which are in the SOAP namespace");
 544             }
 545 
 546             if ("Fault".equalsIgnoreCase(localName) && !"Body".equalsIgnoreCase(this.getLocalName())) {
 547                 log.severe("SAAJ0154.impl.adding.fault.to.nonbody");
 548                 throw new SOAPExceptionImpl("Cannot add a SOAPFault as a child of " + this.getLocalName());
 549             }
 550 
 551             if ("Detail".equalsIgnoreCase(localName) && !"Fault".equalsIgnoreCase(this.getLocalName())) {
 552                 log.severe("SAAJ0155.impl.adding.detail.nonfault");
 553                 throw new SOAPExceptionImpl("Cannot add a Detail as a child of " + this.getLocalName());
 554             }
 555 
 556             if ("Fault".equalsIgnoreCase(localName)) {
 557                // if body is not empty throw an exception
 558                if (!elementURI.equals(this.getElementName().getURI())) {
 559                    log.severe("SAAJ0158.impl.version.mismatch.fault");
 560                    throw new SOAPExceptionImpl("SOAP Version mismatch encountered when trying to add SOAPFault to SOAPBody");
 561                }
 562                Iterator<javax.xml.soap.Node> it = this.getChildElements();
 563                if (it.hasNext()) {
 564                    log.severe("SAAJ0156.impl.adding.fault.error");
 565                    throw new SOAPExceptionImpl("Cannot add SOAPFault as a child of a non-Empty SOAPBody");
 566                }
 567             }
 568         }
 569 
 570         // preserve the encodingStyle attr as it may get lost in the import
 571         String encodingStyle = element.getEncodingStyle();
 572 
 573         final Element importedElement = importElement(element);
 574         addNode(importedElement);
 575 
 576         final SOAPElement converted = convertToSoapElement(importedElement);
 577 
 578         if (encodingStyle != null)
 579             converted.setEncodingStyle(encodingStyle);
 580 
 581         return converted;
 582     }
 583 
 584     protected Element importElement(Element element) {
 585         Document document = getOwnerDocument();
 586         Document oldDocument = element.getOwnerDocument();
 587         if (!oldDocument.equals(document)) {
 588             return (Element) document.importNode(element, true);
 589         } else {
 590             return element;
 591         }
 592     }
 593 
 594     protected SOAPElement addElement(Name name) throws SOAPException {
 595         SOAPElement newElement = createElement(name);
 596         addNode(((ElementImpl) newElement).getDomElement());
 597         return newElement;
 598     }
 599 
 600     protected SOAPElement addElement(QName name) throws SOAPException {
 601         SOAPElement newElement = createElement(name);
 602         addNode(newElement);
 603         return newElement;
 604     }
 605 
 606     protected SOAPElement createElement(Name name) {
 607 
 608         if (isNamespaceQualified(name)) {
 609             return (SOAPElement)
 610                 getOwnerDocument().createElementNS(
 611                                        name.getURI(),
 612                                        name.getQualifiedName());
 613         } else {
 614             return (SOAPElement)
 615                 getOwnerDocument().createElement(name.getQualifiedName());
 616         }
 617     }
 618 
 619     protected SOAPElement createElement(QName name) {
 620 
 621         if (isNamespaceQualified(name)) {
 622             return (SOAPElement)
 623                 getOwnerDocument().createElementNS(
 624                                        name.getNamespaceURI(),
 625                                        getQualifiedName(name));
 626         } else {
 627             return (SOAPElement)
 628                 getOwnerDocument().createElement(getQualifiedName(name));
 629         }
 630     }
 631 
 632     protected void addNode(org.w3c.dom.Node newElement) throws SOAPException {
 633         insertBefore(soapDocument.getDomNode(newElement), null);
 634 
 635         if (getOwnerDocument() instanceof DocumentFragment)
 636             return;
 637 
 638         if (newElement instanceof ElementImpl) {
 639             ElementImpl element = (ElementImpl) newElement;
 640             QName elementName = element.getElementQName();
 641             if (!"".equals(elementName.getNamespaceURI())) {
 642                 element.ensureNamespaceIsDeclared(
 643                     elementName.getPrefix(), elementName.getNamespaceURI());
 644             }
 645         }
 646 
 647     }
 648 
 649     Element getFirstChildElement() {
 650         Node child = getFirstChild();
 651         while (child != null) {
 652             if (child instanceof Element) {
 653                 return (Element) soapDocument.find(child);
 654             }
 655             child = child.getNextSibling();
 656         }
 657         return null;
 658     }
 659 
 660     protected SOAPElement findChild(NameImpl name) {
 661         Node eachChild = getFirstChild();
 662         while (eachChild != null) {
 663             if (eachChild instanceof Element) {
 664                 SOAPElement eachChildSoap = (SOAPElement) soapDocument.find(eachChild);
 665                 if (eachChildSoap != null) {
 666                     if (eachChildSoap.getElementName().equals(name)) {
 667                         return eachChildSoap;
 668                     }
 669                 }
 670             }
 671             eachChild = eachChild.getNextSibling();
 672         }
 673         return null;
 674     }
 675 
 676     protected SOAPElement findAndConvertChildElement(NameImpl name) {
 677         Iterator<Node> eachChild = getChildElementNodes();
 678         while (eachChild.hasNext()) {
 679             SOAPElement child = (SOAPElement) eachChild.next();
 680             if (child.getElementName().equals(name)) {
 681                 return child;
 682             }
 683         }
 684 
 685         return null;
 686     }
 687 
 688     @Override
 689     public SOAPElement addTextNode(String text) throws SOAPException {
 690         if (text.startsWith(CDATAImpl.cdataUC)
 691             || text.startsWith(CDATAImpl.cdataLC))
 692             return addCDATA(
 693                 text.substring(CDATAImpl.cdataUC.length(), text.length() - 3));
 694         return addText(text);
 695     }
 696 
 697     protected SOAPElement addCDATA(String text) throws SOAPException {
 698         org.w3c.dom.Text cdata =
 699                 getOwnerDocument().createCDATASection(text);
 700         addNode(cdata);
 701         return this;
 702     }
 703 
 704     protected SOAPElement addText(String text) throws SOAPException {
 705         org.w3c.dom.Text textNode =
 706                 getOwnerDocument().createTextNode(text);
 707         addNode(textNode);
 708         return this;
 709     }
 710 
 711     @Override
 712     public SOAPElement addAttribute(Name name, String value)
 713         throws SOAPException {
 714         addAttributeBare(name, value);
 715         if (!"".equals(name.getURI())) {
 716             ensureNamespaceIsDeclared(name.getPrefix(), name.getURI());
 717         }
 718         return this;
 719     }
 720 
 721     @Override
 722     public SOAPElement addAttribute(QName qname, String value)
 723         throws SOAPException {
 724         addAttributeBare(qname, value);
 725         if (!"".equals(qname.getNamespaceURI())) {
 726             ensureNamespaceIsDeclared(qname.getPrefix(), qname.getNamespaceURI());
 727         }
 728         return this;
 729     }
 730 
 731     private void addAttributeBare(Name name, String value) {
 732         addAttributeBare(
 733             name.getURI(),
 734             name.getPrefix(),
 735             name.getQualifiedName(),
 736             value);
 737     }
 738     private void addAttributeBare(QName name, String value) {
 739         addAttributeBare(
 740             name.getNamespaceURI(),
 741             name.getPrefix(),
 742             getQualifiedName(name),
 743             value);
 744     }
 745 
 746     private void addAttributeBare(
 747         String uri,
 748         String prefix,
 749         String qualifiedName,
 750         String value) {
 751 
 752         uri = uri.length() == 0 ? null : uri;
 753         if (qualifiedName.equals("xmlns")) {
 754             uri = XMLNS_URI;
 755         }
 756 
 757         if (uri == null) {
 758             setAttribute(qualifiedName, value);
 759         } else {
 760             setAttributeNS(uri, qualifiedName, value);
 761         }
 762     }
 763 
 764     @Override
 765     public SOAPElement addNamespaceDeclaration(String prefix, String uri)
 766         throws SOAPException {
 767         if (prefix.length() > 0) {
 768             setAttributeNS(XMLNS_URI, "xmlns:" + prefix, uri);
 769         } else {
 770             setAttributeNS(XMLNS_URI, "xmlns", uri);
 771         }
 772         //Fix for CR:6474641
 773         //tryToFindEncodingStyleAttributeName();
 774         return this;
 775     }
 776 
 777     @Override
 778     public String getAttributeValue(Name name) {
 779         return getAttributeValueFrom(this, name);
 780     }
 781 
 782     @Override
 783     public String getAttributeValue(QName qname) {
 784         return getAttributeValueFrom(
 785                    this,
 786                    qname.getNamespaceURI(),
 787                    qname.getLocalPart(),
 788                    qname.getPrefix(),
 789                    getQualifiedName(qname));
 790     }
 791 
 792     @Override
 793     public Iterator<Name> getAllAttributes() {
 794         Iterator<Name> i = getAllAttributesFrom(this);
 795         ArrayList<Name> list = new ArrayList<>();
 796         while (i.hasNext()) {
 797             Name name = i.next();
 798             if (!"xmlns".equalsIgnoreCase(name.getPrefix()))
 799                 list.add(name);
 800         }
 801         return list.iterator();
 802     }
 803 
 804     @Override
 805     public Iterator<QName> getAllAttributesAsQNames() {
 806         Iterator<Name> i = getAllAttributesFrom(this);
 807         ArrayList<QName> list = new ArrayList<>();
 808         while (i.hasNext()) {
 809             Name name = i.next();
 810             if (!"xmlns".equalsIgnoreCase(name.getPrefix())) {
 811                 list.add(NameImpl.convertToQName(name));
 812             }
 813         }
 814         return list.iterator();
 815     }
 816 
 817 
 818     @Override
 819     public Iterator<String> getNamespacePrefixes() {
 820         return doGetNamespacePrefixes(false);
 821     }
 822 
 823     @Override
 824     public Iterator<String> getVisibleNamespacePrefixes() {
 825         return doGetNamespacePrefixes(true);
 826     }
 827 
 828     protected Iterator<String> doGetNamespacePrefixes(final boolean deep) {
 829         return new Iterator<String>() {
 830             String next = null;
 831             String last = null;
 832             NamespaceContextIterator eachNamespace =
 833                 getNamespaceContextNodes(deep);
 834 
 835             void findNext() {
 836                 while (next == null && eachNamespace.hasNext()) {
 837                     String attributeKey =
 838                         eachNamespace.nextNamespaceAttr().getNodeName();
 839                     if (attributeKey.startsWith("xmlns:")) {
 840                         next = attributeKey.substring("xmlns:".length());
 841                     }
 842                 }
 843             }
 844 
 845             @Override
 846             public boolean hasNext() {
 847                 findNext();
 848                 return next != null;
 849             }
 850 
 851             @Override
 852             public String next() {
 853                 findNext();
 854                 if (next == null) {
 855                     throw new NoSuchElementException();
 856                 }
 857 
 858                 last = next;
 859                 next = null;
 860                 return last;
 861             }
 862 
 863             @Override
 864             public void remove() {
 865                 if (last == null) {
 866                     throw new IllegalStateException();
 867                 }
 868                 eachNamespace.remove();
 869                 next = null;
 870                 last = null;
 871             }
 872         };
 873     }
 874 
 875     @Override
 876     public Name getElementName() {
 877         return NameImpl.convertToName(elementQName);
 878     }
 879 
 880     @Override
 881     public QName getElementQName() {
 882         return elementQName;
 883     }
 884 
 885     @Override
 886     public boolean removeAttribute(Name name) {
 887         return removeAttribute(name.getURI(), name.getLocalName());
 888     }
 889 
 890     @Override
 891     public boolean removeAttribute(QName name) {
 892         return removeAttribute(name.getNamespaceURI(), name.getLocalPart());
 893     }
 894 
 895     private boolean removeAttribute(String uri, String localName) {
 896         String nonzeroLengthUri =
 897             (uri == null || uri.length() == 0) ? null : uri;
 898         org.w3c.dom.Attr attribute =
 899             getAttributeNodeNS(nonzeroLengthUri, localName);
 900         if (attribute == null) {
 901             return false;
 902         }
 903         removeAttributeNode(attribute);
 904         return true;
 905     }
 906 
 907     @Override
 908     public boolean removeNamespaceDeclaration(String prefix) {
 909         org.w3c.dom.Attr declaration = getNamespaceAttr(prefix);
 910         if (declaration == null) {
 911             return false;
 912         }
 913         try {
 914             removeAttributeNode(declaration);
 915         } catch (DOMException de) {
 916             // ignore
 917         }
 918         return true;
 919     }
 920 
 921     @Override
 922     public Iterator<javax.xml.soap.Node> getChildElements() {
 923         return getChildElementsFrom(this);
 924     }
 925 
 926     protected SOAPElement convertToSoapElement(Element element) {
 927         final Node soapNode = soapDocument.findIfPresent(element);
 928         if (soapNode instanceof SOAPElement) {
 929             return (SOAPElement) soapNode;
 930         } else {
 931             return replaceElementWithSOAPElement(
 932                 element,
 933                 (ElementImpl) createElement(NameImpl.copyElementName(element)));
 934         }
 935     }
 936 
 937     protected TextImpl convertToSoapText(CharacterData characterData) {
 938         final Node soapNode = getSoapDocument().findIfPresent(characterData);
 939         if (soapNode instanceof TextImpl) {
 940             return (TextImpl) soapNode;
 941         } else {
 942             TextImpl t = null;
 943             switch (characterData.getNodeType()) {
 944                 case CDATA_SECTION_NODE:
 945                     t = new CDATAImpl(getSoapDocument(), characterData.getData());
 946                     break;
 947                 case COMMENT_NODE:
 948                     t = new SOAPCommentImpl(getSoapDocument(), characterData.getData());
 949                     break;
 950                 case TEXT_NODE:
 951                     t = new SOAPTextImpl(getSoapDocument(), characterData.getData());
 952                     break;
 953             }
 954             Node parent = getSoapDocument().find(characterData.getParentNode());
 955             if (parent != null) {
 956                 parent.replaceChild(t, characterData);
 957             } // XXX else throw an exception?
 958 
 959             return t;
 960 
 961 //            return replaceElementWithSOAPElement(
 962 //                element,
 963 //                (ElementImpl) createElement(NameImpl.copyElementName(element)));
 964         }
 965     }
 966 
 967     protected SOAPElement replaceElementWithSOAPElement(
 968         Element element,
 969         ElementImpl copy) {
 970 
 971         Iterator<Name> eachAttribute = getAllAttributesFrom(element);
 972         while (eachAttribute.hasNext()) {
 973             Name name = eachAttribute.next();
 974             copy.addAttributeBare(name, getAttributeValueFrom(element, name));
 975         }
 976 
 977         Iterator<Node> eachChild = getChildElementsFromDOM(element);
 978         while (eachChild.hasNext()) {
 979             Node nextChild = eachChild.next();
 980             copy.insertBefore(nextChild, null);
 981         }
 982 
 983         Node parent = soapDocument.find(element.getParentNode());
 984         if (parent != null) {
 985             parent.replaceChild(copy, element);
 986         } // XXX else throw an exception?
 987 
 988         return copy;
 989     }
 990 
 991     private Iterator<Node> getChildElementsFromDOM(final Element el) {
 992         return new Iterator<Node>() {
 993             Node next = el.getFirstChild();
 994             Node nextNext = null;
 995             Node last = null;
 996             Node soapElement = getSoapDocument().findIfPresent(el);
 997 
 998             @Override
 999             public boolean hasNext() {
1000                 if (next != null) {
1001                     return true;
1002                 }
1003                 if (nextNext != null) {
1004                     next = nextNext;
1005                 }
1006 
1007                 return next != null;
1008             }
1009 
1010             public Node next() {
1011                 if (hasNext()) {
1012                     last = next;
1013                     next = null;
1014 
1015                     if ((soapElement instanceof ElementImpl)
1016                             && (last instanceof Element)) {
1017                         last =
1018                                 ((ElementImpl) soapElement).convertToSoapElement(
1019                                         (Element) last);
1020                     } else if ((soapElement instanceof ElementImpl) && (last instanceof CharacterData)) {
1021                         last = ((ElementImpl) soapElement).convertToSoapText(
1022                                         (CharacterData) last);
1023                     }
1024 
1025                     nextNext = last.getNextSibling();
1026                     return last;
1027                 }
1028                 throw new NoSuchElementException();
1029             }
1030 
1031             @Override
1032             public void remove() {
1033                 if (last == null) {
1034                     throw new IllegalStateException();
1035                 }
1036                 Node target = last;
1037                 last = null;
1038                 el.removeChild(target);
1039             }
1040         };
1041     }
1042 
1043     protected Iterator<Node> getChildElementNodes() {
1044         return new Iterator<Node>() {
1045             Iterator<javax.xml.soap.Node> eachNode = getChildElements();
1046             Node next = null;
1047             Node last = null;
1048 
1049             @Override
1050             public boolean hasNext() {
1051                 if (next == null) {
1052                     while (eachNode.hasNext()) {
1053                         Node node = eachNode.next();
1054                         if (node instanceof Element) {
1055                             next = soapDocument.findIfPresent(node);
1056                             break;
1057                         }
1058                     }
1059                 }
1060                 return next != null;
1061             }
1062 
1063             @Override
1064             public javax.xml.soap.Node next() {
1065                 if (hasNext()) {
1066                     last = next;
1067                     next = null;
1068                     return (javax.xml.soap.Node) last;
1069                 }
1070                 throw new NoSuchElementException();
1071             }
1072 
1073             @Override
1074             public void remove() {
1075                 if (last == null) {
1076                     throw new IllegalStateException();
1077                 }
1078                 Node target = last;
1079                 last = null;
1080                 removeChild(target);
1081             }
1082         };
1083     }
1084 
1085     @Override
1086     public Iterator<javax.xml.soap.Node> getChildElements(final Name name) {
1087        return getChildElements(name.getURI(), name.getLocalName());
1088     }
1089 
1090     @Override
1091     public Iterator<javax.xml.soap.Node> getChildElements(final QName qname) {
1092         return getChildElements(qname.getNamespaceURI(), qname.getLocalPart());
1093     }
1094 
1095     private Iterator<javax.xml.soap.Node> getChildElements(final String nameUri, final String nameLocal) {
1096         return new Iterator<javax.xml.soap.Node>() {
1097             Iterator<Node> eachElement = getChildElementNodes();
1098             Node next = null;
1099             Node last = null;
1100 
1101             @Override
1102             public boolean hasNext() {
1103                 if (next == null) {
1104                     while (eachElement.hasNext()) {
1105                         Node element = eachElement.next();
1106                         String elementUri = element.getNamespaceURI();
1107                         elementUri = elementUri == null ? "" : elementUri;
1108                         String elementName = element.getLocalName();
1109                         if (elementUri.equals(nameUri)
1110                             && elementName.equals(nameLocal)) {
1111                             next = element;
1112                             break;
1113                         }
1114                     }
1115                 }
1116                 return next != null;
1117             }
1118 
1119             @Override
1120             public javax.xml.soap.Node next() {
1121                 if (!hasNext()) {
1122                     throw new NoSuchElementException();
1123                 }
1124                 last = next;
1125                 next = null;
1126                 return (javax.xml.soap.Node) last;
1127             }
1128 
1129             @Override
1130             public void remove() {
1131                 if (last == null) {
1132                     throw new IllegalStateException();
1133                 }
1134                 Node target = last;
1135                 last = null;
1136                 removeChild(target);
1137             }
1138         };
1139     }
1140 
1141     @Override
1142     public void removeContents() {
1143         Node currentChild = getFirstChild();
1144 
1145         while (currentChild != null) {
1146             Node temp = currentChild.getNextSibling();
1147             if (currentChild instanceof javax.xml.soap.Node) {
1148                 ((javax.xml.soap.Node) currentChild).detachNode();
1149             } else {
1150                 Node parent = currentChild.getParentNode();
1151                 if (parent != null) {
1152                     parent.removeChild(currentChild);
1153                 }
1154 
1155             }
1156             currentChild = temp;
1157         }
1158     }
1159 
1160     @Override
1161     public void setEncodingStyle(String encodingStyle) throws SOAPException {
1162         if (!"".equals(encodingStyle)) {
1163             try {
1164                 new URI(encodingStyle);
1165             } catch (URISyntaxException m) {
1166                 log.log(
1167                     Level.SEVERE,
1168                     "SAAJ0105.impl.encoding.style.mustbe.valid.URI",
1169                     new String[] { encodingStyle });
1170                 throw new IllegalArgumentException(
1171                     "Encoding style (" + encodingStyle + ") should be a valid URI");
1172             }
1173         }
1174         encodingStyleAttribute.setValue(encodingStyle);
1175         tryToFindEncodingStyleAttributeName();
1176     }
1177 
1178     @Override
1179     public String getEncodingStyle() {
1180         String encodingStyle = encodingStyleAttribute.getValue();
1181         if (encodingStyle != null)
1182             return encodingStyle;
1183         String soapNamespace = getSOAPNamespace();
1184         if (soapNamespace != null) {
1185             Attr attr = getAttributeNodeNS(soapNamespace, "encodingStyle");
1186             if (attr != null) {
1187                 encodingStyle = attr.getValue();
1188                 try {
1189                     setEncodingStyle(encodingStyle);
1190                 } catch (SOAPException se) {
1191                     // has to be ignored
1192                 }
1193                 return encodingStyle;
1194             }
1195         }
1196         return null;
1197     }
1198 
1199     // Node methods
1200     @Override
1201     public String getValue() {
1202         javax.xml.soap.Node valueNode = getValueNode();
1203         return valueNode == null ? null : valueNode.getValue();
1204     }
1205 
1206     @Override
1207     public void setValue(String value) {
1208         Node valueNode = getValueNodeStrict();
1209         if (valueNode != null) {
1210             valueNode.setNodeValue(value);
1211         } else {
1212             try {
1213                 addTextNode(value);
1214             } catch (SOAPException e) {
1215                 throw new RuntimeException(e.getMessage());
1216             }
1217         }
1218     }
1219 
1220     protected Node getValueNodeStrict() {
1221         Node node = getFirstChild();
1222         if (node != null) {
1223             if (node.getNextSibling() == null
1224                 && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
1225                 return node;
1226             } else {
1227                 log.severe("SAAJ0107.impl.elem.child.not.single.text");
1228                 throw new IllegalStateException();
1229             }
1230         }
1231 
1232         return null;
1233     }
1234 
1235     protected javax.xml.soap.Node getValueNode() {
1236         Iterator<javax.xml.soap.Node> i = getChildElements();
1237         while (i.hasNext()) {
1238             Node n = i.next();
1239             if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE ||
1240                 n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
1241                 // TODO: Hack to fix text node split into multiple lines.
1242                 normalize();
1243                 // Should remove the normalization step when this gets fixed in
1244                 // DOM/Xerces.
1245                 return soapDocument.find(n);
1246             }
1247         }
1248         return null;
1249     }
1250 
1251     @Override
1252     public void setParentElement(SOAPElement element) throws SOAPException {
1253         if (element == null) {
1254             log.severe("SAAJ0106.impl.no.null.to.parent.elem");
1255             throw new SOAPException("Cannot pass NULL to setParentElement");
1256         }
1257         element.addChildElement(this);
1258         findEncodingStyleAttributeName();
1259     }
1260 
1261     protected void findEncodingStyleAttributeName() throws SOAPException {
1262         String soapNamespace = getSOAPNamespace();
1263         if (soapNamespace != null) {
1264             String soapNamespacePrefix = getNamespacePrefix(soapNamespace);
1265             if (soapNamespacePrefix != null) {
1266                 setEncodingStyleNamespace(soapNamespace, soapNamespacePrefix);
1267             }
1268         }
1269     }
1270 
1271     protected void setEncodingStyleNamespace(
1272         String soapNamespace,
1273         String soapNamespacePrefix)
1274         throws SOAPException {
1275         Name encodingStyleAttributeName =
1276             NameImpl.create(
1277                 "encodingStyle",
1278                 soapNamespacePrefix,
1279                 soapNamespace);
1280         encodingStyleAttribute.setName(encodingStyleAttributeName);
1281     }
1282 
1283     @Override
1284     public SOAPElement getParentElement() {
1285         Node parentNode = getParentNode();
1286         if (parentNode instanceof SOAPDocument) {
1287             return null;
1288         }
1289         return (SOAPElement) soapDocument.find(parentNode);
1290     }
1291 
1292     protected String getSOAPNamespace() {
1293         String soapNamespace = null;
1294 
1295         SOAPElement antecedent = this;
1296         while (antecedent != null) {
1297             Name antecedentName = antecedent.getElementName();
1298             String antecedentNamespace = antecedentName.getURI();
1299 
1300             if (NameImpl.SOAP11_NAMESPACE.equals(antecedentNamespace)
1301                 || NameImpl.SOAP12_NAMESPACE.equals(antecedentNamespace)) {
1302 
1303                 soapNamespace = antecedentNamespace;
1304                 break;
1305             }
1306 
1307             antecedent = antecedent.getParentElement();
1308         }
1309 
1310         return soapNamespace;
1311     }
1312 
1313     @Override
1314     public void detachNode() {
1315         Node parent = getParentNode();
1316         if (parent != null) {
1317             parent.removeChild(element);
1318         }
1319         encodingStyleAttribute.clearNameAndValue();
1320         // Fix for CR: 6474641
1321         //tryToFindEncodingStyleAttributeName();
1322     }
1323 
1324     public void tryToFindEncodingStyleAttributeName() {
1325         try {
1326             findEncodingStyleAttributeName();
1327         } catch (SOAPException e) { /*okay to fail*/
1328         }
1329     }
1330 
1331     @Override
1332     public void recycleNode() {
1333         detachNode();
1334         // TBD
1335         //  - add this to the factory so subsequent
1336         //    creations can reuse this object.
1337     }
1338 
1339     class AttributeManager {
1340         Name attributeName = null;
1341         String attributeValue = null;
1342 
1343         public void setName(Name newName) throws SOAPException {
1344             clearAttribute();
1345             attributeName = newName;
1346             reconcileAttribute();
1347         }
1348         public void clearName() {
1349             clearAttribute();
1350             attributeName = null;
1351         }
1352         public void setValue(String value) throws SOAPException {
1353             attributeValue = value;
1354             reconcileAttribute();
1355         }
1356         public Name getName() {
1357             return attributeName;
1358         }
1359         public String getValue() {
1360             return attributeValue;
1361         }
1362 
1363         /** Note: to be used only in detachNode method */
1364         public void clearNameAndValue() {
1365             attributeName = null;
1366             attributeValue = null;
1367         }
1368 
1369         private void reconcileAttribute() throws SOAPException {
1370             if (attributeName != null) {
1371                 removeAttribute(attributeName);
1372                 if (attributeValue != null) {
1373                     addAttribute(attributeName, attributeValue);
1374                 }
1375             }
1376         }
1377         private void clearAttribute() {
1378             if (attributeName != null) {
1379                 removeAttribute(attributeName);
1380             }
1381         }
1382     }
1383 
1384     protected static org.w3c.dom.Attr getNamespaceAttrFrom(
1385         Element element,
1386         String prefix) {
1387         NamespaceContextIterator eachNamespace =
1388             new NamespaceContextIterator(element);
1389         while (eachNamespace.hasNext()) {
1390             org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
1391             String declaredPrefix =
1392                 NameImpl.getLocalNameFromTagName(namespaceDecl.getNodeName());
1393             if (declaredPrefix.equals(prefix)) {
1394                 return namespaceDecl;
1395             }
1396         }
1397         return null;
1398     }
1399 
1400     protected static Iterator<Name> getAllAttributesFrom(final Element element) {
1401         final NamedNodeMap attributes = element.getAttributes();
1402 
1403         return new Iterator<Name>() {
1404             int attributesLength = attributes.getLength();
1405             int attributeIndex = 0;
1406             String currentName;
1407 
1408             @Override
1409             public boolean hasNext() {
1410                 return attributeIndex < attributesLength;
1411             }
1412 
1413             @Override
1414             public Name next() {
1415                 if (!hasNext()) {
1416                     throw new NoSuchElementException();
1417                 }
1418                 Node current = attributes.item(attributeIndex++);
1419                 currentName = current.getNodeName();
1420 
1421                 String prefix = NameImpl.getPrefixFromTagName(currentName);
1422                 if (prefix.length() == 0) {
1423                     return NameImpl.createFromUnqualifiedName(currentName);
1424                 } else {
1425                     Name attributeName =
1426                         NameImpl.createFromQualifiedName(
1427                             currentName,
1428                             current.getNamespaceURI());
1429                     return attributeName;
1430                 }
1431             }
1432 
1433             @Override
1434             public void remove() {
1435                 if (currentName == null) {
1436                     throw new IllegalStateException();
1437                 }
1438                 attributes.removeNamedItem(currentName);
1439             }
1440         };
1441     }
1442 
1443     protected static String getAttributeValueFrom(Element element, Name name) {
1444       return getAttributeValueFrom(
1445           element,
1446           name.getURI(),
1447           name.getLocalName(),
1448           name.getPrefix(),
1449           name.getQualifiedName());
1450     }
1451 
1452     private static String getAttributeValueFrom(
1453         Element element,
1454         String uri,
1455         String localName,
1456         String prefix,
1457         String qualifiedName) {
1458 
1459         String nonzeroLengthUri =
1460             (uri == null || uri.length() == 0) ? null : uri;
1461 
1462         boolean mustUseGetAttributeNodeNS =  (nonzeroLengthUri != null);
1463 
1464         if (mustUseGetAttributeNodeNS) {
1465 
1466             if (!element.hasAttributeNS(uri, localName)) {
1467                 return null;
1468             }
1469 
1470             String attrValue =
1471                 element.getAttributeNS(nonzeroLengthUri, localName);
1472 
1473             return attrValue;
1474         }
1475 
1476         Attr attribute = null;
1477         attribute = element.getAttributeNode(qualifiedName);
1478 
1479         return attribute == null ? null : attribute.getValue();
1480     }
1481 
1482     protected Iterator<javax.xml.soap.Node> getChildElementsFrom(final Element element) {
1483         return new Iterator<javax.xml.soap.Node>() {
1484             Node next = element.getFirstChild();
1485             Node nextNext = null;
1486             Node last = null;
1487             Node soapElement = soapDocument.findIfPresent(element);
1488 
1489             @Override
1490             public boolean hasNext() {
1491                 if (next != null) {
1492                     return true;
1493                 }
1494                 if (nextNext != null) {
1495                     next = nextNext;
1496                 }
1497 
1498                 return next != null;
1499             }
1500 
1501             @Override
1502             public javax.xml.soap.Node next() {
1503                 if (hasNext()) {
1504                     last = next;
1505                     next = null;
1506 
1507                     if ((soapElement instanceof ElementImpl)
1508                             && (last instanceof Element)) {
1509                         last =
1510                                 ((ElementImpl) soapElement).convertToSoapElement(
1511                                         (Element) last);
1512                     }
1513 
1514                     nextNext = last.getNextSibling();
1515                     return (javax.xml.soap.Node) soapDocument.findIfPresent(last);
1516                 }
1517                 throw new NoSuchElementException();
1518             }
1519 
1520             @Override
1521             public void remove() {
1522                 if (last == null) {
1523                     throw new IllegalStateException();
1524                 }
1525                 Node target = last;
1526                 last = null;
1527                 element.removeChild(target);
1528             }
1529         };
1530     }
1531 
1532     public static String getQualifiedName(QName name) {
1533         String prefix = name.getPrefix();
1534         String localName = name.getLocalPart();
1535         String qualifiedName = null;
1536 
1537             if (prefix != null && prefix.length() > 0) {
1538                 qualifiedName = prefix + ":" + localName;
1539             } else {
1540                 qualifiedName = localName;
1541             }
1542          return qualifiedName;
1543     }
1544 
1545     public static String getLocalPart(String qualifiedName) {
1546         if (qualifiedName == null) {
1547             // Log
1548             throw new IllegalArgumentException("Cannot get local name for a \"null\" qualified name");
1549         }
1550 
1551         int index = qualifiedName.indexOf(':');
1552         if (index < 0)
1553             return qualifiedName;
1554         else
1555             return qualifiedName.substring(index + 1);
1556     }
1557 
1558     public static String getPrefix(String qualifiedName) {
1559         if (qualifiedName == null) {
1560             // Log
1561             throw new IllegalArgumentException("Cannot get prefix for a  \"null\" qualified name");
1562         }
1563 
1564         int index = qualifiedName.indexOf(':');
1565         if (index < 0)
1566             return "";
1567         else
1568             return qualifiedName.substring(0, index);
1569     }
1570 
1571     protected boolean isNamespaceQualified(Name name) {
1572         return !"".equals(name.getURI());
1573     }
1574 
1575     protected boolean isNamespaceQualified(QName name) {
1576         return !"".equals(name.getNamespaceURI());
1577     }
1578 
1579     //TODO: This is a temporary SAAJ workaround for optimizing XWS
1580     // should be removed once the corresponding JAXP bug is fixed
1581     // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
1582     @Override
1583     public void setAttributeNS(
1584         String namespaceURI,String qualifiedName, String value) {
1585         int index = qualifiedName.indexOf(':');
1586         String localName;
1587         if (index < 0)
1588             localName = qualifiedName;
1589         else
1590             localName = qualifiedName.substring(index + 1);
1591 
1592         // Workaround for bug 6467808 - This needs to be fixed in JAXP
1593 
1594         // Rolling back this fix, this is a wrong fix, infact its causing other regressions in JAXWS tck and
1595         // other tests, because of this change the namespace declarations on soapenv:Fault element are never
1596         // picked up. The fix for bug 6467808 should be in JAXP.
1597 //        if(elementQName.getLocalPart().equals("Fault") &&
1598 //                (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(value) ||
1599 //                SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(value)))
1600 //            return;
1601 
1602         element.setAttributeNS(namespaceURI,qualifiedName,value);
1603         //String tmpLocalName = this.getLocalName();
1604         String tmpURI = this.getNamespaceURI();
1605         boolean isIDNS = false;
1606         if( tmpURI != null && (tmpURI.equals(DSIG_NS) || tmpURI.equals(XENC_NS))){
1607             isIDNS = true;
1608         }
1609         //No need to check for Signature/encryption element
1610         //just check for namespace.
1611         if(localName.equals("Id")){
1612             if(namespaceURI == null || namespaceURI.equals("")){
1613                 setIdAttribute(localName,true);
1614             }else if(isIDNS || WSU_NS.equals(namespaceURI)){
1615                 setIdAttributeNS(namespaceURI,localName,true);
1616             }
1617         }
1618 
1619     }
1620 
1621     @Override
1622     public void removeAttributeNS(String namespaceURI, String localName) throws DOMException {
1623         element.removeAttributeNS(namespaceURI, localName);
1624     }
1625 
1626     @Override
1627     public Attr getAttributeNodeNS(String namespaceURI, String localName) throws DOMException {
1628         return element.getAttributeNodeNS(namespaceURI, localName);
1629     }
1630 
1631     @Override
1632     public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
1633         return element.setAttributeNodeNS(newAttr);
1634     }
1635 
1636     @Override
1637     public NodeList getElementsByTagNameNS(String namespaceURI, String localName) throws DOMException {
1638         return new NodeListImpl(soapDocument, element.getElementsByTagNameNS(namespaceURI, localName));
1639     }
1640 
1641     @Override
1642     public boolean hasAttribute(String name) {
1643         return element.hasAttribute(name);
1644     }
1645 
1646     @Override
1647     public boolean hasAttributeNS(String namespaceURI, String localName) throws DOMException {
1648         return element.hasAttributeNS(namespaceURI, localName);
1649     }
1650 
1651     @Override
1652     public TypeInfo getSchemaTypeInfo() {
1653         return element.getSchemaTypeInfo();
1654     }
1655 
1656     @Override
1657     public void setIdAttribute(String name, boolean isId) throws DOMException {
1658         element.setIdAttribute(name, isId);
1659     }
1660 
1661     @Override
1662     public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) throws DOMException {
1663         element.setIdAttributeNS(namespaceURI, localName, isId);
1664     }
1665 
1666     @Override
1667     public void setIdAttributeNode(Attr idAttr, boolean isId) throws DOMException {
1668         element.setIdAttributeNode(idAttr, isId);
1669     }
1670 
1671     @Override
1672     public String getNodeName() {
1673         return element.getNodeName();
1674     }
1675 
1676     @Override
1677     public String getNodeValue() throws DOMException {
1678         return element.getNodeValue();
1679     }
1680 
1681     @Override
1682     public void setNodeValue(String nodeValue) throws DOMException {
1683         element.setNodeValue(nodeValue);
1684     }
1685 
1686     @Override
1687     public short getNodeType() {
1688         return element.getNodeType();
1689     }
1690 
1691     @Override
1692     public Node getParentNode() {
1693         return soapDocument.find(element.getParentNode());
1694     }
1695 
1696     @Override
1697     public NodeList getChildNodes() {
1698         return new NodeListImpl(soapDocument, element.getChildNodes());
1699     }
1700 
1701     @Override
1702     public Node getFirstChild() {
1703         return soapDocument.findIfPresent(element.getFirstChild());
1704     }
1705 
1706     @Override
1707     public Node getLastChild() {
1708         return soapDocument.findIfPresent(element.getLastChild());
1709     }
1710 
1711     @Override
1712     public Node getPreviousSibling() {
1713         return soapDocument.findIfPresent(element.getPreviousSibling());
1714     }
1715 
1716     @Override
1717     public Node getNextSibling() {
1718         return soapDocument.findIfPresent(element.getNextSibling());
1719     }
1720 
1721     @Override
1722     public NamedNodeMap getAttributes() {
1723         NamedNodeMap attributes = element.getAttributes();
1724         if (attributes == null) {
1725             return null;
1726         }
1727         return new NamedNodeMapImpl(attributes, soapDocument);
1728     }
1729 
1730     public Element getDomElement() {
1731         return element;
1732     }
1733 
1734     public SOAPDocumentImpl getSoapDocument() {
1735         return soapDocument;
1736     }
1737 }