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