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