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 }