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