Thu, 24 May 2018 17:55:52 +0800
Merge
1 /*
2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.messaging.saaj.soap.impl;
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;
34 import javax.xml.namespace.QName;
35 import javax.xml.soap.*;
37 import org.w3c.dom.*;
38 import org.w3c.dom.Node;
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.*;
46 public class ElementImpl
47 extends com.sun.org.apache.xerces.internal.dom.ElementNSImpl
48 implements SOAPElement, SOAPBodyElement {
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();
54 private AttributeManager encodingStyleAttribute = new AttributeManager();
56 protected QName elementQName;
58 protected static final Logger log =
59 Logger.getLogger(LogDomainConstants.SOAP_IMPL_DOMAIN,
60 "com.sun.xml.internal.messaging.saaj.soap.impl.LocalStrings");
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();
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();
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 }
84 public ElementImpl(SOAPDocumentImpl ownerDoc, QName name) {
85 super(
86 ownerDoc,
87 name.getNamespaceURI(),
88 getQualifiedName(name),
89 name.getLocalPart());
90 elementQName = name;
91 }
93 public ElementImpl(
94 SOAPDocumentImpl ownerDoc,
95 String uri,
96 String qualifiedName) {
98 super(ownerDoc, uri, qualifiedName);
99 elementQName =
100 new QName(uri, getLocalPart(qualifiedName), getPrefix(qualifiedName));
101 }
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 }
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 }
121 public SOAPElement addChildElement(Name name) throws SOAPException {
122 return addElement(name);
123 }
125 public SOAPElement addChildElement(QName qname) throws SOAPException {
126 return addElement(qname);
127 }
129 public SOAPElement addChildElement(String localName) throws SOAPException {
130 String nsUri = getNamespaceURI("");
131 Name name = (nsUri == null || nsUri.isEmpty())
132 ? NameImpl.createFromUnqualifiedName(localName)
133 : NameImpl.createFromQualifiedName(localName, nsUri);
134 return addChildElement(name);
135 }
137 public SOAPElement addChildElement(String localName, String prefix)
138 throws SOAPException {
139 String uri = getNamespaceURI(prefix);
140 if (uri == null) {
141 log.log(
142 Level.SEVERE,
143 "SAAJ0101.impl.parent.of.body.elem.mustbe.body",
144 new String[] { prefix });
145 throw new SOAPExceptionImpl(
146 "Unable to locate namespace for prefix " + prefix);
147 }
148 return addChildElement(localName, prefix, uri);
149 }
151 public String getNamespaceURI(String prefix) {
153 if ("xmlns".equals(prefix)) {
154 return XMLNS_URI;
155 }
157 if("xml".equals(prefix)) {
158 return XML_URI;
159 }
161 if ("".equals(prefix)) {
163 org.w3c.dom.Node currentAncestor = this;
164 while (currentAncestor != null &&
165 !(currentAncestor instanceof Document)) {
167 if (currentAncestor instanceof ElementImpl) {
168 QName name = ((ElementImpl) currentAncestor).getElementQName();
169 /*
170 if (prefix.equals(name.getPrefix())) {
171 String uri = name.getNamespaceURI();
172 if ("".equals(uri)) {
173 return null;
174 }
175 else {
176 return uri;
177 }
178 }*/
179 if (((Element) currentAncestor).hasAttributeNS(
180 XMLNS_URI, "xmlns")) {
182 String uri =
183 ((Element) currentAncestor).getAttributeNS(
184 XMLNS_URI, "xmlns");
185 if ("".equals(uri))
186 return null;
187 else {
188 return uri;
189 }
190 }
191 }
192 currentAncestor = currentAncestor.getParentNode();
193 }
195 } else if (prefix != null) {
196 // Find if there's an ancester whose name contains this prefix
197 org.w3c.dom.Node currentAncestor = this;
199 // String uri = currentAncestor.lookupNamespaceURI(prefix);
200 // return uri;
201 while (currentAncestor != null &&
202 !(currentAncestor instanceof Document)) {
204 /* if (prefix.equals(currentAncestor.getPrefix())) {
205 String uri = currentAncestor.getNamespaceURI();
206 // this is because the javadoc says getNamespaceURI() is not a computed value
207 // and URI for a non-empty prefix cannot be null
208 if (uri != null)
209 return uri;
210 }*/
211 //String uri = currentAncestor.lookupNamespaceURI(prefix);
212 //if (uri != null) {
213 // return uri;
214 //}
216 if (((Element) currentAncestor).hasAttributeNS(
217 XMLNS_URI, prefix)) {
218 return ((Element) currentAncestor).getAttributeNS(
219 XMLNS_URI, prefix);
220 }
222 currentAncestor = currentAncestor.getParentNode();
223 }
224 }
226 return null;
227 }
229 public SOAPElement setElementQName(QName newName) throws SOAPException {
230 ElementImpl copy =
231 new ElementImpl((SOAPDocumentImpl) getOwnerDocument(), newName);
232 return replaceElementWithSOAPElement(this,copy);
233 }
235 public QName createQName(String localName, String prefix)
236 throws SOAPException {
237 String uri = getNamespaceURI(prefix);
238 if (uri == null) {
239 log.log(Level.SEVERE, "SAAJ0102.impl.cannot.locate.ns",
240 new Object[] {prefix});
241 throw new SOAPException("Unable to locate namespace for prefix "
242 + prefix);
243 }
244 return new QName(uri, localName, prefix);
245 }
247 public String getNamespacePrefix(String uri) {
249 NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
250 while (eachNamespace.hasNext()) {
251 org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
252 if (namespaceDecl.getNodeValue().equals(uri)) {
253 String candidatePrefix = namespaceDecl.getLocalName();
254 if ("xmlns".equals(candidatePrefix))
255 return "";
256 else
257 return candidatePrefix;
258 }
259 }
261 // Find if any of the ancestors' name has this uri
262 org.w3c.dom.Node currentAncestor = this;
263 while (currentAncestor != null &&
264 !(currentAncestor instanceof Document)) {
266 if (uri.equals(currentAncestor.getNamespaceURI()))
267 return currentAncestor.getPrefix();
268 currentAncestor = currentAncestor.getParentNode();
269 }
271 return null;
272 }
274 protected org.w3c.dom.Attr getNamespaceAttr(String prefix) {
275 NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
276 if (!"".equals(prefix))
277 prefix = ":"+prefix;
278 while (eachNamespace.hasNext()) {
279 org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
280 if (!"".equals(prefix)) {
281 if (namespaceDecl.getNodeName().endsWith(prefix))
282 return namespaceDecl;
283 } else {
284 if (namespaceDecl.getNodeName().equals("xmlns"))
285 return namespaceDecl;
286 }
287 }
288 return null;
289 }
291 public NamespaceContextIterator getNamespaceContextNodes() {
292 return getNamespaceContextNodes(true);
293 }
295 public NamespaceContextIterator getNamespaceContextNodes(boolean traverseStack) {
296 return new NamespaceContextIterator(this, traverseStack);
297 }
299 public SOAPElement addChildElement(
300 String localName,
301 String prefix,
302 String uri)
303 throws SOAPException {
305 SOAPElement newElement = createElement(NameImpl.create(localName, prefix, uri));
306 addNode(newElement);
307 return convertToSoapElement(newElement);
308 }
310 public SOAPElement addChildElement(SOAPElement element)
311 throws SOAPException {
313 // check if Element falls in SOAP 1.1 or 1.2 namespace.
314 String elementURI = element.getElementName().getURI();
315 String localName = element.getLocalName();
317 if ((SOAPConstants.URI_NS_SOAP_ENVELOPE).equals(elementURI)
318 || (SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE).equals(elementURI)) {
321 if ("Envelope".equalsIgnoreCase(localName) ||
322 "Header".equalsIgnoreCase(localName) || "Body".equalsIgnoreCase(localName)) {
323 log.severe("SAAJ0103.impl.cannot.add.fragements");
324 throw new SOAPExceptionImpl(
325 "Cannot add fragments which contain elements "
326 + "which are in the SOAP namespace");
327 }
329 if ("Fault".equalsIgnoreCase(localName) && !"Body".equalsIgnoreCase(this.getLocalName())) {
330 log.severe("SAAJ0154.impl.adding.fault.to.nonbody");
331 throw new SOAPExceptionImpl("Cannot add a SOAPFault as a child of " + this.getLocalName());
332 }
334 if ("Detail".equalsIgnoreCase(localName) && !"Fault".equalsIgnoreCase(this.getLocalName())) {
335 log.severe("SAAJ0155.impl.adding.detail.nonfault");
336 throw new SOAPExceptionImpl("Cannot add a Detail as a child of " + this.getLocalName());
337 }
339 if ("Fault".equalsIgnoreCase(localName)) {
340 // if body is not empty throw an exception
341 if (!elementURI.equals(this.getElementName().getURI())) {
342 log.severe("SAAJ0158.impl.version.mismatch.fault");
343 throw new SOAPExceptionImpl("SOAP Version mismatch encountered when trying to add SOAPFault to SOAPBody");
344 }
345 Iterator it = this.getChildElements();
346 if (it.hasNext()) {
347 log.severe("SAAJ0156.impl.adding.fault.error");
348 throw new SOAPExceptionImpl("Cannot add SOAPFault as a child of a non-Empty SOAPBody");
349 }
350 }
351 }
353 // preserve the encodingStyle attr as it may get lost in the import
354 String encodingStyle = element.getEncodingStyle();
356 ElementImpl importedElement = (ElementImpl) importElement(element);
357 addNode(importedElement);
359 if (encodingStyle != null)
360 importedElement.setEncodingStyle(encodingStyle);
362 return convertToSoapElement(importedElement);
363 }
365 protected Element importElement(Element element) {
366 Document document = getOwnerDocument();
367 Document oldDocument = element.getOwnerDocument();
368 if (!oldDocument.equals(document)) {
369 return (Element) document.importNode(element, true);
370 } else {
371 return element;
372 }
373 }
375 protected SOAPElement addElement(Name name) throws SOAPException {
376 SOAPElement newElement = createElement(name);
377 addNode(newElement);
378 return newElement;
379 }
381 protected SOAPElement addElement(QName name) throws SOAPException {
382 SOAPElement newElement = createElement(name);
383 addNode(newElement);
384 return newElement;
385 }
387 protected SOAPElement createElement(Name name) {
389 if (isNamespaceQualified(name)) {
390 return (SOAPElement)
391 getOwnerDocument().createElementNS(
392 name.getURI(),
393 name.getQualifiedName());
394 } else {
395 return (SOAPElement)
396 getOwnerDocument().createElement(name.getQualifiedName());
397 }
398 }
400 protected SOAPElement createElement(QName name) {
402 if (isNamespaceQualified(name)) {
403 return (SOAPElement)
404 getOwnerDocument().createElementNS(
405 name.getNamespaceURI(),
406 getQualifiedName(name));
407 } else {
408 return (SOAPElement)
409 getOwnerDocument().createElement(getQualifiedName(name));
410 }
411 }
413 protected void addNode(org.w3c.dom.Node newElement) throws SOAPException {
414 insertBefore(newElement, null);
416 if (getOwnerDocument() instanceof DocumentFragment)
417 return;
419 if (newElement instanceof ElementImpl) {
420 ElementImpl element = (ElementImpl) newElement;
421 QName elementName = element.getElementQName();
422 if (!"".equals(elementName.getNamespaceURI())) {
423 element.ensureNamespaceIsDeclared(
424 elementName.getPrefix(), elementName.getNamespaceURI());
425 }
426 }
428 }
430 protected SOAPElement findChild(NameImpl name) {
431 Iterator eachChild = getChildElementNodes();
432 while (eachChild.hasNext()) {
433 SOAPElement child = (SOAPElement) eachChild.next();
434 if (child.getElementName().equals(name)) {
435 return child;
436 }
437 }
439 return null;
440 }
442 public SOAPElement addTextNode(String text) throws SOAPException {
443 if (text.startsWith(CDATAImpl.cdataUC)
444 || text.startsWith(CDATAImpl.cdataLC))
445 return addCDATA(
446 text.substring(CDATAImpl.cdataUC.length(), text.length() - 3));
447 return addText(text);
448 }
450 protected SOAPElement addCDATA(String text) throws SOAPException {
451 org.w3c.dom.Text cdata =
452 (org.w3c.dom.Text) getOwnerDocument().createCDATASection(text);
453 addNode(cdata);
454 return this;
455 }
457 protected SOAPElement addText(String text) throws SOAPException {
458 org.w3c.dom.Text textNode =
459 (org.w3c.dom.Text) getOwnerDocument().createTextNode(text);
460 addNode(textNode);
461 return this;
462 }
464 public SOAPElement addAttribute(Name name, String value)
465 throws SOAPException {
466 addAttributeBare(name, value);
467 if (!"".equals(name.getURI())) {
468 ensureNamespaceIsDeclared(name.getPrefix(), name.getURI());
469 }
470 return this;
471 }
473 public SOAPElement addAttribute(QName qname, String value)
474 throws SOAPException {
475 addAttributeBare(qname, value);
476 if (!"".equals(qname.getNamespaceURI())) {
477 ensureNamespaceIsDeclared(qname.getPrefix(), qname.getNamespaceURI());
478 }
479 return this;
480 }
482 private void addAttributeBare(Name name, String value) {
483 addAttributeBare(
484 name.getURI(),
485 name.getPrefix(),
486 name.getQualifiedName(),
487 value);
488 }
489 private void addAttributeBare(QName name, String value) {
490 addAttributeBare(
491 name.getNamespaceURI(),
492 name.getPrefix(),
493 getQualifiedName(name),
494 value);
495 }
497 private void addAttributeBare(
498 String uri,
499 String prefix,
500 String qualifiedName,
501 String value) {
503 uri = uri.length() == 0 ? null : uri;
504 if (qualifiedName.equals("xmlns")) {
505 uri = XMLNS_URI;
506 }
508 if (uri == null) {
509 setAttribute(qualifiedName, value);
510 } else {
511 setAttributeNS(uri, qualifiedName, value);
512 }
513 }
515 public SOAPElement addNamespaceDeclaration(String prefix, String uri)
516 throws SOAPException {
517 if (prefix.length() > 0) {
518 setAttributeNS(XMLNS_URI, "xmlns:" + prefix, uri);
519 } else {
520 setAttributeNS(XMLNS_URI, "xmlns", uri);
521 }
522 //Fix for CR:6474641
523 //tryToFindEncodingStyleAttributeName();
524 return this;
525 }
527 public String getAttributeValue(Name name) {
528 return getAttributeValueFrom(this, name);
529 }
531 public String getAttributeValue(QName qname) {
532 return getAttributeValueFrom(
533 this,
534 qname.getNamespaceURI(),
535 qname.getLocalPart(),
536 qname.getPrefix(),
537 getQualifiedName(qname));
538 }
540 public Iterator getAllAttributes() {
541 Iterator i = getAllAttributesFrom(this);
542 ArrayList list = new ArrayList();
543 while (i.hasNext()) {
544 Name name = (Name) i.next();
545 if (!"xmlns".equalsIgnoreCase(name.getPrefix()))
546 list.add(name);
547 }
548 return list.iterator();
549 }
551 public Iterator getAllAttributesAsQNames() {
552 Iterator i = getAllAttributesFrom(this);
553 ArrayList list = new ArrayList();
554 while (i.hasNext()) {
555 Name name = (Name) i.next();
556 if (!"xmlns".equalsIgnoreCase(name.getPrefix())) {
557 list.add(NameImpl.convertToQName(name));
558 }
559 }
560 return list.iterator();
561 }
564 public Iterator getNamespacePrefixes() {
565 return doGetNamespacePrefixes(false);
566 }
568 public Iterator getVisibleNamespacePrefixes() {
569 return doGetNamespacePrefixes(true);
570 }
572 protected Iterator doGetNamespacePrefixes(final boolean deep) {
573 return new Iterator() {
574 String next = null;
575 String last = null;
576 NamespaceContextIterator eachNamespace =
577 getNamespaceContextNodes(deep);
579 void findNext() {
580 while (next == null && eachNamespace.hasNext()) {
581 String attributeKey =
582 eachNamespace.nextNamespaceAttr().getNodeName();
583 if (attributeKey.startsWith("xmlns:")) {
584 next = attributeKey.substring("xmlns:".length());
585 }
586 }
587 }
589 public boolean hasNext() {
590 findNext();
591 return next != null;
592 }
594 public Object next() {
595 findNext();
596 if (next == null) {
597 throw new NoSuchElementException();
598 }
600 last = next;
601 next = null;
602 return last;
603 }
605 public void remove() {
606 if (last == null) {
607 throw new IllegalStateException();
608 }
609 eachNamespace.remove();
610 next = null;
611 last = null;
612 }
613 };
614 }
616 public Name getElementName() {
617 return NameImpl.convertToName(elementQName);
618 }
620 public QName getElementQName() {
621 return elementQName;
622 }
624 public boolean removeAttribute(Name name) {
625 return removeAttribute(name.getURI(), name.getLocalName());
626 }
628 public boolean removeAttribute(QName name) {
629 return removeAttribute(name.getNamespaceURI(), name.getLocalPart());
630 }
632 private boolean removeAttribute(String uri, String localName) {
633 String nonzeroLengthUri =
634 (uri == null || uri.length() == 0) ? null : uri;
635 org.w3c.dom.Attr attribute =
636 getAttributeNodeNS(nonzeroLengthUri, localName);
637 if (attribute == null) {
638 return false;
639 }
640 removeAttributeNode(attribute);
641 return true;
642 }
644 public boolean removeNamespaceDeclaration(String prefix) {
645 org.w3c.dom.Attr declaration = getNamespaceAttr(prefix);
646 if (declaration == null) {
647 return false;
648 }
649 try {
650 removeAttributeNode(declaration);
651 } catch (DOMException de) {
652 // ignore
653 }
654 return true;
655 }
657 public Iterator getChildElements() {
658 return getChildElementsFrom(this);
659 }
661 protected SOAPElement convertToSoapElement(Element element) {
662 if (element instanceof SOAPElement) {
663 return (SOAPElement) element;
664 } else {
665 return replaceElementWithSOAPElement(
666 element,
667 (ElementImpl) createElement(NameImpl.copyElementName(element)));
668 }
669 }
671 protected static SOAPElement replaceElementWithSOAPElement(
672 Element element,
673 ElementImpl copy) {
675 Iterator eachAttribute = getAllAttributesFrom(element);
676 while (eachAttribute.hasNext()) {
677 Name name = (Name) eachAttribute.next();
678 copy.addAttributeBare(name, getAttributeValueFrom(element, name));
679 }
681 Iterator eachChild = getChildElementsFrom(element);
682 while (eachChild.hasNext()) {
683 Node nextChild = (Node) eachChild.next();
684 copy.insertBefore(nextChild, null);
685 }
687 Node parent = element.getParentNode();
688 if (parent != null) {
689 parent.replaceChild(copy, element);
690 } // XXX else throw an exception?
692 return copy;
693 }
695 protected Iterator getChildElementNodes() {
696 return new Iterator() {
697 Iterator eachNode = getChildElements();
698 Node next = null;
699 Node last = null;
701 public boolean hasNext() {
702 if (next == null) {
703 while (eachNode.hasNext()) {
704 Node node = (Node) eachNode.next();
705 if (node instanceof SOAPElement) {
706 next = node;
707 break;
708 }
709 }
710 }
711 return next != null;
712 }
714 public Object next() {
715 if (hasNext()) {
716 last = next;
717 next = null;
718 return last;
719 }
720 throw new NoSuchElementException();
721 }
723 public void remove() {
724 if (last == null) {
725 throw new IllegalStateException();
726 }
727 Node target = last;
728 last = null;
729 removeChild(target);
730 }
731 };
732 }
734 public Iterator getChildElements(final Name name) {
735 return getChildElements(name.getURI(), name.getLocalName());
736 }
738 public Iterator getChildElements(final QName qname) {
739 return getChildElements(qname.getNamespaceURI(), qname.getLocalPart());
740 }
742 private Iterator getChildElements(final String nameUri, final String nameLocal) {
743 return new Iterator() {
744 Iterator eachElement = getChildElementNodes();
745 Node next = null;
746 Node last = null;
748 public boolean hasNext() {
749 if (next == null) {
750 while (eachElement.hasNext()) {
751 Node element = (Node) eachElement.next();
752 String elementUri = element.getNamespaceURI();
753 elementUri = elementUri == null ? "" : elementUri;
754 String elementName = element.getLocalName();
755 if (elementUri.equals(nameUri)
756 && elementName.equals(nameLocal)) {
757 next = element;
758 break;
759 }
760 }
761 }
762 return next != null;
763 }
765 public Object next() {
766 if (!hasNext()) {
767 throw new NoSuchElementException();
768 }
769 last = next;
770 next = null;
771 return last;
772 }
774 public void remove() {
775 if (last == null) {
776 throw new IllegalStateException();
777 }
778 Node target = last;
779 last = null;
780 removeChild(target);
781 }
782 };
783 }
785 public void removeContents() {
786 Node currentChild = getFirstChild();
788 while (currentChild != null) {
789 Node temp = currentChild.getNextSibling();
790 if (currentChild instanceof javax.xml.soap.Node) {
791 ((javax.xml.soap.Node) currentChild).detachNode();
792 } else {
793 Node parent = currentChild.getParentNode();
794 if (parent != null) {
795 parent.removeChild(currentChild);
796 }
798 }
799 currentChild = temp;
800 }
801 }
803 public void setEncodingStyle(String encodingStyle) throws SOAPException {
804 if (!"".equals(encodingStyle)) {
805 try {
806 new URI(encodingStyle);
807 } catch (URISyntaxException m) {
808 log.log(
809 Level.SEVERE,
810 "SAAJ0105.impl.encoding.style.mustbe.valid.URI",
811 new String[] { encodingStyle });
812 throw new IllegalArgumentException(
813 "Encoding style (" + encodingStyle + ") should be a valid URI");
814 }
815 }
816 encodingStyleAttribute.setValue(encodingStyle);
817 tryToFindEncodingStyleAttributeName();
818 }
820 public String getEncodingStyle() {
821 String encodingStyle = encodingStyleAttribute.getValue();
822 if (encodingStyle != null)
823 return encodingStyle;
824 String soapNamespace = getSOAPNamespace();
825 if (soapNamespace != null) {
826 Attr attr = getAttributeNodeNS(soapNamespace, "encodingStyle");
827 if (attr != null) {
828 encodingStyle = attr.getValue();
829 try {
830 setEncodingStyle(encodingStyle);
831 } catch (SOAPException se) {
832 // has to be ignored
833 }
834 return encodingStyle;
835 }
836 }
837 return null;
838 }
840 // Node methods
841 public String getValue() {
842 javax.xml.soap.Node valueNode = getValueNode();
843 return valueNode == null ? null : valueNode.getValue();
844 }
846 public void setValue(String value) {
847 Node valueNode = getValueNodeStrict();
848 if (valueNode != null) {
849 valueNode.setNodeValue(value);
850 } else {
851 try {
852 addTextNode(value);
853 } catch (SOAPException e) {
854 throw new RuntimeException(e.getMessage());
855 }
856 }
857 }
859 protected Node getValueNodeStrict() {
860 Node node = getFirstChild();
861 if (node != null) {
862 if (node.getNextSibling() == null
863 && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
864 return node;
865 } else {
866 log.severe("SAAJ0107.impl.elem.child.not.single.text");
867 throw new IllegalStateException();
868 }
869 }
871 return null;
872 }
874 protected javax.xml.soap.Node getValueNode() {
875 Iterator i = getChildElements();
876 while (i.hasNext()) {
877 javax.xml.soap.Node n = (javax.xml.soap.Node) i.next();
878 if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE ||
879 n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
880 // TODO: Hack to fix text node split into multiple lines.
881 normalize();
882 // Should remove the normalization step when this gets fixed in
883 // DOM/Xerces.
884 return (javax.xml.soap.Node) n;
885 }
886 }
887 return null;
888 }
890 public void setParentElement(SOAPElement element) throws SOAPException {
891 if (element == null) {
892 log.severe("SAAJ0106.impl.no.null.to.parent.elem");
893 throw new SOAPException("Cannot pass NULL to setParentElement");
894 }
895 element.addChildElement(this);
896 findEncodingStyleAttributeName();
897 }
899 protected void findEncodingStyleAttributeName() throws SOAPException {
900 String soapNamespace = getSOAPNamespace();
901 if (soapNamespace != null) {
902 String soapNamespacePrefix = getNamespacePrefix(soapNamespace);
903 if (soapNamespacePrefix != null) {
904 setEncodingStyleNamespace(soapNamespace, soapNamespacePrefix);
905 }
906 }
907 }
909 protected void setEncodingStyleNamespace(
910 String soapNamespace,
911 String soapNamespacePrefix)
912 throws SOAPException {
913 Name encodingStyleAttributeName =
914 NameImpl.create(
915 "encodingStyle",
916 soapNamespacePrefix,
917 soapNamespace);
918 encodingStyleAttribute.setName(encodingStyleAttributeName);
919 }
921 public SOAPElement getParentElement() {
922 Node parentNode = getParentNode();
923 if (parentNode instanceof SOAPDocument) {
924 return null;
925 }
926 return (SOAPElement) parentNode;
927 }
929 protected String getSOAPNamespace() {
930 String soapNamespace = null;
932 SOAPElement antecedent = this;
933 while (antecedent != null) {
934 Name antecedentName = antecedent.getElementName();
935 String antecedentNamespace = antecedentName.getURI();
937 if (NameImpl.SOAP11_NAMESPACE.equals(antecedentNamespace)
938 || NameImpl.SOAP12_NAMESPACE.equals(antecedentNamespace)) {
940 soapNamespace = antecedentNamespace;
941 break;
942 }
944 antecedent = antecedent.getParentElement();
945 }
947 return soapNamespace;
948 }
950 public void detachNode() {
951 Node parent = getParentNode();
952 if (parent != null) {
953 parent.removeChild(this);
954 }
955 encodingStyleAttribute.clearNameAndValue();
956 // Fix for CR: 6474641
957 //tryToFindEncodingStyleAttributeName();
958 }
960 public void tryToFindEncodingStyleAttributeName() {
961 try {
962 findEncodingStyleAttributeName();
963 } catch (SOAPException e) { /*okay to fail*/
964 }
965 }
967 public void recycleNode() {
968 detachNode();
969 // TBD
970 // - add this to the factory so subsequent
971 // creations can reuse this object.
972 }
974 class AttributeManager {
975 Name attributeName = null;
976 String attributeValue = null;
978 public void setName(Name newName) throws SOAPException {
979 clearAttribute();
980 attributeName = newName;
981 reconcileAttribute();
982 }
983 public void clearName() {
984 clearAttribute();
985 attributeName = null;
986 }
987 public void setValue(String value) throws SOAPException {
988 attributeValue = value;
989 reconcileAttribute();
990 }
991 public Name getName() {
992 return attributeName;
993 }
994 public String getValue() {
995 return attributeValue;
996 }
998 /** Note: to be used only in detachNode method */
999 public void clearNameAndValue() {
1000 attributeName = null;
1001 attributeValue = null;
1002 }
1004 private void reconcileAttribute() throws SOAPException {
1005 if (attributeName != null) {
1006 removeAttribute(attributeName);
1007 if (attributeValue != null) {
1008 addAttribute(attributeName, attributeValue);
1009 }
1010 }
1011 }
1012 private void clearAttribute() {
1013 if (attributeName != null) {
1014 removeAttribute(attributeName);
1015 }
1016 }
1017 }
1019 protected static org.w3c.dom.Attr getNamespaceAttrFrom(
1020 Element element,
1021 String prefix) {
1022 NamespaceContextIterator eachNamespace =
1023 new NamespaceContextIterator(element);
1024 while (eachNamespace.hasNext()) {
1025 org.w3c.dom.Attr namespaceDecl = eachNamespace.nextNamespaceAttr();
1026 String declaredPrefix =
1027 NameImpl.getLocalNameFromTagName(namespaceDecl.getNodeName());
1028 if (declaredPrefix.equals(prefix)) {
1029 return namespaceDecl;
1030 }
1031 }
1032 return null;
1033 }
1035 protected static Iterator getAllAttributesFrom(final Element element) {
1036 final NamedNodeMap attributes = element.getAttributes();
1038 return new Iterator() {
1039 int attributesLength = attributes.getLength();
1040 int attributeIndex = 0;
1041 String currentName;
1043 public boolean hasNext() {
1044 return attributeIndex < attributesLength;
1045 }
1047 public Object next() {
1048 if (!hasNext()) {
1049 throw new NoSuchElementException();
1050 }
1051 Node current = attributes.item(attributeIndex++);
1052 currentName = current.getNodeName();
1054 String prefix = NameImpl.getPrefixFromTagName(currentName);
1055 if (prefix.length() == 0) {
1056 return NameImpl.createFromUnqualifiedName(currentName);
1057 } else {
1058 Name attributeName =
1059 NameImpl.createFromQualifiedName(
1060 currentName,
1061 current.getNamespaceURI());
1062 return attributeName;
1063 }
1064 }
1066 public void remove() {
1067 if (currentName == null) {
1068 throw new IllegalStateException();
1069 }
1070 attributes.removeNamedItem(currentName);
1071 }
1072 };
1073 }
1075 protected static String getAttributeValueFrom(Element element, Name name) {
1076 return getAttributeValueFrom(
1077 element,
1078 name.getURI(),
1079 name.getLocalName(),
1080 name.getPrefix(),
1081 name.getQualifiedName());
1082 }
1084 private static String getAttributeValueFrom(
1085 Element element,
1086 String uri,
1087 String localName,
1088 String prefix,
1089 String qualifiedName) {
1091 String nonzeroLengthUri =
1092 (uri == null || uri.length() == 0) ? null : uri;
1094 boolean mustUseGetAttributeNodeNS = (nonzeroLengthUri != null);
1096 if (mustUseGetAttributeNodeNS) {
1098 if (!element.hasAttributeNS(uri, localName)) {
1099 return null;
1100 }
1102 String attrValue =
1103 element.getAttributeNS(nonzeroLengthUri, localName);
1105 return attrValue;
1106 }
1108 Attr attribute = null;
1109 attribute = element.getAttributeNode(qualifiedName);
1111 return attribute == null ? null : attribute.getValue();
1112 }
1114 protected static Iterator getChildElementsFrom(final Element element) {
1115 return new Iterator() {
1116 Node next = element.getFirstChild();
1117 Node nextNext = null;
1118 Node last = null;
1120 public boolean hasNext() {
1121 if (next != null) {
1122 return true;
1123 }
1124 if (next == null && nextNext != null) {
1125 next = nextNext;
1126 }
1128 return next != null;
1129 }
1131 public Object next() {
1132 if (hasNext()) {
1133 last = next;
1134 next = null;
1136 if ((element instanceof ElementImpl)
1137 && (last instanceof Element)) {
1138 last =
1139 ((ElementImpl) element).convertToSoapElement(
1140 (Element) last);
1141 }
1143 nextNext = last.getNextSibling();
1144 return last;
1145 }
1146 throw new NoSuchElementException();
1147 }
1149 public void remove() {
1150 if (last == null) {
1151 throw new IllegalStateException();
1152 }
1153 Node target = last;
1154 last = null;
1155 element.removeChild(target);
1156 }
1157 };
1158 }
1160 public static String getQualifiedName(QName name) {
1161 String prefix = name.getPrefix();
1162 String localName = name.getLocalPart();
1163 String qualifiedName = null;
1165 if (prefix != null && prefix.length() > 0) {
1166 qualifiedName = prefix + ":" + localName;
1167 } else {
1168 qualifiedName = localName;
1169 }
1170 return qualifiedName;
1171 }
1173 public static String getLocalPart(String qualifiedName) {
1174 if (qualifiedName == null) {
1175 // Log
1176 throw new IllegalArgumentException("Cannot get local name for a \"null\" qualified name");
1177 }
1179 int index = qualifiedName.indexOf(':');
1180 if (index < 0)
1181 return qualifiedName;
1182 else
1183 return qualifiedName.substring(index + 1);
1184 }
1186 public static String getPrefix(String qualifiedName) {
1187 if (qualifiedName == null) {
1188 // Log
1189 throw new IllegalArgumentException("Cannot get prefix for a \"null\" qualified name");
1190 }
1192 int index = qualifiedName.indexOf(':');
1193 if (index < 0)
1194 return "";
1195 else
1196 return qualifiedName.substring(0, index);
1197 }
1199 protected boolean isNamespaceQualified(Name name) {
1200 return !"".equals(name.getURI());
1201 }
1203 protected boolean isNamespaceQualified(QName name) {
1204 return !"".equals(name.getNamespaceURI());
1205 }
1207 //TODO: This is a temporary SAAJ workaround for optimizing XWS
1208 // should be removed once the corresponding JAXP bug is fixed
1209 // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
1210 public void setAttributeNS(
1211 String namespaceURI,String qualifiedName, String value) {
1212 int index = qualifiedName.indexOf(':');
1213 String localName;
1214 if (index < 0)
1215 localName = qualifiedName;
1216 else
1217 localName = qualifiedName.substring(index + 1);
1219 // Workaround for bug 6467808 - This needs to be fixed in JAXP
1221 // Rolling back this fix, this is a wrong fix, infact its causing other regressions in JAXWS tck and
1222 // other tests, because of this change the namespace declarations on soapenv:Fault element are never
1223 // picked up. The fix for bug 6467808 should be in JAXP.
1224 // if(elementQName.getLocalPart().equals("Fault") &&
1225 // (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(value) ||
1226 // SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(value)))
1227 // return;
1229 super.setAttributeNS(namespaceURI,qualifiedName,value);
1230 //String tmpLocalName = this.getLocalName();
1231 String tmpURI = this.getNamespaceURI();
1232 boolean isIDNS = false;
1233 if( tmpURI != null && (tmpURI.equals(DSIG_NS) || tmpURI.equals(XENC_NS))){
1234 isIDNS = true;
1235 }
1236 //No need to check for Signature/encryption element
1237 //just check for namespace.
1238 if(localName.equals("Id")){
1239 if(namespaceURI == null || namespaceURI.equals("")){
1240 setIdAttribute(localName,true);
1241 }else if(isIDNS || WSU_NS.equals(namespaceURI)){
1242 setIdAttributeNS(namespaceURI,localName,true);
1243 }
1244 }
1246 }
1248 }