1 /* 2 * Copyright (c) 1997, 2012, 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 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 protected SOAPElement findChild(NameImpl name) { 428 Iterator eachChild = getChildElementNodes(); 429 while (eachChild.hasNext()) { 430 SOAPElement child = (SOAPElement) eachChild.next(); 431 if (child.getElementName().equals(name)) { 432 return child; 433 } 434 } 435 436 return null; 437 } 438 439 public SOAPElement addTextNode(String text) throws SOAPException { 440 if (text.startsWith(CDATAImpl.cdataUC) 441 || text.startsWith(CDATAImpl.cdataLC)) 442 return addCDATA( 443 text.substring(CDATAImpl.cdataUC.length(), text.length() - 3)); 444 return addText(text); 445 } 446 447 protected SOAPElement addCDATA(String text) throws SOAPException { 448 org.w3c.dom.Text cdata = 449 (org.w3c.dom.Text) getOwnerDocument().createCDATASection(text); 450 addNode(cdata); 451 return this; 452 } 453 454 protected SOAPElement addText(String text) throws SOAPException { 455 org.w3c.dom.Text textNode = 456 (org.w3c.dom.Text) getOwnerDocument().createTextNode(text); 457 addNode(textNode); 458 return this; 459 } 460 461 public SOAPElement addAttribute(Name name, String value) 462 throws SOAPException { 463 addAttributeBare(name, value); 464 if (!"".equals(name.getURI())) { 465 ensureNamespaceIsDeclared(name.getPrefix(), name.getURI()); 466 } 467 return this; 468 } 469 470 public SOAPElement addAttribute(QName qname, String value) 471 throws SOAPException { 472 addAttributeBare(qname, value); 473 if (!"".equals(qname.getNamespaceURI())) { 474 ensureNamespaceIsDeclared(qname.getPrefix(), qname.getNamespaceURI()); 475 } 476 return this; 477 } 478 479 private void addAttributeBare(Name name, String value) { 480 addAttributeBare( 481 name.getURI(), 482 name.getPrefix(), 483 name.getQualifiedName(), 484 value); 485 } 486 private void addAttributeBare(QName name, String value) { 487 addAttributeBare( 488 name.getNamespaceURI(), 489 name.getPrefix(), 490 getQualifiedName(name), 491 value); 492 } 493 494 private void addAttributeBare( 495 String uri, 496 String prefix, 497 String qualifiedName, 498 String value) { 499 500 uri = uri.length() == 0 ? null : uri; 501 if (qualifiedName.equals("xmlns")) { 502 uri = XMLNS_URI; 503 } 504 505 if (uri == null) { 506 setAttribute(qualifiedName, value); 507 } else { 508 setAttributeNS(uri, qualifiedName, value); 509 } 510 } 511 512 public SOAPElement addNamespaceDeclaration(String prefix, String uri) 513 throws SOAPException { 514 if (prefix.length() > 0) { 515 setAttributeNS(XMLNS_URI, "xmlns:" + prefix, uri); 516 } else { 517 setAttributeNS(XMLNS_URI, "xmlns", uri); 518 } 519 //Fix for CR:6474641 520 //tryToFindEncodingStyleAttributeName(); 521 return this; 522 } 523 524 public String getAttributeValue(Name name) { 525 return getAttributeValueFrom(this, name); 526 } 527 528 public String getAttributeValue(QName qname) { 529 return getAttributeValueFrom( 530 this, 531 qname.getNamespaceURI(), 532 qname.getLocalPart(), 533 qname.getPrefix(), 534 getQualifiedName(qname)); 535 } 536 537 public Iterator getAllAttributes() { 538 Iterator i = getAllAttributesFrom(this); 539 ArrayList list = new ArrayList(); 540 while (i.hasNext()) { 541 Name name = (Name) i.next(); 542 if (!"xmlns".equalsIgnoreCase(name.getPrefix())) 543 list.add(name); 544 } 545 return list.iterator(); 546 } 547 548 public Iterator getAllAttributesAsQNames() { 549 Iterator i = getAllAttributesFrom(this); 550 ArrayList list = new ArrayList(); 551 while (i.hasNext()) { 552 Name name = (Name) i.next(); 553 if (!"xmlns".equalsIgnoreCase(name.getPrefix())) { 554 list.add(NameImpl.convertToQName(name)); 555 } 556 } 557 return list.iterator(); 558 } 559 560 561 public Iterator getNamespacePrefixes() { 562 return doGetNamespacePrefixes(false); 563 } 564 565 public Iterator getVisibleNamespacePrefixes() { 566 return doGetNamespacePrefixes(true); 567 } 568 569 protected Iterator doGetNamespacePrefixes(final boolean deep) { 570 return new Iterator() { 571 String next = null; 572 String last = null; 573 NamespaceContextIterator eachNamespace = 574 getNamespaceContextNodes(deep); 575 576 void findNext() { 577 while (next == null && eachNamespace.hasNext()) { 578 String attributeKey = 579 eachNamespace.nextNamespaceAttr().getNodeName(); 580 if (attributeKey.startsWith("xmlns:")) { 581 next = attributeKey.substring("xmlns:".length()); 582 } 583 } 584 } 585 586 public boolean hasNext() { 587 findNext(); 588 return next != null; 589 } 590 591 public Object next() { 592 findNext(); 593 if (next == null) { 594 throw new NoSuchElementException(); 595 } 596 597 last = next; 598 next = null; 599 return last; 600 } 601 602 public void remove() { 603 if (last == null) { 604 throw new IllegalStateException(); 605 } 606 eachNamespace.remove(); 607 next = null; 608 last = null; 609 } 610 }; 611 } 612 613 public Name getElementName() { 614 return NameImpl.convertToName(elementQName); 615 } 616 617 public QName getElementQName() { 618 return elementQName; 619 } 620 621 public boolean removeAttribute(Name name) { 622 return removeAttribute(name.getURI(), name.getLocalName()); 623 } 624 625 public boolean removeAttribute(QName name) { 626 return removeAttribute(name.getNamespaceURI(), name.getLocalPart()); 627 } 628 629 private boolean removeAttribute(String uri, String localName) { 630 String nonzeroLengthUri = 631 (uri == null || uri.length() == 0) ? null : uri; 632 org.w3c.dom.Attr attribute = 633 getAttributeNodeNS(nonzeroLengthUri, localName); 634 if (attribute == null) { 635 return false; 636 } 637 removeAttributeNode(attribute); 638 return true; 639 } 640 641 public boolean removeNamespaceDeclaration(String prefix) { 642 org.w3c.dom.Attr declaration = getNamespaceAttr(prefix); 643 if (declaration == null) { 644 return false; 645 } 646 try { 647 removeAttributeNode(declaration); 648 } catch (DOMException de) { 649 // ignore 650 } 651 return true; 652 } 653 654 public Iterator getChildElements() { 655 return getChildElementsFrom(this); 656 } 657 658 protected SOAPElement convertToSoapElement(Element element) { 659 if (element instanceof SOAPElement) { 660 return (SOAPElement) element; 661 } else { 662 return replaceElementWithSOAPElement( 663 element, 664 (ElementImpl) createElement(NameImpl.copyElementName(element))); 665 } 666 } 667 668 protected static SOAPElement replaceElementWithSOAPElement( 669 Element element, 670 ElementImpl copy) { 671 672 Iterator eachAttribute = getAllAttributesFrom(element); 673 while (eachAttribute.hasNext()) { 674 Name name = (Name) eachAttribute.next(); 675 copy.addAttributeBare(name, getAttributeValueFrom(element, name)); 676 } 677 678 Iterator eachChild = getChildElementsFrom(element); 679 while (eachChild.hasNext()) { 680 Node nextChild = (Node) eachChild.next(); 681 copy.insertBefore(nextChild, null); 682 } 683 684 Node parent = element.getParentNode(); 685 if (parent != null) { 686 parent.replaceChild(copy, element); 687 } // XXX else throw an exception? 688 689 return copy; 690 } 691 692 protected Iterator getChildElementNodes() { 693 return new Iterator() { 694 Iterator eachNode = getChildElements(); 695 Node next = null; 696 Node last = null; 697 698 public boolean hasNext() { 699 if (next == null) { 700 while (eachNode.hasNext()) { 701 Node node = (Node) eachNode.next(); 702 if (node instanceof SOAPElement) { 703 next = node; 704 break; 705 } 706 } 707 } 708 return next != null; 709 } 710 711 public Object next() { 712 if (hasNext()) { 713 last = next; 714 next = null; 715 return last; 716 } 717 throw new NoSuchElementException(); 718 } 719 720 public void remove() { 721 if (last == null) { 722 throw new IllegalStateException(); 723 } 724 Node target = last; 725 last = null; 726 removeChild(target); 727 } 728 }; 729 } 730 731 public Iterator getChildElements(final Name name) { 732 return getChildElements(name.getURI(), name.getLocalName()); 733 } 734 735 public Iterator getChildElements(final QName qname) { 736 return getChildElements(qname.getNamespaceURI(), qname.getLocalPart()); 737 } 738 739 private Iterator getChildElements(final String nameUri, final String nameLocal) { 740 return new Iterator() { 741 Iterator eachElement = getChildElementNodes(); 742 Node next = null; 743 Node last = null; 744 745 public boolean hasNext() { 746 if (next == null) { 747 while (eachElement.hasNext()) { 748 Node element = (Node) eachElement.next(); 749 String elementUri = element.getNamespaceURI(); 750 elementUri = elementUri == null ? "" : elementUri; 751 String elementName = element.getLocalName(); 752 if (elementUri.equals(nameUri) 753 && elementName.equals(nameLocal)) { 754 next = element; 755 break; 756 } 757 } 758 } 759 return next != null; 760 } 761 762 public Object next() { 763 if (!hasNext()) { 764 throw new NoSuchElementException(); 765 } 766 last = next; 767 next = null; 768 return last; 769 } 770 771 public void remove() { 772 if (last == null) { 773 throw new IllegalStateException(); 774 } 775 Node target = last; 776 last = null; 777 removeChild(target); 778 } 779 }; 780 } 781 782 public void removeContents() { 783 Node currentChild = getFirstChild(); 784 785 while (currentChild != null) { 786 Node temp = currentChild.getNextSibling(); 787 if (currentChild instanceof javax.xml.soap.Node) { 788 ((javax.xml.soap.Node) currentChild).detachNode(); 789 } else { 790 Node parent = currentChild.getParentNode(); 791 if (parent != null) { 792 parent.removeChild(currentChild); 793 } 794 795 } 796 currentChild = temp; 797 } 798 } 799 800 public void setEncodingStyle(String encodingStyle) throws SOAPException { 801 if (!"".equals(encodingStyle)) { 802 try { 803 new URI(encodingStyle); 804 } catch (URISyntaxException m) { 805 log.log( 806 Level.SEVERE, 807 "SAAJ0105.impl.encoding.style.mustbe.valid.URI", 808 new String[] { encodingStyle }); 809 throw new IllegalArgumentException( 810 "Encoding style (" + encodingStyle + ") should be a valid URI"); 811 } 812 } 813 encodingStyleAttribute.setValue(encodingStyle); 814 tryToFindEncodingStyleAttributeName(); 815 } 816 817 public String getEncodingStyle() { 818 String encodingStyle = encodingStyleAttribute.getValue(); 819 if (encodingStyle != null) 820 return encodingStyle; 821 String soapNamespace = getSOAPNamespace(); 822 if (soapNamespace != null) { 823 Attr attr = getAttributeNodeNS(soapNamespace, "encodingStyle"); 824 if (attr != null) { 825 encodingStyle = attr.getValue(); 826 try { 827 setEncodingStyle(encodingStyle); 828 } catch (SOAPException se) { 829 // has to be ignored 830 } 831 return encodingStyle; 832 } 833 } 834 return null; 835 } 836 837 // Node methods 838 public String getValue() { 839 javax.xml.soap.Node valueNode = getValueNode(); 840 return valueNode == null ? null : valueNode.getValue(); 841 } 842 843 public void setValue(String value) { 844 Node valueNode = getValueNodeStrict(); 845 if (valueNode != null) { 846 valueNode.setNodeValue(value); 847 } else { 848 try { 849 addTextNode(value); 850 } catch (SOAPException e) { 851 throw new RuntimeException(e.getMessage()); 852 } 853 } 854 } 855 856 protected Node getValueNodeStrict() { 857 Node node = getFirstChild(); 858 if (node != null) { 859 if (node.getNextSibling() == null 860 && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) { 861 return node; 862 } else { 863 log.severe("SAAJ0107.impl.elem.child.not.single.text"); 864 throw new IllegalStateException(); 865 } 866 } 867 868 return null; 869 } 870 871 protected javax.xml.soap.Node getValueNode() { 872 Iterator i = getChildElements(); 873 while (i.hasNext()) { 874 javax.xml.soap.Node n = (javax.xml.soap.Node) i.next(); 875 if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE || 876 n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) { 877 // TODO: Hack to fix text node split into multiple lines. 878 normalize(); 879 // Should remove the normalization step when this gets fixed in 880 // DOM/Xerces. 881 return (javax.xml.soap.Node) n; 882 } 883 } 884 return null; 885 } 886 887 public void setParentElement(SOAPElement element) throws SOAPException { 888 if (element == null) { 889 log.severe("SAAJ0106.impl.no.null.to.parent.elem"); 890 throw new SOAPException("Cannot pass NULL to setParentElement"); 891 } 892 element.addChildElement(this); 893 findEncodingStyleAttributeName(); 894 } 895 896 protected void findEncodingStyleAttributeName() throws SOAPException { 897 String soapNamespace = getSOAPNamespace(); 898 if (soapNamespace != null) { 899 String soapNamespacePrefix = getNamespacePrefix(soapNamespace); 900 if (soapNamespacePrefix != null) { 901 setEncodingStyleNamespace(soapNamespace, soapNamespacePrefix); 902 } 903 } 904 } 905 906 protected void setEncodingStyleNamespace( 907 String soapNamespace, 908 String soapNamespacePrefix) 909 throws SOAPException { 910 Name encodingStyleAttributeName = 911 NameImpl.create( 912 "encodingStyle", 913 soapNamespacePrefix, 914 soapNamespace); 915 encodingStyleAttribute.setName(encodingStyleAttributeName); 916 } 917 918 public SOAPElement getParentElement() { 919 Node parentNode = getParentNode(); 920 if (parentNode instanceof SOAPDocument) { 921 return null; 922 } 923 return (SOAPElement) parentNode; 924 } 925 926 protected String getSOAPNamespace() { 927 String soapNamespace = null; 928 929 SOAPElement antecedent = this; 930 while (antecedent != null) { 931 Name antecedentName = antecedent.getElementName(); 932 String antecedentNamespace = antecedentName.getURI(); 933 934 if (NameImpl.SOAP11_NAMESPACE.equals(antecedentNamespace) 935 || NameImpl.SOAP12_NAMESPACE.equals(antecedentNamespace)) { 936 937 soapNamespace = antecedentNamespace; 938 break; 939 } 940 941 antecedent = antecedent.getParentElement(); 942 } 943 944 return soapNamespace; 945 } 946 947 public void detachNode() { 948 Node parent = getParentNode(); 949 if (parent != null) { 950 parent.removeChild(this); 951 } 952 encodingStyleAttribute.clearNameAndValue(); 953 // Fix for CR: 6474641 954 //tryToFindEncodingStyleAttributeName(); 955 } 956 957 public void tryToFindEncodingStyleAttributeName() { 958 try { 959 findEncodingStyleAttributeName(); 960 } catch (SOAPException e) { /*okay to fail*/ 961 } 962 } 963 964 public void recycleNode() { 965 detachNode(); 966 // TBD 967 // - add this to the factory so subsequent 968 // creations can reuse this object. 969 } 970 971 class AttributeManager { 972 Name attributeName = null; 973 String attributeValue = null; 974 975 public void setName(Name newName) throws SOAPException { 976 clearAttribute(); 977 attributeName = newName; 978 reconcileAttribute(); 979 } 980 public void clearName() { 981 clearAttribute(); 982 attributeName = null; 983 } 984 public void setValue(String value) throws SOAPException { 985 attributeValue = value; 986 reconcileAttribute(); 987 } 988 public Name getName() { 989 return attributeName; 990 } 991 public String getValue() { 992 return attributeValue; 993 } 994 995 /** Note: to be used only in detachNode method */ 996 public void clearNameAndValue() { 997 attributeName = null; 998 attributeValue = null; 999 } 1000 1001 private void reconcileAttribute() throws SOAPException { 1002 if (attributeName != null) { 1003 removeAttribute(attributeName); 1004 if (attributeValue != null) { 1005 addAttribute(attributeName, attributeValue); 1006 } 1007 } 1008 } 1009 private void clearAttribute() { 1010 if (attributeName != null) { 1011 removeAttribute(attributeName); 1012 } 1013 } 1014 } 1015 1016 protected static org.w3c.dom.Attr getNamespaceAttrFrom( 1017 Element element, 1018 String prefix) { 1019 NamespaceContextIterator eachNamespace = 1020 new NamespaceContextIterator(element); 1021 while (eachNamespace.hasNext()) { 1022 org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr(); 1023 String declaredPrefix = 1024 NameImpl.getLocalNameFromTagName(namespaceDecl.getNodeName()); 1025 if (declaredPrefix.equals(prefix)) { 1026 return namespaceDecl; 1027 } 1028 } 1029 return null; 1030 } 1031 1032 protected static Iterator getAllAttributesFrom(final Element element) { 1033 final NamedNodeMap attributes = element.getAttributes(); 1034 1035 return new Iterator() { 1036 int attributesLength = attributes.getLength(); 1037 int attributeIndex = 0; 1038 String currentName; 1039 1040 public boolean hasNext() { 1041 return attributeIndex < attributesLength; 1042 } 1043 1044 public Object next() { 1045 if (!hasNext()) { 1046 throw new NoSuchElementException(); 1047 } 1048 Node current = attributes.item(attributeIndex++); 1049 currentName = current.getNodeName(); 1050 1051 String prefix = NameImpl.getPrefixFromTagName(currentName); 1052 if (prefix.length() == 0) { 1053 return NameImpl.createFromUnqualifiedName(currentName); 1054 } else { 1055 Name attributeName = 1056 NameImpl.createFromQualifiedName( 1057 currentName, 1058 current.getNamespaceURI()); 1059 return attributeName; 1060 } 1061 } 1062 1063 public void remove() { 1064 if (currentName == null) { 1065 throw new IllegalStateException(); 1066 } 1067 attributes.removeNamedItem(currentName); 1068 } 1069 }; 1070 } 1071 1072 protected static String getAttributeValueFrom(Element element, Name name) { 1073 return getAttributeValueFrom( 1074 element, 1075 name.getURI(), 1076 name.getLocalName(), 1077 name.getPrefix(), 1078 name.getQualifiedName()); 1079 } 1080 1081 private static String getAttributeValueFrom( 1082 Element element, 1083 String uri, 1084 String localName, 1085 String prefix, 1086 String qualifiedName) { 1087 1088 String nonzeroLengthUri = 1089 (uri == null || uri.length() == 0) ? null : uri; 1090 1091 boolean mustUseGetAttributeNodeNS = (nonzeroLengthUri != null); 1092 1093 if (mustUseGetAttributeNodeNS) { 1094 1095 if (!element.hasAttributeNS(uri, localName)) { 1096 return null; 1097 } 1098 1099 String attrValue = 1100 element.getAttributeNS(nonzeroLengthUri, localName); 1101 1102 return attrValue; 1103 } 1104 1105 Attr attribute = null; 1106 attribute = element.getAttributeNode(qualifiedName); 1107 1108 return attribute == null ? null : attribute.getValue(); 1109 } 1110 1111 protected static Iterator getChildElementsFrom(final Element element) { 1112 return new Iterator() { 1113 Node next = element.getFirstChild(); 1114 Node nextNext = null; 1115 Node last = null; 1116 1117 public boolean hasNext() { 1118 if (next != null) { 1119 return true; 1120 } 1121 if (next == null && nextNext != null) { 1122 next = nextNext; 1123 } 1124 1125 return next != null; 1126 } 1127 1128 public Object next() { 1129 if (hasNext()) { 1130 last = next; 1131 next = null; 1132 1133 if ((element instanceof ElementImpl) 1134 && (last instanceof Element)) { 1135 last = 1136 ((ElementImpl) element).convertToSoapElement( 1137 (Element) last); 1138 } 1139 1140 nextNext = last.getNextSibling(); 1141 return last; 1142 } 1143 throw new NoSuchElementException(); 1144 } 1145 1146 public void remove() { 1147 if (last == null) { 1148 throw new IllegalStateException(); 1149 } 1150 Node target = last; 1151 last = null; 1152 element.removeChild(target); 1153 } 1154 }; 1155 } 1156 1157 public static String getQualifiedName(QName name) { 1158 String prefix = name.getPrefix(); 1159 String localName = name.getLocalPart(); 1160 String qualifiedName = null; 1161 1162 if (prefix != null && prefix.length() > 0) { 1163 qualifiedName = prefix + ":" + localName; 1164 } else { 1165 qualifiedName = localName; 1166 } 1167 return qualifiedName; 1168 } 1169 1170 public static String getLocalPart(String qualifiedName) { 1171 if (qualifiedName == null) { 1172 // Log 1173 throw new IllegalArgumentException("Cannot get local name for a \"null\" qualified name"); 1174 } 1175 1176 int index = qualifiedName.indexOf(':'); 1177 if (index < 0) 1178 return qualifiedName; 1179 else 1180 return qualifiedName.substring(index + 1); 1181 } 1182 1183 public static String getPrefix(String qualifiedName) { 1184 if (qualifiedName == null) { 1185 // Log 1186 throw new IllegalArgumentException("Cannot get prefix for a \"null\" qualified name"); 1187 } 1188 1189 int index = qualifiedName.indexOf(':'); 1190 if (index < 0) 1191 return ""; 1192 else 1193 return qualifiedName.substring(0, index); 1194 } 1195 1196 protected boolean isNamespaceQualified(Name name) { 1197 return !"".equals(name.getURI()); 1198 } 1199 1200 protected boolean isNamespaceQualified(QName name) { 1201 return !"".equals(name.getNamespaceURI()); 1202 } 1203 1204 protected SOAPElement circumventBug5034339(SOAPElement element) { 1205 1206 Name elementName = element.getElementName(); 1207 if (!isNamespaceQualified(elementName)) { 1208 String prefix = elementName.getPrefix(); 1209 String defaultNamespace = getNamespaceURI(prefix); 1210 if (defaultNamespace != null) { 1211 Name newElementName = 1212 NameImpl.create( 1213 elementName.getLocalName(), 1214 elementName.getPrefix(), 1215 defaultNamespace); 1216 SOAPElement newElement = createElement(newElementName); 1217 replaceChild(newElement, element); 1218 return newElement; 1219 } 1220 } 1221 return element; 1222 } 1223 1224 //TODO: This is a temporary SAAJ workaround for optimizing XWS 1225 // should be removed once the corresponding JAXP bug is fixed 1226 // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe) 1227 public void setAttributeNS( 1228 String namespaceURI,String qualifiedName, String value) { 1229 int index = qualifiedName.indexOf(':'); 1230 String localName; 1231 if (index < 0) 1232 localName = qualifiedName; 1233 else 1234 localName = qualifiedName.substring(index + 1); 1235 1236 // Workaround for bug 6467808 - This needs to be fixed in JAXP 1237 1238 // Rolling back this fix, this is a wrong fix, infact its causing other regressions in JAXWS tck and 1239 // other tests, because of this change the namespace declarations on soapenv:Fault element are never 1240 // picked up. The fix for bug 6467808 should be in JAXP. 1241 // if(elementQName.getLocalPart().equals("Fault") && 1242 // (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(value) || 1243 // SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(value))) 1244 // return; 1245 1246 super.setAttributeNS(namespaceURI,qualifiedName,value); 1247 //String tmpLocalName = this.getLocalName(); 1248 String tmpURI = this.getNamespaceURI(); 1249 boolean isIDNS = false; 1250 if( tmpURI != null && (tmpURI.equals(DSIG_NS) || tmpURI.equals(XENC_NS))){ 1251 isIDNS = true; 1252 } 1253 //No need to check for Signature/encryption element 1254 //just check for namespace. 1255 if(localName.equals("Id")){ 1256 if(namespaceURI == null || namespaceURI.equals("")){ 1257 setIdAttribute(localName,true); 1258 }else if(isIDNS || WSU_NS.equals(namespaceURI)){ 1259 setIdAttributeNS(namespaceURI,localName,true); 1260 } 1261 } 1262 1263 } 1264 1265 }