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