0001: /*
0002: * The contents of this file are subject to the terms
0003: * of the Common Development and Distribution License
0004: * (the "License"). You may not use this file except
0005: * in compliance with the License.
0006: *
0007: * You can obtain a copy of the license at
0008: * https://jwsdp.dev.java.net/CDDLv1.0.html
0009: * See the License for the specific language governing
0010: * permissions and limitations under the License.
0011: *
0012: * When distributing Covered Code, include this CDDL
0013: * HEADER in each file and include the License file at
0014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
0015: * add the following below this CDDL HEADER, with the
0016: * fields enclosed by brackets "[]" replaced with your
0017: * own identifying information: Portions Copyright [yyyy]
0018: * [name of copyright owner]
0019: */
0020: /*
0021: * $Id: ElementImpl.java,v 1.8 2007/07/16 16:41:23 ofung Exp $
0022: * $Revision: 1.8 $
0023: * $Date: 2007/07/16 16:41:23 $
0024: */
0025:
0026: /*
0027: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0028: *
0029: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0030: *
0031: * The contents of this file are subject to the terms of either the GNU
0032: * General Public License Version 2 only ("GPL") or the Common Development
0033: * and Distribution License("CDDL") (collectively, the "License"). You
0034: * may not use this file except in compliance with the License. You can obtain
0035: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0036: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
0037: * language governing permissions and limitations under the License.
0038: *
0039: * When distributing the software, include this License Header Notice in each
0040: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0041: * Sun designates this particular file as subject to the "Classpath" exception
0042: * as provided by Sun in the GPL Version 2 section of the License file that
0043: * accompanied this code. If applicable, add the following below the License
0044: * Header, with the fields enclosed by brackets [] replaced by your own
0045: * identifying information: "Portions Copyrighted [year]
0046: * [name of copyright owner]"
0047: *
0048: * Contributor(s):
0049: *
0050: * If you wish your version of this file to be governed by only the CDDL or
0051: * only the GPL Version 2, indicate your decision by adding "[Contributor]
0052: * elects to include this software in this distribution under the [CDDL or GPL
0053: * Version 2] license." If you don't indicate a single choice of license, a
0054: * recipient has the option to distribute your version of this file under
0055: * either the CDDL, the GPL Version 2 or to extend the choice of license to
0056: * its licensees as provided above. However, if you add GPL Version 2 code
0057: * and therefore, elected the GPL Version 2 license, then the option applies
0058: * only if the new code is made subject to such option by the copyright
0059: * holder.
0060: */
0061: package com.sun.xml.messaging.saaj.soap.impl;
0062:
0063: import java.util.*;
0064: import java.util.logging.Level;
0065: import java.util.logging.Logger;
0066:
0067: import javax.xml.namespace.QName;
0068: import javax.xml.soap.*;
0069:
0070: import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
0071: import org.w3c.dom.*;
0072: import org.w3c.dom.Node;
0073:
0074: import com.sun.xml.messaging.saaj.SOAPExceptionImpl;
0075: import com.sun.xml.messaging.saaj.soap.SOAPDocument;
0076: import com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl;
0077: import com.sun.xml.messaging.saaj.soap.name.NameImpl;
0078: import com.sun.xml.messaging.saaj.util.*;
0079:
0080: public class ElementImpl extends
0081: com.sun.org.apache.xerces.internal.dom.ElementNSImpl implements
0082: SOAPElement, SOAPBodyElement {
0083:
0084: public static final String DSIG_NS = "http://www.w3.org/2000/09/xmldsig#"
0085: .intern();
0086: public static final String XENC_NS = "http://www.w3.org/2001/04/xmlenc#"
0087: .intern();
0088: public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
0089: .intern();
0090:
0091: private AttributeManager encodingStyleAttribute = new AttributeManager();
0092:
0093: protected QName elementQName;
0094:
0095: protected static Logger log = Logger.getLogger(
0096: LogDomainConstants.SOAP_IMPL_DOMAIN,
0097: "com.sun.xml.messaging.saaj.soap.impl.LocalStrings");
0098:
0099: public ElementImpl(SOAPDocumentImpl ownerDoc, Name name) {
0100: super (ownerDoc, name.getURI(), name.getQualifiedName(), name
0101: .getLocalName());
0102: elementQName = NameImpl.convertToQName(name);
0103: }
0104:
0105: public ElementImpl(SOAPDocumentImpl ownerDoc, QName name) {
0106: super (ownerDoc, name.getNamespaceURI(), getQualifiedName(name),
0107: name.getLocalPart());
0108: elementQName = name;
0109: }
0110:
0111: public ElementImpl(SOAPDocumentImpl ownerDoc, String uri,
0112: String qualifiedName) {
0113:
0114: super (ownerDoc, uri, qualifiedName);
0115: elementQName = new QName(uri, getLocalPart(qualifiedName),
0116: getPrefix(qualifiedName));
0117: }
0118:
0119: public void ensureNamespaceIsDeclared(String prefix, String uri) {
0120: String alreadyDeclaredUri = getNamespaceURI(prefix);
0121: if (alreadyDeclaredUri == null
0122: || !alreadyDeclaredUri.equals(uri)) {
0123: try {
0124: addNamespaceDeclaration(prefix, uri);
0125: } catch (SOAPException e) { /*ignore*/
0126: }
0127: }
0128: }
0129:
0130: public Document getOwnerDocument() {
0131: SOAPDocument ownerSOAPDocument = ((SOAPDocument) super
0132: .getOwnerDocument());
0133: if (ownerSOAPDocument == null) {
0134: return null;
0135: }
0136: return ownerSOAPDocument.getDocument();
0137: }
0138:
0139: public SOAPElement addChildElement(Name name) throws SOAPException {
0140: return addElement(name);
0141: }
0142:
0143: public SOAPElement addChildElement(QName qname)
0144: throws SOAPException {
0145: return addElement(qname);
0146: }
0147:
0148: public SOAPElement addChildElement(String localName)
0149: throws SOAPException {
0150: return (SOAPElement) addChildElement(NameImpl
0151: .createFromUnqualifiedName(localName));
0152: }
0153:
0154: public SOAPElement addChildElement(String localName, String prefix)
0155: throws SOAPException {
0156: String uri = getNamespaceURI(prefix);
0157: if (uri == null) {
0158: log.log(Level.SEVERE,
0159: "SAAJ0101.impl.parent.of.body.elem.mustbe.body",
0160: new String[] { prefix });
0161: throw new SOAPExceptionImpl(
0162: "Unable to locate namespace for prefix " + prefix);
0163: }
0164: return addChildElement(localName, prefix, uri);
0165: }
0166:
0167: public String getNamespaceURI(String prefix) {
0168:
0169: if ("xmlns".equals(prefix)) {
0170: return NamespaceContext.XMLNS_URI;
0171: }
0172:
0173: if ("xml".equals(prefix)) {
0174: return NamespaceContext.XML_URI;
0175: }
0176:
0177: if ("".equals(prefix)) {
0178:
0179: org.w3c.dom.Node currentAncestor = this ;
0180: while (currentAncestor != null
0181: && !(currentAncestor instanceof Document)) {
0182:
0183: if (currentAncestor instanceof ElementImpl) {
0184: QName name = ((ElementImpl) currentAncestor)
0185: .getElementQName();
0186: /*
0187: if (prefix.equals(name.getPrefix())) {
0188: String uri = name.getNamespaceURI();
0189: if ("".equals(uri)) {
0190: return null;
0191: }
0192: else {
0193: return uri;
0194: }
0195: }*/
0196: if (((Element) currentAncestor).hasAttributeNS(
0197: NamespaceContext.XMLNS_URI, "xmlns")) {
0198:
0199: String uri = ((Element) currentAncestor)
0200: .getAttributeNS(
0201: NamespaceContext.XMLNS_URI,
0202: "xmlns");
0203: if ("".equals(uri))
0204: return null;
0205: else {
0206: return uri;
0207: }
0208: }
0209: }
0210: currentAncestor = currentAncestor.getParentNode();
0211: }
0212:
0213: } else if (prefix != null) {
0214: // Find if there's an ancester whose name contains this prefix
0215: org.w3c.dom.Node currentAncestor = this ;
0216:
0217: // String uri = currentAncestor.lookupNamespaceURI(prefix);
0218: // return uri;
0219: while (currentAncestor != null
0220: && !(currentAncestor instanceof Document)) {
0221:
0222: /* if (prefix.equals(currentAncestor.getPrefix())) {
0223: String uri = currentAncestor.getNamespaceURI();
0224: // this is because the javadoc says getNamespaceURI() is not a computed value
0225: // and URI for a non-empty prefix cannot be null
0226: if (uri != null)
0227: return uri;
0228: }*/
0229: //String uri = currentAncestor.lookupNamespaceURI(prefix);
0230: //if (uri != null) {
0231: // return uri;
0232: //}
0233: if (((Element) currentAncestor).hasAttributeNS(
0234: NamespaceContext.XMLNS_URI, prefix)) {
0235: return ((Element) currentAncestor).getAttributeNS(
0236: NamespaceContext.XMLNS_URI, prefix);
0237: }
0238:
0239: currentAncestor = currentAncestor.getParentNode();
0240: }
0241: }
0242:
0243: return null;
0244: }
0245:
0246: public SOAPElement setElementQName(QName newName)
0247: throws SOAPException {
0248: ElementImpl copy = new ElementImpl(
0249: (SOAPDocumentImpl) getOwnerDocument(), newName);
0250: return replaceElementWithSOAPElement(this , copy);
0251: }
0252:
0253: public QName createQName(String localName, String prefix)
0254: throws SOAPException {
0255: String uri = getNamespaceURI(prefix);
0256: if (uri == null) {
0257: log.log(Level.SEVERE, "SAAJ0102.impl.cannot.locate.ns",
0258: new Object[] { prefix });
0259: throw new SOAPException(
0260: "Unable to locate namespace for prefix " + prefix);
0261: }
0262: return new QName(uri, localName, prefix);
0263: }
0264:
0265: public String getNamespacePrefix(String uri) {
0266:
0267: NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
0268: while (eachNamespace.hasNext()) {
0269: org.w3c.dom.Attr namespaceDecl = eachNamespace
0270: .nextNamespaceAttr();
0271: if (namespaceDecl.getNodeValue().equals(uri)) {
0272: String candidatePrefix = namespaceDecl.getLocalName();
0273: if ("xmlns".equals(candidatePrefix))
0274: return "";
0275: else
0276: return candidatePrefix;
0277: }
0278: }
0279:
0280: // Find if any of the ancestors' name has this uri
0281: org.w3c.dom.Node currentAncestor = this ;
0282: while (currentAncestor != null
0283: && !(currentAncestor instanceof Document)) {
0284:
0285: if (uri.equals(currentAncestor.getNamespaceURI()))
0286: return currentAncestor.getPrefix();
0287: currentAncestor = currentAncestor.getParentNode();
0288: }
0289:
0290: return null;
0291: }
0292:
0293: protected org.w3c.dom.Attr getNamespaceAttr(String prefix) {
0294: NamespaceContextIterator eachNamespace = getNamespaceContextNodes();
0295: if (!"".equals(prefix))
0296: prefix = ":" + prefix;
0297: while (eachNamespace.hasNext()) {
0298: org.w3c.dom.Attr namespaceDecl = eachNamespace
0299: .nextNamespaceAttr();
0300: if (!"".equals(prefix)) {
0301: if (namespaceDecl.getNodeName().endsWith(prefix))
0302: return namespaceDecl;
0303: } else {
0304: if (namespaceDecl.getNodeName().equals("xmlns"))
0305: return namespaceDecl;
0306: }
0307: }
0308: return null;
0309: }
0310:
0311: public NamespaceContextIterator getNamespaceContextNodes() {
0312: return getNamespaceContextNodes(true);
0313: }
0314:
0315: public NamespaceContextIterator getNamespaceContextNodes(
0316: boolean traverseStack) {
0317: return new NamespaceContextIterator(this , traverseStack);
0318: }
0319:
0320: public SOAPElement addChildElement(String localName, String prefix,
0321: String uri) throws SOAPException {
0322:
0323: SOAPElement newElement = createElement(NameImpl.create(
0324: localName, prefix, uri));
0325: addNode(newElement);
0326: return convertToSoapElement(newElement);
0327: }
0328:
0329: public SOAPElement addChildElement(SOAPElement element)
0330: throws SOAPException {
0331:
0332: // check if Element falls in SOAP 1.1 or 1.2 namespace.
0333: String elementURI = element.getElementName().getURI();
0334: String localName = element.getLocalName();
0335:
0336: if ((SOAPConstants.URI_NS_SOAP_ENVELOPE).equals(elementURI)
0337: || (SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE)
0338: .equals(elementURI)) {
0339:
0340: if ("Envelope".equalsIgnoreCase(localName)
0341: || "Header".equalsIgnoreCase(localName)
0342: || "Body".equalsIgnoreCase(localName)) {
0343: log.severe("SAAJ0103.impl.cannot.add.fragements");
0344: throw new SOAPExceptionImpl(
0345: "Cannot add fragments which contain elements "
0346: + "which are in the SOAP namespace");
0347: }
0348:
0349: if ("Fault".equalsIgnoreCase(localName)
0350: && !"Body".equalsIgnoreCase(this .getLocalName())) {
0351: log.severe("SAAJ0154.impl.adding.fault.to.nonbody");
0352: throw new SOAPExceptionImpl(
0353: "Cannot add a SOAPFault as a child of "
0354: + this .getLocalName());
0355: }
0356:
0357: if ("Detail".equalsIgnoreCase(localName)
0358: && !"Fault".equalsIgnoreCase(this .getLocalName())) {
0359: log.severe("SAAJ0155.impl.adding.detail.nonfault");
0360: throw new SOAPExceptionImpl(
0361: "Cannot add a Detail as a child of "
0362: + this .getLocalName());
0363: }
0364:
0365: if ("Fault".equalsIgnoreCase(localName)) {
0366: // if body is not empty throw an exception
0367: if (!elementURI.equals(this .getElementName().getURI())) {
0368: log.severe("SAAJ0158.impl.version.mismatch.fault");
0369: throw new SOAPExceptionImpl(
0370: "SOAP Version mismatch encountered when trying to add SOAPFault to SOAPBody");
0371: }
0372: Iterator it = this .getChildElements();
0373: if (it.hasNext()) {
0374: log.severe("SAAJ0156.impl.adding.fault.error");
0375: throw new SOAPExceptionImpl(
0376: "Cannot add SOAPFault as a child of a non-Empty SOAPBody");
0377: }
0378: }
0379: }
0380:
0381: // preserve the encodingStyle attr as it may get lost in the import
0382: String encodingStyle = element.getEncodingStyle();
0383:
0384: ElementImpl importedElement = (ElementImpl) importElement(element);
0385: addNode(importedElement);
0386:
0387: if (encodingStyle != null)
0388: importedElement.setEncodingStyle(encodingStyle);
0389:
0390: return convertToSoapElement(importedElement);
0391: }
0392:
0393: protected Element importElement(Element element) {
0394: Document document = getOwnerDocument();
0395: Document oldDocument = element.getOwnerDocument();
0396: if (!oldDocument.equals(document)) {
0397: return (Element) document.importNode(element, true);
0398: } else {
0399: return element;
0400: }
0401: }
0402:
0403: protected SOAPElement addElement(Name name) throws SOAPException {
0404: SOAPElement newElement = createElement(name);
0405: addNode(newElement);
0406: return circumventBug5034339(newElement);
0407: }
0408:
0409: protected SOAPElement addElement(QName name) throws SOAPException {
0410: SOAPElement newElement = createElement(name);
0411: addNode(newElement);
0412: return circumventBug5034339(newElement);
0413: }
0414:
0415: protected SOAPElement createElement(Name name) {
0416:
0417: if (isNamespaceQualified(name)) {
0418: return (SOAPElement) getOwnerDocument().createElementNS(
0419: name.getURI(), name.getQualifiedName());
0420: } else {
0421: return (SOAPElement) getOwnerDocument().createElement(
0422: name.getQualifiedName());
0423: }
0424: }
0425:
0426: protected SOAPElement createElement(QName name) {
0427:
0428: if (isNamespaceQualified(name)) {
0429: return (SOAPElement) getOwnerDocument().createElementNS(
0430: name.getNamespaceURI(), getQualifiedName(name));
0431: } else {
0432: return (SOAPElement) getOwnerDocument().createElement(
0433: getQualifiedName(name));
0434: }
0435: }
0436:
0437: protected void addNode(org.w3c.dom.Node newElement)
0438: throws SOAPException {
0439: insertBefore(newElement, null);
0440:
0441: if (getOwnerDocument() instanceof DocumentFragment)
0442: return;
0443:
0444: if (newElement instanceof ElementImpl) {
0445: ElementImpl element = (ElementImpl) newElement;
0446: QName elementName = element.getElementQName();
0447: if (!"".equals(elementName.getNamespaceURI())) {
0448: element.ensureNamespaceIsDeclared(elementName
0449: .getPrefix(), elementName.getNamespaceURI());
0450: }
0451: }
0452:
0453: }
0454:
0455: protected SOAPElement findChild(NameImpl name) {
0456: Iterator eachChild = getChildElementNodes();
0457: while (eachChild.hasNext()) {
0458: SOAPElement child = (SOAPElement) eachChild.next();
0459: if (child.getElementName().equals(name)) {
0460: return child;
0461: }
0462: }
0463:
0464: return null;
0465: }
0466:
0467: public SOAPElement addTextNode(String text) throws SOAPException {
0468: if (text.startsWith(CDATAImpl.cdataUC)
0469: || text.startsWith(CDATAImpl.cdataLC))
0470: return addCDATA(text.substring(CDATAImpl.cdataUC.length(),
0471: text.length() - 3));
0472: return addText(text);
0473: }
0474:
0475: protected SOAPElement addCDATA(String text) throws SOAPException {
0476: org.w3c.dom.Text cdata = (org.w3c.dom.Text) getOwnerDocument()
0477: .createCDATASection(text);
0478: addNode(cdata);
0479: return this ;
0480: }
0481:
0482: protected SOAPElement addText(String text) throws SOAPException {
0483: org.w3c.dom.Text textNode = (org.w3c.dom.Text) getOwnerDocument()
0484: .createTextNode(text);
0485: addNode(textNode);
0486: return this ;
0487: }
0488:
0489: public SOAPElement addAttribute(Name name, String value)
0490: throws SOAPException {
0491: addAttributeBare(name, value);
0492: if (!"".equals(name.getURI())) {
0493: ensureNamespaceIsDeclared(name.getPrefix(), name.getURI());
0494: }
0495: return this ;
0496: }
0497:
0498: public SOAPElement addAttribute(QName qname, String value)
0499: throws SOAPException {
0500: addAttributeBare(qname, value);
0501: if (!"".equals(qname.getNamespaceURI())) {
0502: ensureNamespaceIsDeclared(qname.getPrefix(), qname
0503: .getNamespaceURI());
0504: }
0505: return this ;
0506: }
0507:
0508: private void addAttributeBare(Name name, String value) {
0509: addAttributeBare(name.getURI(), name.getPrefix(), name
0510: .getQualifiedName(), value);
0511: }
0512:
0513: private void addAttributeBare(QName name, String value) {
0514: addAttributeBare(name.getNamespaceURI(), name.getPrefix(),
0515: getQualifiedName(name), value);
0516: }
0517:
0518: private void addAttributeBare(String uri, String prefix,
0519: String qualifiedName, String value) {
0520:
0521: uri = uri.length() == 0 ? null : uri;
0522: if (qualifiedName.equals("xmlns")) {
0523: uri = NamespaceContext.XMLNS_URI;
0524: }
0525:
0526: if (uri == null) {
0527: setAttribute(qualifiedName, value);
0528: } else {
0529: setAttributeNS(uri, qualifiedName, value);
0530: }
0531: }
0532:
0533: public SOAPElement addNamespaceDeclaration(String prefix, String uri)
0534: throws SOAPException {
0535: if (prefix.length() > 0) {
0536: setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns:"
0537: + prefix, uri);
0538: } else {
0539: setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns", uri);
0540: }
0541: //Fix for CR:6474641
0542: //tryToFindEncodingStyleAttributeName();
0543: return this ;
0544: }
0545:
0546: public String getAttributeValue(Name name) {
0547: return getAttributeValueFrom(this , name);
0548: }
0549:
0550: public String getAttributeValue(QName qname) {
0551: return getAttributeValueFrom(this , qname.getNamespaceURI(),
0552: qname.getLocalPart(), qname.getPrefix(),
0553: getQualifiedName(qname));
0554: }
0555:
0556: public Iterator getAllAttributes() {
0557: Iterator i = getAllAttributesFrom(this );
0558: ArrayList list = new ArrayList();
0559: while (i.hasNext()) {
0560: Name name = (Name) i.next();
0561: if (!"xmlns".equalsIgnoreCase(name.getPrefix()))
0562: list.add(name);
0563: }
0564: return list.iterator();
0565: }
0566:
0567: public Iterator getAllAttributesAsQNames() {
0568: Iterator i = getAllAttributesFrom(this );
0569: ArrayList list = new ArrayList();
0570: while (i.hasNext()) {
0571: Name name = (Name) i.next();
0572: if (!"xmlns".equalsIgnoreCase(name.getPrefix())) {
0573: list.add(NameImpl.convertToQName(name));
0574: }
0575: }
0576: return list.iterator();
0577: }
0578:
0579: public Iterator getNamespacePrefixes() {
0580: return doGetNamespacePrefixes(false);
0581: }
0582:
0583: public Iterator getVisibleNamespacePrefixes() {
0584: return doGetNamespacePrefixes(true);
0585: }
0586:
0587: protected Iterator doGetNamespacePrefixes(final boolean deep) {
0588: return new Iterator() {
0589: String next = null;
0590: String last = null;
0591: NamespaceContextIterator eachNamespace = getNamespaceContextNodes(deep);
0592:
0593: void findNext() {
0594: while (next == null && eachNamespace.hasNext()) {
0595: String attributeKey = eachNamespace
0596: .nextNamespaceAttr().getNodeName();
0597: if (attributeKey.startsWith("xmlns:")) {
0598: next = attributeKey
0599: .substring("xmlns:".length());
0600: }
0601: }
0602: }
0603:
0604: public boolean hasNext() {
0605: findNext();
0606: return next != null;
0607: }
0608:
0609: public Object next() {
0610: findNext();
0611: if (next == null) {
0612: throw new NoSuchElementException();
0613: }
0614:
0615: last = next;
0616: next = null;
0617: return last;
0618: }
0619:
0620: public void remove() {
0621: if (last == null) {
0622: throw new IllegalStateException();
0623: }
0624: eachNamespace.remove();
0625: next = null;
0626: last = null;
0627: }
0628: };
0629: }
0630:
0631: public Name getElementName() {
0632: return NameImpl.convertToName(elementQName);
0633: }
0634:
0635: public QName getElementQName() {
0636: return elementQName;
0637: }
0638:
0639: public boolean removeAttribute(Name name) {
0640: return removeAttribute(name.getURI(), name.getLocalName());
0641: }
0642:
0643: public boolean removeAttribute(QName name) {
0644: return removeAttribute(name.getNamespaceURI(), name
0645: .getLocalPart());
0646: }
0647:
0648: private boolean removeAttribute(String uri, String localName) {
0649: String nonzeroLengthUri = (uri == null || uri.length() == 0) ? null
0650: : uri;
0651: org.w3c.dom.Attr attribute = getAttributeNodeNS(
0652: nonzeroLengthUri, localName);
0653: if (attribute == null) {
0654: return false;
0655: }
0656: removeAttributeNode(attribute);
0657: return true;
0658: }
0659:
0660: public boolean removeNamespaceDeclaration(String prefix) {
0661: org.w3c.dom.Attr declaration = getNamespaceAttr(prefix);
0662: if (declaration == null) {
0663: return false;
0664: }
0665: try {
0666: removeAttributeNode(declaration);
0667: } catch (DOMException de) {
0668: // ignore
0669: }
0670: return true;
0671: }
0672:
0673: public Iterator getChildElements() {
0674: return getChildElementsFrom(this );
0675: }
0676:
0677: protected SOAPElement convertToSoapElement(Element element) {
0678: if (element instanceof SOAPElement) {
0679: return (SOAPElement) element;
0680: } else {
0681: return replaceElementWithSOAPElement(element,
0682: (ElementImpl) createElement(NameImpl
0683: .copyElementName(element)));
0684: }
0685: }
0686:
0687: protected static SOAPElement replaceElementWithSOAPElement(
0688: Element element, ElementImpl copy) {
0689:
0690: Iterator eachAttribute = getAllAttributesFrom(element);
0691: while (eachAttribute.hasNext()) {
0692: Name name = (Name) eachAttribute.next();
0693: copy.addAttributeBare(name, getAttributeValueFrom(element,
0694: name));
0695: }
0696:
0697: Iterator eachChild = getChildElementsFrom(element);
0698: while (eachChild.hasNext()) {
0699: Node nextChild = (Node) eachChild.next();
0700: copy.insertBefore(nextChild, null);
0701: }
0702:
0703: Node parent = element.getParentNode();
0704: if (parent != null) {
0705: parent.replaceChild(copy, element);
0706: } // XXX else throw an exception?
0707:
0708: return copy;
0709: }
0710:
0711: protected Iterator getChildElementNodes() {
0712: return new Iterator() {
0713: Iterator eachNode = getChildElements();
0714: Node next = null;
0715: Node last = null;
0716:
0717: public boolean hasNext() {
0718: if (next == null) {
0719: while (eachNode.hasNext()) {
0720: Node node = (Node) eachNode.next();
0721: if (node instanceof SOAPElement) {
0722: next = node;
0723: break;
0724: }
0725: }
0726: }
0727: return next != null;
0728: }
0729:
0730: public Object next() {
0731: if (hasNext()) {
0732: last = next;
0733: next = null;
0734: return last;
0735: }
0736: throw new NoSuchElementException();
0737: }
0738:
0739: public void remove() {
0740: if (last == null) {
0741: throw new IllegalStateException();
0742: }
0743: Node target = last;
0744: last = null;
0745: removeChild(target);
0746: }
0747: };
0748: }
0749:
0750: public Iterator getChildElements(final Name name) {
0751: return getChildElements(name.getURI(), name.getLocalName());
0752: }
0753:
0754: public Iterator getChildElements(final QName qname) {
0755: return getChildElements(qname.getNamespaceURI(), qname
0756: .getLocalPart());
0757: }
0758:
0759: private Iterator getChildElements(final String nameUri,
0760: final String nameLocal) {
0761: return new Iterator() {
0762: Iterator eachElement = getChildElementNodes();
0763: Node next = null;
0764: Node last = null;
0765:
0766: public boolean hasNext() {
0767: if (next == null) {
0768: while (eachElement.hasNext()) {
0769: Node element = (Node) eachElement.next();
0770: String elementUri = element.getNamespaceURI();
0771: elementUri = elementUri == null ? ""
0772: : elementUri;
0773: String elementName = element.getLocalName();
0774: if (elementUri.equals(nameUri)
0775: && elementName.equals(nameLocal)) {
0776: next = element;
0777: break;
0778: }
0779: }
0780: }
0781: return next != null;
0782: }
0783:
0784: public Object next() {
0785: if (!hasNext()) {
0786: throw new NoSuchElementException();
0787: }
0788: last = next;
0789: next = null;
0790: return last;
0791: }
0792:
0793: public void remove() {
0794: if (last == null) {
0795: throw new IllegalStateException();
0796: }
0797: Node target = last;
0798: last = null;
0799: removeChild(target);
0800: }
0801: };
0802: }
0803:
0804: public void removeContents() {
0805: Node currentChild = getFirstChild();
0806:
0807: while (currentChild != null) {
0808: Node temp = currentChild.getNextSibling();
0809: if (currentChild instanceof javax.xml.soap.Node) {
0810: ((javax.xml.soap.Node) currentChild).detachNode();
0811: } else {
0812: Node parent = currentChild.getParentNode();
0813: if (parent != null) {
0814: parent.removeChild(currentChild);
0815: }
0816:
0817: }
0818: currentChild = temp;
0819: }
0820: }
0821:
0822: public void setEncodingStyle(String encodingStyle)
0823: throws SOAPException {
0824: if (!"".equals(encodingStyle)) {
0825: try {
0826: JaxmURI uri = new JaxmURI(encodingStyle);
0827: } catch (JaxmURI.MalformedURIException m) {
0828: log
0829: .log(
0830: Level.SEVERE,
0831: "SAAJ0105.impl.encoding.style.mustbe.valid.URI",
0832: new String[] { encodingStyle });
0833: throw new IllegalArgumentException("Encoding style ("
0834: + encodingStyle + ") should be a valid URI");
0835: }
0836: }
0837: encodingStyleAttribute.setValue(encodingStyle);
0838: tryToFindEncodingStyleAttributeName();
0839: }
0840:
0841: public String getEncodingStyle() {
0842: String encodingStyle = encodingStyleAttribute.getValue();
0843: if (encodingStyle != null)
0844: return encodingStyle;
0845: String soapNamespace = getSOAPNamespace();
0846: if (soapNamespace != null) {
0847: Attr attr = getAttributeNodeNS(soapNamespace,
0848: "encodingStyle");
0849: if (attr != null) {
0850: encodingStyle = attr.getValue();
0851: try {
0852: setEncodingStyle(encodingStyle);
0853: } catch (SOAPException se) {
0854: // has to be ignored
0855: }
0856: return encodingStyle;
0857: }
0858: }
0859: return null;
0860: }
0861:
0862: // Node methods
0863: public String getValue() {
0864: javax.xml.soap.Node valueNode = getValueNode();
0865: return valueNode == null ? null : valueNode.getValue();
0866: }
0867:
0868: public void setValue(String value) {
0869: Node valueNode = getValueNodeStrict();
0870: if (valueNode != null) {
0871: valueNode.setNodeValue(value);
0872: } else {
0873: try {
0874: addTextNode(value);
0875: } catch (SOAPException e) {
0876: throw new RuntimeException(e.getMessage());
0877: }
0878: }
0879: }
0880:
0881: protected Node getValueNodeStrict() {
0882: Node node = getFirstChild();
0883: if (node != null) {
0884: if (node.getNextSibling() == null
0885: && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
0886: return node;
0887: } else {
0888: log.severe("SAAJ0107.impl.elem.child.not.single.text");
0889: throw new IllegalStateException();
0890: }
0891: }
0892:
0893: return null;
0894: }
0895:
0896: protected javax.xml.soap.Node getValueNode() {
0897: Iterator i = getChildElements();
0898: while (i.hasNext()) {
0899: javax.xml.soap.Node n = (javax.xml.soap.Node) i.next();
0900: if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE
0901: || n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
0902: // TODO: Hack to fix text node split into multiple lines.
0903: normalize();
0904: // Should remove the normalization step when this gets fixed in
0905: // DOM/Xerces.
0906: return (javax.xml.soap.Node) n;
0907: }
0908: }
0909: return null;
0910: }
0911:
0912: public void setParentElement(SOAPElement element)
0913: throws SOAPException {
0914: if (element == null) {
0915: log.severe("SAAJ0106.impl.no.null.to.parent.elem");
0916: throw new SOAPException(
0917: "Cannot pass NULL to setParentElement");
0918: }
0919: element.addChildElement(this );
0920: findEncodingStyleAttributeName();
0921: }
0922:
0923: protected void findEncodingStyleAttributeName()
0924: throws SOAPException {
0925: String soapNamespace = getSOAPNamespace();
0926: if (soapNamespace != null) {
0927: String soapNamespacePrefix = getNamespacePrefix(soapNamespace);
0928: if (soapNamespacePrefix != null) {
0929: setEncodingStyleNamespace(soapNamespace,
0930: soapNamespacePrefix);
0931: }
0932: }
0933: }
0934:
0935: protected void setEncodingStyleNamespace(String soapNamespace,
0936: String soapNamespacePrefix) throws SOAPException {
0937: Name encodingStyleAttributeName = NameImpl.create(
0938: "encodingStyle", soapNamespacePrefix, soapNamespace);
0939: encodingStyleAttribute.setName(encodingStyleAttributeName);
0940: }
0941:
0942: public SOAPElement getParentElement() {
0943: Node parentNode = getParentNode();
0944: if (parentNode instanceof SOAPDocument) {
0945: return null;
0946: }
0947: return (SOAPElement) parentNode;
0948: }
0949:
0950: protected String getSOAPNamespace() {
0951: String soapNamespace = null;
0952:
0953: SOAPElement antecedent = this ;
0954: while (antecedent != null) {
0955: Name antecedentName = antecedent.getElementName();
0956: String antecedentNamespace = antecedentName.getURI();
0957:
0958: if (NameImpl.SOAP11_NAMESPACE.equals(antecedentNamespace)
0959: || NameImpl.SOAP12_NAMESPACE
0960: .equals(antecedentNamespace)) {
0961:
0962: soapNamespace = antecedentNamespace;
0963: break;
0964: }
0965:
0966: antecedent = antecedent.getParentElement();
0967: }
0968:
0969: return soapNamespace;
0970: }
0971:
0972: public void detachNode() {
0973: Node parent = getParentNode();
0974: if (parent != null) {
0975: parent.removeChild(this );
0976: }
0977: encodingStyleAttribute.clearNameAndValue();
0978: // Fix for CR: 6474641
0979: //tryToFindEncodingStyleAttributeName();
0980: }
0981:
0982: public void tryToFindEncodingStyleAttributeName() {
0983: try {
0984: findEncodingStyleAttributeName();
0985: } catch (SOAPException e) { /*okay to fail*/
0986: }
0987: }
0988:
0989: public void recycleNode() {
0990: detachNode();
0991: // TBD
0992: // - add this to the factory so subsequent
0993: // creations can reuse this object.
0994: }
0995:
0996: class AttributeManager {
0997: Name attributeName = null;
0998: String attributeValue = null;
0999:
1000: public void setName(Name newName) throws SOAPException {
1001: clearAttribute();
1002: attributeName = newName;
1003: reconcileAttribute();
1004: }
1005:
1006: public void clearName() {
1007: clearAttribute();
1008: attributeName = null;
1009: }
1010:
1011: public void setValue(String value) throws SOAPException {
1012: attributeValue = value;
1013: reconcileAttribute();
1014: }
1015:
1016: public Name getName() {
1017: return attributeName;
1018: }
1019:
1020: public String getValue() {
1021: return attributeValue;
1022: }
1023:
1024: /** Note: to be used only in detachNode method */
1025: public void clearNameAndValue() {
1026: attributeName = null;
1027: attributeValue = null;
1028: }
1029:
1030: private void reconcileAttribute() throws SOAPException {
1031: if (attributeName != null) {
1032: removeAttribute(attributeName);
1033: if (attributeValue != null) {
1034: addAttribute(attributeName, attributeValue);
1035: }
1036: }
1037: }
1038:
1039: private void clearAttribute() {
1040: if (attributeName != null) {
1041: removeAttribute(attributeName);
1042: }
1043: }
1044: }
1045:
1046: protected static org.w3c.dom.Attr getNamespaceAttrFrom(
1047: Element element, String prefix) {
1048: NamespaceContextIterator eachNamespace = new NamespaceContextIterator(
1049: element);
1050: while (eachNamespace.hasNext()) {
1051: org.w3c.dom.Attr namespaceDecl = eachNamespace
1052: .nextNamespaceAttr();
1053: String declaredPrefix = NameImpl
1054: .getLocalNameFromTagName(namespaceDecl
1055: .getNodeName());
1056: if (declaredPrefix.equals(prefix)) {
1057: return namespaceDecl;
1058: }
1059: }
1060: return null;
1061: }
1062:
1063: protected static Iterator getAllAttributesFrom(final Element element) {
1064: final NamedNodeMap attributes = element.getAttributes();
1065:
1066: return new Iterator() {
1067: int attributesLength = attributes.getLength();
1068: int attributeIndex = 0;
1069: String currentName;
1070:
1071: public boolean hasNext() {
1072: return attributeIndex < attributesLength;
1073: }
1074:
1075: public Object next() {
1076: if (!hasNext()) {
1077: throw new NoSuchElementException();
1078: }
1079: Node current = attributes.item(attributeIndex++);
1080: currentName = current.getNodeName();
1081:
1082: String prefix = NameImpl
1083: .getPrefixFromTagName(currentName);
1084: if (prefix.length() == 0) {
1085: return NameImpl
1086: .createFromUnqualifiedName(currentName);
1087: } else {
1088: Name attributeName = NameImpl
1089: .createFromQualifiedName(currentName,
1090: current.getNamespaceURI());
1091: return attributeName;
1092: }
1093: }
1094:
1095: public void remove() {
1096: if (currentName == null) {
1097: throw new IllegalStateException();
1098: }
1099: attributes.removeNamedItem(currentName);
1100: }
1101: };
1102: }
1103:
1104: protected static String getAttributeValueFrom(Element element,
1105: Name name) {
1106: return getAttributeValueFrom(element, name.getURI(), name
1107: .getLocalName(), name.getPrefix(), name
1108: .getQualifiedName());
1109: }
1110:
1111: private static String getAttributeValueFrom(Element element,
1112: String uri, String localName, String prefix,
1113: String qualifiedName) {
1114:
1115: String nonzeroLengthUri = (uri == null || uri.length() == 0) ? null
1116: : uri;
1117:
1118: boolean mustUseGetAttributeNodeNS = (nonzeroLengthUri != null);
1119:
1120: if (mustUseGetAttributeNodeNS) {
1121:
1122: if (!element.hasAttributeNS(uri, localName)) {
1123: return null;
1124: }
1125:
1126: String attrValue = element.getAttributeNS(nonzeroLengthUri,
1127: localName);
1128:
1129: return attrValue;
1130: }
1131:
1132: Attr attribute = null;
1133: attribute = element.getAttributeNode(qualifiedName);
1134:
1135: return attribute == null ? null : attribute.getValue();
1136: }
1137:
1138: protected static Iterator getChildElementsFrom(final Element element) {
1139: return new Iterator() {
1140: Node next = element.getFirstChild();
1141: Node nextNext = null;
1142: Node last = null;
1143:
1144: public boolean hasNext() {
1145: if (next != null) {
1146: return true;
1147: }
1148: if (next == null && nextNext != null) {
1149: next = nextNext;
1150: }
1151:
1152: return next != null;
1153: }
1154:
1155: public Object next() {
1156: if (hasNext()) {
1157: last = next;
1158: next = null;
1159:
1160: if ((element instanceof ElementImpl)
1161: && (last instanceof Element)) {
1162: last = ((ElementImpl) element)
1163: .convertToSoapElement((Element) last);
1164: }
1165:
1166: nextNext = last.getNextSibling();
1167: return last;
1168: }
1169: throw new NoSuchElementException();
1170: }
1171:
1172: public void remove() {
1173: if (last == null) {
1174: throw new IllegalStateException();
1175: }
1176: Node target = last;
1177: last = null;
1178: element.removeChild(target);
1179: }
1180: };
1181: }
1182:
1183: public static String getQualifiedName(QName name) {
1184: String prefix = name.getPrefix();
1185: String localName = name.getLocalPart();
1186: String qualifiedName = null;
1187:
1188: if (prefix != null && prefix.length() > 0) {
1189: qualifiedName = prefix + ":" + localName;
1190: } else {
1191: qualifiedName = localName;
1192: }
1193: return qualifiedName;
1194: }
1195:
1196: public static String getLocalPart(String qualifiedName) {
1197: if (qualifiedName == null) {
1198: // Log
1199: throw new IllegalArgumentException(
1200: "Cannot get local name for a \"null\" qualified name");
1201: }
1202:
1203: int index = qualifiedName.indexOf(':');
1204: if (index < 0)
1205: return qualifiedName;
1206: else
1207: return qualifiedName.substring(index + 1);
1208: }
1209:
1210: public static String getPrefix(String qualifiedName) {
1211: if (qualifiedName == null) {
1212: // Log
1213: throw new IllegalArgumentException(
1214: "Cannot get prefix for a \"null\" qualified name");
1215: }
1216:
1217: int index = qualifiedName.indexOf(':');
1218: if (index < 0)
1219: return "";
1220: else
1221: return qualifiedName.substring(0, index);
1222: }
1223:
1224: protected boolean isNamespaceQualified(Name name) {
1225: return !"".equals(name.getURI());
1226: }
1227:
1228: protected boolean isNamespaceQualified(QName name) {
1229: return !"".equals(name.getNamespaceURI());
1230: }
1231:
1232: protected SOAPElement circumventBug5034339(SOAPElement element) {
1233:
1234: Name elementName = element.getElementName();
1235: if (!isNamespaceQualified(elementName)) {
1236: String prefix = elementName.getPrefix();
1237: String defaultNamespace = getNamespaceURI(prefix);
1238: if (defaultNamespace != null) {
1239: Name newElementName = NameImpl.create(elementName
1240: .getLocalName(), elementName.getPrefix(),
1241: defaultNamespace);
1242: SOAPElement newElement = createElement(newElementName);
1243: replaceChild(newElement, element);
1244: return newElement;
1245: }
1246: }
1247: return element;
1248: }
1249:
1250: //TODO: This is a temporary SAAJ workaround for optimizing XWS
1251: // should be removed once the corresponding JAXP bug is fixed
1252: // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
1253: public void setAttributeNS(String namespaceURI,
1254: String qualifiedName, String value) {
1255: int index = qualifiedName.indexOf(':');
1256: String prefix, localName;
1257: if (index < 0) {
1258: prefix = null;
1259: localName = qualifiedName;
1260: } else {
1261: prefix = qualifiedName.substring(0, index);
1262: localName = qualifiedName.substring(index + 1);
1263: }
1264:
1265: // Workaround for bug 6467808 - This needs to be fixed in JAXP
1266:
1267: // Rolling back this fix, this is a wrong fix, infact its causing other regressions in JAXWS tck and
1268: // other tests, because of this change the namespace declarations on soapenv:Fault element are never
1269: // picked up. The fix for bug 6467808 should be in JAXP.
1270: // if(elementQName.getLocalPart().equals("Fault") &&
1271: // (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(value) ||
1272: // SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(value)))
1273: // return;
1274:
1275: super .setAttributeNS(namespaceURI, qualifiedName, value);
1276: //String tmpLocalName = this.getLocalName();
1277: String tmpURI = this .getNamespaceURI();
1278: boolean isIDNS = false;
1279: if (tmpURI != null
1280: && (tmpURI.equals(DSIG_NS) || tmpURI.equals(XENC_NS))) {
1281: isIDNS = true;
1282: }
1283: //No need to check for Signature/encryption element
1284: //just check for namespace.
1285: if (localName.equals("Id")) {
1286: if (namespaceURI == null || namespaceURI.equals("")) {
1287: setIdAttribute(localName, true);
1288: } else if (isIDNS || WSU_NS.equals(namespaceURI)) {
1289: setIdAttributeNS(namespaceURI, localName, true);
1290: }
1291: }
1292:
1293: }
1294:
1295: }
|