1 /*
   2  * Copyright (c) 1997, 2010, 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.util.*;
  29 import java.util.logging.Level;
  30 import java.util.logging.Logger;
  31 
  32 import javax.xml.namespace.QName;
  33 import javax.xml.soap.*;
  34 
  35 import org.w3c.dom.*;
  36 import org.w3c.dom.Node;
  37 
  38 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
  39 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocument;
  40 import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl;
  41 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
  42 import com.sun.xml.internal.messaging.saaj.util.*;
  43 
  44 public class ElementImpl
  45     extends com.sun.org.apache.xerces.internal.dom.ElementNSImpl
  46     implements SOAPElement, SOAPBodyElement {
  47 
  48     public static final String DSIG_NS = "http://www.w3.org/2000/09/xmldsig#".intern();
  49     public static final String XENC_NS = "http://www.w3.org/2001/04/xmlenc#".intern();
  50     public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd".intern();
  51 
  52     private AttributeManager encodingStyleAttribute = new AttributeManager();
  53 
  54     protected QName elementQName;
  55 
  56     protected static final Logger log =
  57         Logger.getLogger(LogDomainConstants.SOAP_IMPL_DOMAIN,
  58                          "com.sun.xml.internal.messaging.saaj.soap.impl.LocalStrings");
  59 
  60     /**
  61      * XML Information Set REC
  62      * all namespace attributes (including those named xmlns,
  63      * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/
  64      */
  65     public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern();
  66 
  67     /**
  68      * The XML Namespace ("http://www.w3.org/XML/1998/namespace"). This is
  69      * the Namespace URI that is automatically mapped to the "xml" prefix.
  70      */
  71     public final static String XML_URI = "http://www.w3.org/XML/1998/namespace".intern();
  72 
  73     public ElementImpl(SOAPDocumentImpl ownerDoc, Name name) {
  74         super(
  75             ownerDoc,
  76             name.getURI(),
  77             name.getQualifiedName(),
  78             name.getLocalName());
  79         elementQName = NameImpl.convertToQName(name);
  80     }
  81 
  82     public ElementImpl(SOAPDocumentImpl ownerDoc, QName name) {
  83         super(
  84             ownerDoc,
  85             name.getNamespaceURI(),
  86             getQualifiedName(name),
  87             name.getLocalPart());
  88         elementQName = name;
  89     }
  90 
  91     public ElementImpl(
  92         SOAPDocumentImpl ownerDoc,
  93         String uri,
  94         String qualifiedName) {
  95 
  96         super(ownerDoc, uri, qualifiedName);
  97         elementQName =
  98             new QName(uri, getLocalPart(qualifiedName), getPrefix(qualifiedName));
  99     }
 100 
 101     public void ensureNamespaceIsDeclared(String prefix, String uri) {
 102         String alreadyDeclaredUri = getNamespaceURI(prefix);
 103         if (alreadyDeclaredUri == null || !alreadyDeclaredUri.equals(uri)) {
 104             try {
 105                 addNamespaceDeclaration(prefix, uri);
 106             } catch (SOAPException e) { /*ignore*/
 107             }
 108         }
 109     }
 110 
 111     public Document getOwnerDocument() {
 112         SOAPDocument ownerSOAPDocument =
 113             ((SOAPDocument) super.getOwnerDocument());
 114         if (ownerSOAPDocument == null) {
 115             return null;
 116         }
 117         return ownerSOAPDocument.getDocument();
 118     }
 119 
 120     public SOAPElement addChildElement(Name name) throws SOAPException {
 121         return  addElement(name);
 122     }
 123 
 124     public SOAPElement addChildElement(QName qname) throws SOAPException {
 125         return  addElement(qname);
 126     }
 127 
 128     public SOAPElement addChildElement(String localName) throws SOAPException {
 129         return (SOAPElement) addChildElement(
 130             NameImpl.createFromUnqualifiedName(localName));
 131     }
 132 
 133     public SOAPElement addChildElement(String localName, String prefix)
 134         throws SOAPException {
 135         String uri = getNamespaceURI(prefix);
 136         if (uri == null) {
 137             log.log(
 138                 Level.SEVERE,
 139                 "SAAJ0101.impl.parent.of.body.elem.mustbe.body",
 140                 new String[] { prefix });
 141             throw new SOAPExceptionImpl(
 142                 "Unable to locate namespace for prefix " + prefix);
 143         }
 144         return addChildElement(localName, prefix, uri);
 145     }
 146 
 147     public String getNamespaceURI(String prefix) {
 148 
 149         if ("xmlns".equals(prefix)) {
 150             return XMLNS_URI;
 151         }
 152 
 153         if("xml".equals(prefix)) {
 154             return XML_URI;
 155         }
 156 
 157         if ("".equals(prefix)) {
 158 
 159             org.w3c.dom.Node currentAncestor = this;
 160             while (currentAncestor != null &&
 161                    !(currentAncestor instanceof Document)) {
 162 
 163                 if (currentAncestor instanceof ElementImpl) {
 164                     QName name = ((ElementImpl) currentAncestor).getElementQName();
 165                     /*
 166                     if (prefix.equals(name.getPrefix())) {
 167                         String uri = name.getNamespaceURI();
 168                         if ("".equals(uri)) {
 169                             return null;
 170                         }
 171                         else {
 172                             return uri;
 173                         }
 174                     }*/
 175                     if (((Element) currentAncestor).hasAttributeNS(
 176                             XMLNS_URI, "xmlns")) {
 177 
 178                         String uri =
 179                             ((Element) currentAncestor).getAttributeNS(
 180                                 XMLNS_URI, "xmlns");
 181                         if ("".equals(uri))
 182                             return null;
 183                         else {
 184                             return uri;
 185                         }
 186                     }
 187                 }
 188                 currentAncestor = currentAncestor.getParentNode();
 189             }
 190 
 191         } else if (prefix != null) {
 192             // Find if there's an ancester whose name contains this prefix
 193             org.w3c.dom.Node currentAncestor = this;
 194 
 195 //            String uri = currentAncestor.lookupNamespaceURI(prefix);
 196 //            return uri;
 197             while (currentAncestor != null &&
 198                    !(currentAncestor instanceof Document)) {
 199 
 200                /* if (prefix.equals(currentAncestor.getPrefix())) {
 201                     String uri = currentAncestor.getNamespaceURI();
 202                     // this is because the javadoc says getNamespaceURI() is not a computed value
 203                     // and URI for a non-empty prefix cannot be null
 204                     if (uri != null)
 205                         return uri;
 206                 }*/
 207                 //String uri = currentAncestor.lookupNamespaceURI(prefix);
 208                 //if (uri != null) {
 209                 //    return uri;
 210                 //}
 211 
 212                 if (((Element) currentAncestor).hasAttributeNS(
 213                         XMLNS_URI, prefix)) {
 214                     return ((Element) currentAncestor).getAttributeNS(
 215                                XMLNS_URI, prefix);
 216                 }
 217 
 218                 currentAncestor = currentAncestor.getParentNode();
 219             }
 220         }
 221 
 222         return null;
 223     }
 224 
 225     public SOAPElement setElementQName(QName newName) throws SOAPException {
 226         ElementImpl copy =
 227             new ElementImpl((SOAPDocumentImpl) getOwnerDocument(), newName);
 228         return replaceElementWithSOAPElement(this,copy);
 229     }
 230 
 231     public QName createQName(String localName, String prefix)
 232         throws SOAPException {
 233         String uri = getNamespaceURI(prefix);
 234         if (uri == null) {
 235             log.log(Level.SEVERE, "SAAJ0102.impl.cannot.locate.ns",
 236                     new Object[] {prefix});
 237             throw new SOAPException("Unable to locate namespace for prefix "
 238                                     + prefix);
 239         }
 240         return new QName(uri, localName, prefix);
 241     }
 242 
 243     public String getNamespacePrefix(String uri) {
 244 
 245         NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
 246         while (eachNamespace.hasNext()) {
 247             org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
 248             if (namespaceDecl.getNodeValue().equals(uri)) {
 249                 String candidatePrefix = namespaceDecl.getLocalName();
 250                 if ("xmlns".equals(candidatePrefix))
 251                     return "";
 252                 else
 253                     return candidatePrefix;
 254             }
 255         }
 256 
 257         // Find if any of the ancestors' name has this uri
 258         org.w3c.dom.Node currentAncestor = this;
 259         while (currentAncestor != null &&
 260                !(currentAncestor instanceof Document)) {
 261 
 262             if (uri.equals(currentAncestor.getNamespaceURI()))
 263                 return currentAncestor.getPrefix();
 264             currentAncestor = currentAncestor.getParentNode();
 265         }
 266 
 267         return null;
 268     }
 269 
 270     protected org.w3c.dom.Attr getNamespaceAttr(String prefix) {
 271         NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
 272         if (!"".equals(prefix))
 273             prefix = ":"+prefix;
 274         while (eachNamespace.hasNext()) {
 275             org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
 276             if (!"".equals(prefix)) {
 277                 if (namespaceDecl.getNodeName().endsWith(prefix))
 278                     return namespaceDecl;
 279             } else {
 280                 if (namespaceDecl.getNodeName().equals("xmlns"))
 281                     return namespaceDecl;
 282             }
 283         }
 284         return null;
 285     }
 286 
 287     public NamespaceContextIterator getNamespaceContextNodes() {
 288         return getNamespaceContextNodes(true);
 289     }
 290 
 291     public NamespaceContextIterator getNamespaceContextNodes(boolean traverseStack) {
 292         return new NamespaceContextIterator(this, traverseStack);
 293     }
 294 
 295     public SOAPElement addChildElement(
 296         String localName,
 297         String prefix,
 298         String uri)
 299         throws SOAPException {
 300 
 301         SOAPElement newElement = createElement(NameImpl.create(localName, prefix, uri));
 302         addNode(newElement);
 303         return convertToSoapElement(newElement);
 304     }
 305 
 306     public SOAPElement addChildElement(SOAPElement element)
 307         throws SOAPException {
 308 
 309         // check if Element falls in SOAP 1.1 or 1.2 namespace.
 310         String elementURI = element.getElementName().getURI();
 311         String localName = element.getLocalName();
 312 
 313         if ((SOAPConstants.URI_NS_SOAP_ENVELOPE).equals(elementURI)
 314             || (SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE).equals(elementURI)) {
 315 
 316 
 317             if ("Envelope".equalsIgnoreCase(localName) ||
 318                 "Header".equalsIgnoreCase(localName) || "Body".equalsIgnoreCase(localName)) {
 319                 log.severe("SAAJ0103.impl.cannot.add.fragements");
 320                 throw new SOAPExceptionImpl(
 321                     "Cannot add fragments which contain elements "
 322                         + "which are in the SOAP namespace");
 323             }
 324 
 325             if ("Fault".equalsIgnoreCase(localName) && !"Body".equalsIgnoreCase(this.getLocalName())) {
 326                 log.severe("SAAJ0154.impl.adding.fault.to.nonbody");
 327                 throw new SOAPExceptionImpl("Cannot add a SOAPFault as a child of " + this.getLocalName());
 328             }
 329 
 330             if ("Detail".equalsIgnoreCase(localName) && !"Fault".equalsIgnoreCase(this.getLocalName())) {
 331                 log.severe("SAAJ0155.impl.adding.detail.nonfault");
 332                 throw new SOAPExceptionImpl("Cannot add a Detail as a child of " + this.getLocalName());
 333             }
 334 
 335             if ("Fault".equalsIgnoreCase(localName)) {
 336                // if body is not empty throw an exception
 337                if (!elementURI.equals(this.getElementName().getURI())) {
 338                    log.severe("SAAJ0158.impl.version.mismatch.fault");
 339                    throw new SOAPExceptionImpl("SOAP Version mismatch encountered when trying to add SOAPFault to SOAPBody");
 340                }
 341                Iterator it = this.getChildElements();
 342                if (it.hasNext()) {
 343                    log.severe("SAAJ0156.impl.adding.fault.error");
 344                    throw new SOAPExceptionImpl("Cannot add SOAPFault as a child of a non-Empty SOAPBody");
 345                }
 346             }
 347         }
 348 
 349         // preserve the encodingStyle attr as it may get lost in the import
 350         String encodingStyle = element.getEncodingStyle();
 351 
 352         ElementImpl importedElement = (ElementImpl) importElement(element);
 353         addNode(importedElement);
 354 
 355         if (encodingStyle != null)
 356             importedElement.setEncodingStyle(encodingStyle);
 357 
 358         return convertToSoapElement(importedElement);
 359     }
 360 
 361     protected Element importElement(Element element) {
 362         Document document = getOwnerDocument();
 363         Document oldDocument = element.getOwnerDocument();
 364         if (!oldDocument.equals(document)) {
 365             return (Element) document.importNode(element, true);
 366         } else {
 367             return element;
 368         }
 369     }
 370 
 371     protected SOAPElement addElement(Name name) throws SOAPException {
 372         SOAPElement newElement = createElement(name);
 373         addNode(newElement);
 374         return circumventBug5034339(newElement);
 375     }
 376 
 377     protected SOAPElement addElement(QName name) throws SOAPException {
 378         SOAPElement newElement = createElement(name);
 379         addNode(newElement);
 380         return circumventBug5034339(newElement);
 381     }
 382 
 383     protected SOAPElement createElement(Name name) {
 384 
 385         if (isNamespaceQualified(name)) {
 386             return (SOAPElement)
 387                 getOwnerDocument().createElementNS(
 388                                        name.getURI(),
 389                                        name.getQualifiedName());
 390         } else {
 391             return (SOAPElement)
 392                 getOwnerDocument().createElement(name.getQualifiedName());
 393         }
 394     }
 395 
 396     protected SOAPElement createElement(QName name) {
 397 
 398         if (isNamespaceQualified(name)) {
 399             return (SOAPElement)
 400                 getOwnerDocument().createElementNS(
 401                                        name.getNamespaceURI(),
 402                                        getQualifiedName(name));
 403         } else {
 404             return (SOAPElement)
 405                 getOwnerDocument().createElement(getQualifiedName(name));
 406         }
 407     }
 408 
 409     protected void addNode(org.w3c.dom.Node newElement) throws SOAPException {
 410         insertBefore(newElement, null);
 411 
 412         if (getOwnerDocument() instanceof DocumentFragment)
 413             return;
 414 
 415         if (newElement instanceof ElementImpl) {
 416             ElementImpl element = (ElementImpl) newElement;
 417             QName elementName = element.getElementQName();
 418             if (!"".equals(elementName.getNamespaceURI())) {
 419                 element.ensureNamespaceIsDeclared(
 420                     elementName.getPrefix(), elementName.getNamespaceURI());
 421             }
 422         }
 423 
 424     }
 425 
 426     protected SOAPElement findChild(NameImpl name) {
 427         Iterator eachChild = getChildElementNodes();
 428         while (eachChild.hasNext()) {
 429             SOAPElement child = (SOAPElement) eachChild.next();
 430             if (child.getElementName().equals(name)) {
 431                 return child;
 432             }
 433         }
 434 
 435         return null;
 436     }
 437 
 438     public SOAPElement addTextNode(String text) throws SOAPException {
 439         if (text.startsWith(CDATAImpl.cdataUC)
 440             || text.startsWith(CDATAImpl.cdataLC))
 441             return addCDATA(
 442                 text.substring(CDATAImpl.cdataUC.length(), text.length() - 3));
 443         return addText(text);
 444     }
 445 
 446     protected SOAPElement addCDATA(String text) throws SOAPException {
 447         org.w3c.dom.Text cdata =
 448             (org.w3c.dom.Text) getOwnerDocument().createCDATASection(text);
 449         addNode(cdata);
 450         return this;
 451     }
 452 
 453     protected SOAPElement addText(String text) throws SOAPException {
 454         org.w3c.dom.Text textNode =
 455             (org.w3c.dom.Text) getOwnerDocument().createTextNode(text);
 456         addNode(textNode);
 457         return this;
 458     }
 459 
 460     public SOAPElement addAttribute(Name name, String value)
 461         throws SOAPException {
 462         addAttributeBare(name, value);
 463         if (!"".equals(name.getURI())) {
 464             ensureNamespaceIsDeclared(name.getPrefix(), name.getURI());
 465         }
 466         return this;
 467     }
 468 
 469     public SOAPElement addAttribute(QName qname, String value)
 470         throws SOAPException {
 471         addAttributeBare(qname, value);
 472         if (!"".equals(qname.getNamespaceURI())) {
 473             ensureNamespaceIsDeclared(qname.getPrefix(), qname.getNamespaceURI());
 474         }
 475         return this;
 476     }
 477 
 478     private void addAttributeBare(Name name, String value) {
 479         addAttributeBare(
 480             name.getURI(),
 481             name.getPrefix(),
 482             name.getQualifiedName(),
 483             value);
 484     }
 485     private void addAttributeBare(QName name, String value) {
 486         addAttributeBare(
 487             name.getNamespaceURI(),
 488             name.getPrefix(),
 489             getQualifiedName(name),
 490             value);
 491     }
 492 
 493     private void addAttributeBare(
 494         String uri,
 495         String prefix,
 496         String qualifiedName,
 497         String value) {
 498 
 499         uri = uri.length() == 0 ? null : uri;
 500         if (qualifiedName.equals("xmlns")) {
 501             uri = XMLNS_URI;
 502         }
 503 
 504         if (uri == null) {
 505             setAttribute(qualifiedName, value);
 506         } else {
 507             setAttributeNS(uri, qualifiedName, value);
 508         }
 509     }
 510 
 511     public SOAPElement addNamespaceDeclaration(String prefix, String uri)
 512         throws SOAPException {
 513         if (prefix.length() > 0) {
 514             setAttributeNS(XMLNS_URI, "xmlns:" + prefix, uri);
 515         } else {
 516             setAttributeNS(XMLNS_URI, "xmlns", uri);
 517         }
 518         //Fix for CR:6474641
 519         //tryToFindEncodingStyleAttributeName();
 520         return this;
 521     }
 522 
 523     public String getAttributeValue(Name name) {
 524         return getAttributeValueFrom(this, name);
 525     }
 526 
 527     public String getAttributeValue(QName qname) {
 528         return getAttributeValueFrom(
 529                    this,
 530                    qname.getNamespaceURI(),
 531                    qname.getLocalPart(),
 532                    qname.getPrefix(),
 533                    getQualifiedName(qname));
 534     }
 535 
 536     public Iterator getAllAttributes() {
 537         Iterator i = getAllAttributesFrom(this);
 538         ArrayList list = new ArrayList();
 539         while (i.hasNext()) {
 540             Name name = (Name) i.next();
 541             if (!"xmlns".equalsIgnoreCase(name.getPrefix()))
 542                 list.add(name);
 543         }
 544         return list.iterator();
 545     }
 546 
 547     public Iterator getAllAttributesAsQNames() {
 548         Iterator i = getAllAttributesFrom(this);
 549         ArrayList list = new ArrayList();
 550         while (i.hasNext()) {
 551             Name name = (Name) i.next();
 552             if (!"xmlns".equalsIgnoreCase(name.getPrefix())) {
 553                 list.add(NameImpl.convertToQName(name));
 554             }
 555         }
 556         return list.iterator();
 557     }
 558 
 559 
 560     public Iterator getNamespacePrefixes() {
 561         return doGetNamespacePrefixes(false);
 562     }
 563 
 564     public Iterator getVisibleNamespacePrefixes() {
 565         return doGetNamespacePrefixes(true);
 566     }
 567 
 568     protected Iterator doGetNamespacePrefixes(final boolean deep) {
 569         return new Iterator() {
 570             String next = null;
 571             String last = null;
 572             NamespaceContextIterator eachNamespace =
 573                 getNamespaceContextNodes(deep);
 574 
 575             void findNext() {
 576                 while (next == null && eachNamespace.hasNext()) {
 577                     String attributeKey =
 578                         eachNamespace.nextNamespaceAttr().getNodeName();
 579                     if (attributeKey.startsWith("xmlns:")) {
 580                         next = attributeKey.substring("xmlns:".length());
 581                     }
 582                 }
 583             }
 584 
 585             public boolean hasNext() {
 586                 findNext();
 587                 return next != null;
 588             }
 589 
 590             public Object next() {
 591                 findNext();
 592                 if (next == null) {
 593                     throw new NoSuchElementException();
 594                 }
 595 
 596                 last = next;
 597                 next = null;
 598                 return last;
 599             }
 600 
 601             public void remove() {
 602                 if (last == null) {
 603                     throw new IllegalStateException();
 604                 }
 605                 eachNamespace.remove();
 606                 next = null;
 607                 last = null;
 608             }
 609         };
 610     }
 611 
 612     public Name getElementName() {
 613         return NameImpl.convertToName(elementQName);
 614     }
 615 
 616     public QName getElementQName() {
 617         return elementQName;
 618     }
 619 
 620     public boolean removeAttribute(Name name) {
 621         return removeAttribute(name.getURI(), name.getLocalName());
 622     }
 623 
 624     public boolean removeAttribute(QName name) {
 625         return removeAttribute(name.getNamespaceURI(), name.getLocalPart());
 626     }
 627 
 628     private boolean removeAttribute(String uri, String localName) {
 629         String nonzeroLengthUri =
 630             (uri == null || uri.length() == 0) ? null : uri;
 631         org.w3c.dom.Attr attribute =
 632             getAttributeNodeNS(nonzeroLengthUri, localName);
 633         if (attribute == null) {
 634             return false;
 635         }
 636         removeAttributeNode(attribute);
 637         return true;
 638     }
 639 
 640     public boolean removeNamespaceDeclaration(String prefix) {
 641         org.w3c.dom.Attr declaration = getNamespaceAttr(prefix);
 642         if (declaration == null) {
 643             return false;
 644         }
 645         try {
 646             removeAttributeNode(declaration);
 647         } catch (DOMException de) {
 648             // ignore
 649         }
 650         return true;
 651     }
 652 
 653     public Iterator getChildElements() {
 654         return getChildElementsFrom(this);
 655     }
 656 
 657     protected SOAPElement convertToSoapElement(Element element) {
 658         if (element instanceof SOAPElement) {
 659             return (SOAPElement) element;
 660         } else {
 661             return replaceElementWithSOAPElement(
 662                 element,
 663                 (ElementImpl) createElement(NameImpl.copyElementName(element)));
 664         }
 665     }
 666 
 667     protected static SOAPElement replaceElementWithSOAPElement(
 668         Element element,
 669         ElementImpl copy) {
 670 
 671         Iterator eachAttribute = getAllAttributesFrom(element);
 672         while (eachAttribute.hasNext()) {
 673             Name name = (Name) eachAttribute.next();
 674             copy.addAttributeBare(name, getAttributeValueFrom(element, name));
 675         }
 676 
 677         Iterator eachChild = getChildElementsFrom(element);
 678         while (eachChild.hasNext()) {
 679             Node nextChild = (Node) eachChild.next();
 680             copy.insertBefore(nextChild, null);
 681         }
 682 
 683         Node parent = element.getParentNode();
 684         if (parent != null) {
 685             parent.replaceChild(copy, element);
 686         } // XXX else throw an exception?
 687 
 688         return copy;
 689     }
 690 
 691     protected Iterator getChildElementNodes() {
 692         return new Iterator() {
 693             Iterator eachNode = getChildElements();
 694             Node next = null;
 695             Node last = null;
 696 
 697             public boolean hasNext() {
 698                 if (next == null) {
 699                     while (eachNode.hasNext()) {
 700                         Node node = (Node) eachNode.next();
 701                         if (node instanceof SOAPElement) {
 702                             next = node;
 703                             break;
 704                         }
 705                     }
 706                 }
 707                 return next != null;
 708             }
 709 
 710             public Object next() {
 711                 if (hasNext()) {
 712                     last = next;
 713                     next = null;
 714                     return last;
 715                 }
 716                 throw new NoSuchElementException();
 717             }
 718 
 719             public void remove() {
 720                 if (last == null) {
 721                     throw new IllegalStateException();
 722                 }
 723                 Node target = last;
 724                 last = null;
 725                 removeChild(target);
 726             }
 727         };
 728     }
 729 
 730     public Iterator getChildElements(final Name name) {
 731        return getChildElements(name.getURI(), name.getLocalName());
 732     }
 733 
 734     public Iterator getChildElements(final QName qname) {
 735         return getChildElements(qname.getNamespaceURI(), qname.getLocalPart());
 736     }
 737 
 738     private Iterator getChildElements(final String nameUri, final String nameLocal) {
 739         return new Iterator() {
 740             Iterator eachElement = getChildElementNodes();
 741             Node next = null;
 742             Node last = null;
 743 
 744             public boolean hasNext() {
 745                 if (next == null) {
 746                     while (eachElement.hasNext()) {
 747                         Node element = (Node) eachElement.next();
 748                         String elementUri = element.getNamespaceURI();
 749                         elementUri = elementUri == null ? "" : elementUri;
 750                         String elementName = element.getLocalName();
 751                         if (elementUri.equals(nameUri)
 752                             && elementName.equals(nameLocal)) {
 753                             next = element;
 754                             break;
 755                         }
 756                     }
 757                 }
 758                 return next != null;
 759             }
 760 
 761             public Object next() {
 762                 if (!hasNext()) {
 763                     throw new NoSuchElementException();
 764                 }
 765                 last = next;
 766                 next = null;
 767                 return last;
 768             }
 769 
 770             public void remove() {
 771                 if (last == null) {
 772                     throw new IllegalStateException();
 773                 }
 774                 Node target = last;
 775                 last = null;
 776                 removeChild(target);
 777             }
 778         };
 779     }
 780 
 781     public void removeContents() {
 782         Node currentChild = getFirstChild();
 783 
 784         while (currentChild != null) {
 785             Node temp = currentChild.getNextSibling();
 786             if (currentChild instanceof javax.xml.soap.Node) {
 787                 ((javax.xml.soap.Node) currentChild).detachNode();
 788             } else {
 789                 Node parent = currentChild.getParentNode();
 790                 if (parent != null) {
 791                     parent.removeChild(currentChild);
 792                 }
 793 
 794             }
 795             currentChild = temp;
 796         }
 797     }
 798 
 799     public void setEncodingStyle(String encodingStyle) throws SOAPException {
 800         if (!"".equals(encodingStyle)) {
 801             try {
 802                 JaxmURI uri = new JaxmURI(encodingStyle);
 803             } catch (JaxmURI.MalformedURIException m) {
 804                 log.log(
 805                     Level.SEVERE,
 806                     "SAAJ0105.impl.encoding.style.mustbe.valid.URI",
 807                     new String[] { encodingStyle });
 808                 throw new IllegalArgumentException(
 809                     "Encoding style (" + encodingStyle + ") should be a valid URI");
 810             }
 811         }
 812         encodingStyleAttribute.setValue(encodingStyle);
 813         tryToFindEncodingStyleAttributeName();
 814     }
 815 
 816     public String getEncodingStyle() {
 817         String encodingStyle = encodingStyleAttribute.getValue();
 818         if (encodingStyle != null)
 819             return encodingStyle;
 820         String soapNamespace = getSOAPNamespace();
 821         if (soapNamespace != null) {
 822             Attr attr = getAttributeNodeNS(soapNamespace, "encodingStyle");
 823             if (attr != null) {
 824                 encodingStyle = attr.getValue();
 825                 try {
 826                     setEncodingStyle(encodingStyle);
 827                 } catch (SOAPException se) {
 828                     // has to be ignored
 829                 }
 830                 return encodingStyle;
 831             }
 832         }
 833         return null;
 834     }
 835 
 836     // Node methods
 837     public String getValue() {
 838         javax.xml.soap.Node valueNode = getValueNode();
 839         return valueNode == null ? null : valueNode.getValue();
 840     }
 841 
 842     public void setValue(String value) {
 843         Node valueNode = getValueNodeStrict();
 844         if (valueNode != null) {
 845             valueNode.setNodeValue(value);
 846         } else {
 847             try {
 848                 addTextNode(value);
 849             } catch (SOAPException e) {
 850                 throw new RuntimeException(e.getMessage());
 851             }
 852         }
 853     }
 854 
 855     protected Node getValueNodeStrict() {
 856         Node node = getFirstChild();
 857         if (node != null) {
 858             if (node.getNextSibling() == null
 859                 && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
 860                 return node;
 861             } else {
 862                 log.severe("SAAJ0107.impl.elem.child.not.single.text");
 863                 throw new IllegalStateException();
 864             }
 865         }
 866 
 867         return null;
 868     }
 869 
 870     protected javax.xml.soap.Node getValueNode() {
 871         Iterator i = getChildElements();
 872         while (i.hasNext()) {
 873             javax.xml.soap.Node n = (javax.xml.soap.Node) i.next();
 874             if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE ||
 875                 n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
 876                 // TODO: Hack to fix text node split into multiple lines.
 877                 normalize();
 878                 // Should remove the normalization step when this gets fixed in
 879                 // DOM/Xerces.
 880                 return (javax.xml.soap.Node) n;
 881             }
 882         }
 883         return null;
 884     }
 885 
 886     public void setParentElement(SOAPElement element) throws SOAPException {
 887         if (element == null) {
 888             log.severe("SAAJ0106.impl.no.null.to.parent.elem");
 889             throw new SOAPException("Cannot pass NULL to setParentElement");
 890         }
 891         element.addChildElement(this);
 892         findEncodingStyleAttributeName();
 893     }
 894 
 895     protected void findEncodingStyleAttributeName() throws SOAPException {
 896         String soapNamespace = getSOAPNamespace();
 897         if (soapNamespace != null) {
 898             String soapNamespacePrefix = getNamespacePrefix(soapNamespace);
 899             if (soapNamespacePrefix != null) {
 900                 setEncodingStyleNamespace(soapNamespace, soapNamespacePrefix);
 901             }
 902         }
 903     }
 904 
 905     protected void setEncodingStyleNamespace(
 906         String soapNamespace,
 907         String soapNamespacePrefix)
 908         throws SOAPException {
 909         Name encodingStyleAttributeName =
 910             NameImpl.create(
 911                 "encodingStyle",
 912                 soapNamespacePrefix,
 913                 soapNamespace);
 914         encodingStyleAttribute.setName(encodingStyleAttributeName);
 915     }
 916 
 917     public SOAPElement getParentElement() {
 918         Node parentNode = getParentNode();
 919         if (parentNode instanceof SOAPDocument) {
 920             return null;
 921         }
 922         return (SOAPElement) parentNode;
 923     }
 924 
 925     protected String getSOAPNamespace() {
 926         String soapNamespace = null;
 927 
 928         SOAPElement antecedent = this;
 929         while (antecedent != null) {
 930             Name antecedentName = antecedent.getElementName();
 931             String antecedentNamespace = antecedentName.getURI();
 932 
 933             if (NameImpl.SOAP11_NAMESPACE.equals(antecedentNamespace)
 934                 || NameImpl.SOAP12_NAMESPACE.equals(antecedentNamespace)) {
 935 
 936                 soapNamespace = antecedentNamespace;
 937                 break;
 938             }
 939 
 940             antecedent = antecedent.getParentElement();
 941         }
 942 
 943         return soapNamespace;
 944     }
 945 
 946     public void detachNode() {
 947         Node parent = getParentNode();
 948         if (parent != null) {
 949             parent.removeChild(this);
 950         }
 951         encodingStyleAttribute.clearNameAndValue();
 952         // Fix for CR: 6474641
 953         //tryToFindEncodingStyleAttributeName();
 954     }
 955 
 956     public void tryToFindEncodingStyleAttributeName() {
 957         try {
 958             findEncodingStyleAttributeName();
 959         } catch (SOAPException e) { /*okay to fail*/
 960         }
 961     }
 962 
 963     public void recycleNode() {
 964         detachNode();
 965         // TBD
 966         //  - add this to the factory so subsequent
 967         //    creations can reuse this object.
 968     }
 969 
 970     class AttributeManager {
 971         Name attributeName = null;
 972         String attributeValue = null;
 973 
 974         public void setName(Name newName) throws SOAPException {
 975             clearAttribute();
 976             attributeName = newName;
 977             reconcileAttribute();
 978         }
 979         public void clearName() {
 980             clearAttribute();
 981             attributeName = null;
 982         }
 983         public void setValue(String value) throws SOAPException {
 984             attributeValue = value;
 985             reconcileAttribute();
 986         }
 987         public Name getName() {
 988             return attributeName;
 989         }
 990         public String getValue() {
 991             return attributeValue;
 992         }
 993 
 994         /** Note: to be used only in detachNode method */
 995         public void clearNameAndValue() {
 996             attributeName = null;
 997             attributeValue = null;
 998         }
 999 
1000         private void reconcileAttribute() throws SOAPException {
1001             if (attributeName != null) {
1002                 removeAttribute(attributeName);
1003                 if (attributeValue != null) {
1004                     addAttribute(attributeName, attributeValue);
1005                 }
1006             }
1007         }
1008         private void clearAttribute() {
1009             if (attributeName != null) {
1010                 removeAttribute(attributeName);
1011             }
1012         }
1013     }
1014 
1015     protected static org.w3c.dom.Attr getNamespaceAttrFrom(
1016         Element element,
1017         String prefix) {
1018         NamespaceContextIterator eachNamespace =
1019             new NamespaceContextIterator(element);
1020         while (eachNamespace.hasNext()) {
1021             org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
1022             String declaredPrefix =
1023                 NameImpl.getLocalNameFromTagName(namespaceDecl.getNodeName());
1024             if (declaredPrefix.equals(prefix)) {
1025                 return namespaceDecl;
1026             }
1027         }
1028         return null;
1029     }
1030 
1031     protected static Iterator getAllAttributesFrom(final Element element) {
1032         final NamedNodeMap attributes = element.getAttributes();
1033 
1034         return new Iterator() {
1035             int attributesLength = attributes.getLength();
1036             int attributeIndex = 0;
1037             String currentName;
1038 
1039             public boolean hasNext() {
1040                 return attributeIndex < attributesLength;
1041             }
1042 
1043             public Object next() {
1044                 if (!hasNext()) {
1045                     throw new NoSuchElementException();
1046                 }
1047                 Node current = attributes.item(attributeIndex++);
1048                 currentName = current.getNodeName();
1049 
1050                 String prefix = NameImpl.getPrefixFromTagName(currentName);
1051                 if (prefix.length() == 0) {
1052                     return NameImpl.createFromUnqualifiedName(currentName);
1053                 } else {
1054                     Name attributeName =
1055                         NameImpl.createFromQualifiedName(
1056                             currentName,
1057                             current.getNamespaceURI());
1058                     return attributeName;
1059                 }
1060             }
1061 
1062             public void remove() {
1063                 if (currentName == null) {
1064                     throw new IllegalStateException();
1065                 }
1066                 attributes.removeNamedItem(currentName);
1067             }
1068         };
1069     }
1070 
1071     protected static String getAttributeValueFrom(Element element, Name name) {
1072       return getAttributeValueFrom(
1073           element,
1074           name.getURI(),
1075           name.getLocalName(),
1076           name.getPrefix(),
1077           name.getQualifiedName());
1078     }
1079 
1080     private static String getAttributeValueFrom(
1081         Element element,
1082         String uri,
1083         String localName,
1084         String prefix,
1085         String qualifiedName) {
1086 
1087         String nonzeroLengthUri =
1088             (uri == null || uri.length() == 0) ? null : uri;
1089 
1090         boolean mustUseGetAttributeNodeNS =  (nonzeroLengthUri != null);
1091 
1092         if (mustUseGetAttributeNodeNS) {
1093 
1094             if (!element.hasAttributeNS(uri, localName)) {
1095                 return null;
1096             }
1097 
1098             String attrValue =
1099                 element.getAttributeNS(nonzeroLengthUri, localName);
1100 
1101             return attrValue;
1102         }
1103 
1104         Attr attribute = null;
1105         attribute = element.getAttributeNode(qualifiedName);
1106 
1107         return attribute == null ? null : attribute.getValue();
1108     }
1109 
1110     protected static Iterator getChildElementsFrom(final Element element) {
1111         return new Iterator() {
1112             Node next = element.getFirstChild();
1113             Node nextNext = null;
1114             Node last = null;
1115 
1116             public boolean hasNext() {
1117                 if (next != null) {
1118                     return true;
1119                 }
1120                 if (next == null && nextNext != null) {
1121                     next = nextNext;
1122                 }
1123 
1124                 return next != null;
1125             }
1126 
1127             public Object next() {
1128                 if (hasNext()) {
1129                     last = next;
1130                     next = null;
1131 
1132                     if ((element instanceof ElementImpl)
1133                         && (last instanceof Element)) {
1134                         last =
1135                             ((ElementImpl) element).convertToSoapElement(
1136                                 (Element) last);
1137                     }
1138 
1139                     nextNext = last.getNextSibling();
1140                     return last;
1141                 }
1142                 throw new NoSuchElementException();
1143             }
1144 
1145             public void remove() {
1146                 if (last == null) {
1147                     throw new IllegalStateException();
1148                 }
1149                 Node target = last;
1150                 last = null;
1151                 element.removeChild(target);
1152             }
1153         };
1154     }
1155 
1156     public static String getQualifiedName(QName name) {
1157         String prefix = name.getPrefix();
1158         String localName = name.getLocalPart();
1159         String qualifiedName = null;
1160 
1161             if (prefix != null && prefix.length() > 0) {
1162                 qualifiedName = prefix + ":" + localName;
1163             } else {
1164                 qualifiedName = localName;
1165             }
1166          return qualifiedName;
1167     }
1168 
1169     public static String getLocalPart(String qualifiedName) {
1170         if (qualifiedName == null) {
1171             // Log
1172             throw new IllegalArgumentException("Cannot get local name for a \"null\" qualified name");
1173         }
1174 
1175         int index = qualifiedName.indexOf(':');
1176         if (index < 0)
1177             return qualifiedName;
1178         else
1179             return qualifiedName.substring(index + 1);
1180     }
1181 
1182     public static String getPrefix(String qualifiedName) {
1183         if (qualifiedName == null) {
1184             // Log
1185             throw new IllegalArgumentException("Cannot get prefix for a  \"null\" qualified name");
1186         }
1187 
1188         int index = qualifiedName.indexOf(':');
1189         if (index < 0)
1190             return "";
1191         else
1192             return qualifiedName.substring(0, index);
1193     }
1194 
1195     protected boolean isNamespaceQualified(Name name) {
1196         return !"".equals(name.getURI());
1197     }
1198 
1199     protected boolean isNamespaceQualified(QName name) {
1200         return !"".equals(name.getNamespaceURI());
1201     }
1202 
1203     protected SOAPElement circumventBug5034339(SOAPElement element) {
1204 
1205         Name elementName = element.getElementName();
1206         if (!isNamespaceQualified(elementName)) {
1207             String prefix = elementName.getPrefix();
1208             String defaultNamespace = getNamespaceURI(prefix);
1209             if (defaultNamespace != null) {
1210                 Name newElementName =
1211                     NameImpl.create(
1212                         elementName.getLocalName(),
1213                         elementName.getPrefix(),
1214                         defaultNamespace);
1215                 SOAPElement newElement = createElement(newElementName);
1216                 replaceChild(newElement, element);
1217                 return newElement;
1218             }
1219         }
1220         return element;
1221     }
1222 
1223     //TODO: This is a temporary SAAJ workaround for optimizing XWS
1224     // should be removed once the corresponding JAXP bug is fixed
1225     // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
1226     public void setAttributeNS(
1227         String namespaceURI,String qualifiedName, String value) {
1228         int index = qualifiedName.indexOf(':');
1229         String prefix, localName;
1230         if (index < 0) {
1231             prefix = null;
1232             localName = qualifiedName;
1233         }
1234         else {
1235             prefix = qualifiedName.substring(0, index);
1236             localName = qualifiedName.substring(index + 1);
1237         }
1238 
1239         // Workaround for bug 6467808 - This needs to be fixed in JAXP
1240 
1241         // Rolling back this fix, this is a wrong fix, infact its causing other regressions in JAXWS tck and
1242         // other tests, because of this change the namespace declarations on soapenv:Fault element are never
1243         // picked up. The fix for bug 6467808 should be in JAXP.
1244 //        if(elementQName.getLocalPart().equals("Fault") &&
1245 //                (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(value) ||
1246 //                SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(value)))
1247 //            return;
1248 
1249         super.setAttributeNS(namespaceURI,qualifiedName,value);
1250         //String tmpLocalName = this.getLocalName();
1251         String tmpURI = this.getNamespaceURI();
1252         boolean isIDNS = false;
1253         if( tmpURI != null && (tmpURI.equals(DSIG_NS) || tmpURI.equals(XENC_NS))){
1254             isIDNS = true;
1255         }
1256         //No need to check for Signature/encryption element
1257         //just check for namespace.
1258         if(localName.equals("Id")){
1259             if(namespaceURI == null || namespaceURI.equals("")){
1260                 setIdAttribute(localName,true);
1261             }else if(isIDNS || WSU_NS.equals(namespaceURI)){
1262                 setIdAttributeNS(namespaceURI,localName,true);
1263             }
1264         }
1265 
1266     }
1267 
1268 }