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