blob: 18a807fe20a965331da0648605bd311c6ad9255d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.saaj;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPVersion;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
public class SOAPBodyImpl extends SOAPElementImpl<org.apache.axiom.soap.SOAPBody> implements SOAPBody {
private boolean isBodyElementAdded;
/** @param omSOAPBody */
public SOAPBodyImpl(org.apache.axiom.soap.SOAPBody omSOAPBody) {
super(omSOAPBody);
}
/* (non-Javadoc)
* @see javax.xml.soap.SOAPElement#addChildElement(java.lang.String)
*/
public SOAPElement addChildElement(String localName) throws SOAPException {
if (omTarget.hasFault()) {
throw new SOAPException("A SOAPFault has been already added to this SOAPBody");
}
SOAPBodyElementImpl<OMElement> childEle =
new SOAPBodyElementImpl<OMElement>((OMElement)target.getOwnerDocument().createElementNS(null, localName));
target.appendChild(childEle.target);
isBodyElementAdded = true;
return childEle;
}
public SOAPElement addChildElement(String localName, String prefix) throws SOAPException {
String namespaceURI = getNamespaceURI(prefix);
if (namespaceURI == null) {
throw new SOAPException("Namespace not declared for the give prefix: " + prefix);
}
SOAPBodyElementImpl<OMElement> childEle =
new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(namespaceURI,
localName));
childEle.omTarget.setNamespace(childEle.omTarget.declareNamespace(namespaceURI, prefix));
target.appendChild(childEle.target);
childEle.setParentElement(this);
return childEle;
}
@Override
protected Element appendElement(Element child) throws SOAPException {
String namespaceURI = child.getNamespaceURI();
String prefix = child.getPrefix();
SOAPBodyElementImpl<?> childEle = toSOAPBodyElement(child);
if (namespaceURI != null && namespaceURI.trim().length() > 0) {
childEle.omTarget.setNamespace(childEle.omTarget.declareNamespace(namespaceURI, prefix));
}
target.appendChild(childEle.target);
childEle.setParentElement(this);
return childEle;
}
private SOAPBodyElementImpl<?> toSOAPBodyElement(Element element) {
if (element instanceof SOAPBodyElementImpl) {
return (SOAPBodyElementImpl<?>)element;
} else {
return new SOAPBodyElementImpl<OMElement>(((SOAPElementImpl<?>)element).omTarget);
}
}
public SOAPElement addChildElement(SOAPElement soapElement) throws SOAPException {
String namespaceURI = soapElement.getNamespaceURI();
String prefix = soapElement.getPrefix();
String localName = soapElement.getLocalName();
SOAPBodyElementImpl<OMElement> childEle;
if (namespaceURI == null || namespaceURI.trim().length() == 0) {
childEle =
new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(null, localName));
} else {
omTarget.declareNamespace(namespaceURI, prefix);
childEle =
new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(namespaceURI,
localName));
}
for (Iterator iter = soapElement.getAllAttributes(); iter.hasNext();) {
Name name = (Name)iter.next();
childEle.addAttribute(name, soapElement.getAttributeValue(name));
}
for (Iterator iter = soapElement.getChildElements(); iter.hasNext();) {
Object o = iter.next();
if (o instanceof Text) {
childEle.addTextNode(((Text)o).getData());
} else {
childEle.addChildElement((SOAPElement)o);
}
}
if (namespaceURI != null && namespaceURI.trim().length() > 0) {
childEle.omTarget.setNamespace(childEle.omTarget.declareNamespace(namespaceURI, prefix));
}
target.appendChild(childEle.target);
childEle.setParentElement(this);
return childEle;
}
/* (non-Javadoc)
* @see javax.xml.soap.SOAPElement#addChildElement(java.lang.String, java.lang.String, java.lang.String)
*/
public SOAPElement addChildElement(String localName, String prefix, String uri)
throws SOAPException {
if (omTarget.hasFault()) {
throw new SOAPException("A SOAPFault has been already added to this SOAPBody");
}
if (prefix == null) {
prefix = "";
}
SOAPBodyElementImpl<OMElement> childEle;
if (uri == null || "".equals(uri)) {
childEle = new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(null, localName));
} else if (prefix.length() == 0) {
childEle = new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(uri,
localName));
} else {
childEle = new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(uri,
prefix + ":" + localName));
}
childEle.omTarget.setNamespace(omTarget.getOMFactory().createOMNamespace(uri, prefix));
target.appendChild(childEle.target);
isBodyElementAdded = true;
childEle.setParentElement(this);
return childEle;
}
/**
* Creates a new <code>SOAPFault</code> object and adds it to this <code>SOAPBody</code>
* object.
*
* @return the new <code>SOAPFault</code> object
* @throws SOAPException if there is a SOAP error
*/
public SOAPFault addFault() throws SOAPException {
if (isBodyElementAdded) {
throw new SOAPException("A SOAPBodyElement has been already added to this SOAPBody");
}
org.apache.axiom.soap.SOAPFault fault = ((SOAPFactory)this.omTarget.getOMFactory()).createSOAPFault(omTarget);
SOAPFaultImpl saajSOAPFault = new SOAPFaultImpl(fault);
// set default fault code and string
saajSOAPFault.setDefaults();
return saajSOAPFault;
}
/**
* Indicates whether a <code>SOAPFault</code> object exists in this <code>SOAPBody</code>
* object.
*
* @return <code>true</code> if a <code>SOAPFault</code> object exists in this
* <code>SOAPBody</code> object; <code>false</code> otherwise
*/
public boolean hasFault() {
return omTarget.hasFault();
}
/**
* Returns the <code>SOAPFault</code> object in this <code>SOAPBody</code> object.
*
* @return the <code>SOAPFault</code> object in this <code>SOAPBody</code> object
*/
public SOAPFault getFault() {
if (omTarget.hasFault()) {
return (SOAPFault)toSAAJNode((org.w3c.dom.Node)omTarget.getFault());
}
return null;
}
/**
* Creates a new <code>SOAPBodyElement</code> object with the specified name and adds it to this
* <code>SOAPBody</code> object.
*
* @param name a <code>Name</code> object with the name for the new <code>SOAPBodyElement</code>
* object
* @return the new <code>SOAPBodyElement</code> object
* @throws SOAPException if a SOAP error occurs
*/
public SOAPBodyElement addBodyElement(Name name) throws SOAPException {
return (SOAPBodyElement)addChildElement(name);
}
/**
* Creates a new <code>SOAPFault</code> object and adds it to this <code>SOAPBody</code> object.
* The new <code>SOAPFault</code> will have a <code>faultcode</code> element that is set to the
* <code>faultCode</code> parameter and a <code>faultstring</code> set to
* <code>faultstring</code> and localized to <code>locale</code>.
*
* @param faultCode a <code>Name</code> object giving the fault code to be set; must be one of
* the fault codes defined in the SOAP 1.1 specification and of type QName
* @param faultString a <code>String</code> giving an explanation of the fault
* @param locale a <code>Locale</code> object indicating the native language of the
* <ocde>faultString</code>
* @return the new <code>SOAPFault</code> object
* @throws SOAPException if there is a SOAP error
*/
public SOAPFault addFault(Name faultCode, String faultString, Locale locale)
throws SOAPException {
org.apache.axiom.soap.SOAPFault fault = ((SOAPFactory)this.omTarget.getOMFactory()).createSOAPFault(omTarget);
SOAPFaultImpl faultImpl = new SOAPFaultImpl(fault);
faultImpl.setFaultCode(faultCode);
if (locale != null) {
faultImpl.setFaultString(faultString, locale);
} else {
faultImpl.setFaultString(faultString);
}
return faultImpl;
}
/**
* Creates a new <code>SOAPFault</code> object and adds it to this <code>SOAPBody</code> object.
* The new <code>SOAPFault</code> will have a <code>faultcode</code> element that is set to the
* <code>faultCode</code> parameter and a <code>faultstring</code> set to
* <code>faultstring</code>.
*
* @param faultCode a <code>Name</code> object giving the fault code to be set; must be one of
* the fault codes defined in the SOAP 1.1 specification and of type QName
* @param faultString a <code>String</code> giving an explanation of the fault
* @return the new <code>SOAPFault</code> object
* @throws SOAPException if there is a SOAP error
*/
public SOAPFault addFault(Name faultCode, String faultString) throws SOAPException {
return addFault(faultCode, faultString, null);
}
/**
* Adds the root node of the DOM <code>Document</code> to this <code>SOAPBody</code> object.
* <p/>
* Calling this method invalidates the <code>document</code> parameter. The client application
* should discard all references to this <code>Document</code> and its contents upon calling
* <code>addDocument</code>. The behavior of an application that continues to use such
* references is undefined.
*
* @param document the <code>Document</code> object whose root node will be added to this
* <code>SOAPBody</code>
* @return the <code>SOAPBodyElement</code> that represents the root node that was added
* @throws SOAPException if the <code>Document</code> cannot be added
*/
public SOAPBodyElement addDocument(Document document) throws SOAPException {
Element docEle = document.getDocumentElement();
SOAPElement saajSOAPEle = (SOAPElement)toSAAJNode(docEle, this);
SOAPBodyElementImpl<OMElement> bodyEle =
new SOAPBodyElementImpl<OMElement>(((SOAPElementImpl<?>)saajSOAPEle).omTarget);
addChildElement(bodyEle);
return bodyEle;
}
/**
* Creates a new <code>SOAPBodyElement</code> object with the specified name and adds it to this
* <code>SOAPBody</code> object.
*
* @param qname a <code>QName</code> object with the name for the new <code>SOAPBodyElement</code>
* object
* @return the new <code>SOAPBodyElement</code> object
* @throws SOAPException if a SOAP error occurs
*/
public SOAPBodyElement addBodyElement(QName qname) throws SOAPException {
return (SOAPBodyElement)addChildElement(qname);
}
public SOAPFault addFault(QName faultcode, String faultString) throws SOAPException {
return addFault(faultcode, faultString, null);
}
/**
* Creates a new <code>SOAPFault</code> object and adds it to this <code>SOAPBody</code> object.
* The new <code>SOAPFault</code> will have a <code>faultcode</code> element that is set to the
* <code>faultCode</code> parameter and a <code>faultstring</code> set to
* <code>faultstring</code> and localized to <code>locale</code>.
*
* @param faultCode a <code>QName</code> object giving the fault code to be
* @param faultString a <code>String</code> giving an explanation of the fault
* @param locale a <code>Locale</code> object indicating the native language of the
* <ocde>faultString</code>
* @return the new <code>SOAPFault</code> object
* @throws SOAPException if there is a SOAP error
*/
public SOAPFault addFault(QName faultCode, String faultString, Locale locale)
throws SOAPException {
org.apache.axiom.soap.SOAPFault fault = ((SOAPFactory)this.omTarget.getOMFactory()).createSOAPFault(omTarget);
SOAPFaultImpl faultImpl = new SOAPFaultImpl(fault);
if (faultImpl != null) {
faultImpl.setFaultCode(faultCode);
if (locale != null) {
faultImpl.setFaultString(faultString, locale);
} else {
faultImpl.setFaultString(faultString);
}
}
return faultImpl;
}
/**
* Creates a new DOM org.w3c.dom.Document and sets the first child of this SOAPBody as its
* document element. The child SOAPElement is removed as part of the process.
*
* @return The org.w3c.dom.Document representation of the SOAPBody content.
* @throws SOAPException - if there is not exactly one child SOAPElement of the SOAPBody.
*/
public Document extractContentAsDocument() throws SOAPException {
Iterator childElements = this.getChildElements();
org.w3c.dom.Node domNode = null;
int childCount = 0;
while (childElements.hasNext()) {
domNode = (org.w3c.dom.Node)childElements.next();
childCount++;
if (childCount > 1) {
throw new SOAPException("SOAPBody contains more than one child element");
}
}
//The child SOAPElement is removed as part of the process
this.removeContents();
Document document;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
Element element =
document.createElementNS(domNode.getNamespaceURI(), domNode.getLocalName());
element.setNodeValue(domNode.getNodeValue());
document.appendChild(element);
} catch (ParserConfigurationException e) {
throw new SOAPException(e);
}
return document;
}
private javax.xml.soap.Node toSAAJNode(org.w3c.dom.Node node,
SOAPElement parent) throws SOAPException {
if (node == null) {
return null;
}
if (node instanceof org.w3c.dom.Text) {
org.w3c.dom.Text domText = (org.w3c.dom.Text)node;
return new TextImplEx(domText.getData());
}
if (node instanceof org.w3c.dom.Comment) {
org.w3c.dom.Comment domText = (org.w3c.dom.Comment)node;
return new CommentImpl(domText.getData());
}
Element domEle = ((Element)node);
int indexOfColon = domEle.getTagName().indexOf(":");
OMNamespace ns;
String localName;
if (indexOfColon != -1) {
localName = domEle.getTagName().substring(indexOfColon + 1);
ns = omTarget.getOMFactory().createOMNamespace(domEle.getNamespaceURI(),
domEle.getTagName().substring(0, indexOfColon));
} else {
localName = domEle.getLocalName();
if (localName == null) { //it is possible that localname isn't set but name is set
localName = domEle.getTagName();
}
String prefix = domEle.getPrefix();
if(prefix == null) {
prefix = "";
}
if (domEle.getNamespaceURI() != null) {
ns = omTarget.getOMFactory().createOMNamespace(domEle.getNamespaceURI(), prefix);
} else {
if (prefix != null) {
ns = omTarget.getOMFactory().createOMNamespace("", prefix);
} else {
ns = omTarget.getOMFactory().createOMNamespace("", "");
}
}
}
OMElement eleImpl = this.omTarget.getOMFactory().createOMElement(localName, ns);
getOwnerDocument().adoptNode((Element)eleImpl);
SOAPElementImpl<OMElement> saajEle = new SOAPElementImpl<OMElement>(eleImpl);
saajEle.setParentElement(parent);
NamedNodeMap domAttrs = domEle.getAttributes();
for (int i = 0; i < domAttrs.getLength(); i++) {
org.w3c.dom.Node attrNode = domAttrs.item(i);
String attrLocalName = attrNode.getLocalName();
if (attrLocalName == null) {
attrLocalName = attrNode.getNodeName();
}
if (attrLocalName == null) {
//local part is required. "" is allowed to preserve compatibility with QName 1.0
attrLocalName = "";
}
saajEle.addAttribute(new PrefixedQName(attrNode.getNamespaceURI(),
attrLocalName,
attrNode.getPrefix()),
attrNode.getNodeValue());
}
NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childSAAJNode = toSAAJNode(childNodes.item(i), saajEle);
if (childSAAJNode instanceof javax.xml.soap.Text) {
saajEle.addTextNode(childSAAJNode.getValue());
} else {
saajEle.addChildElement((javax.xml.soap.SOAPElement)childSAAJNode);
}
}
return saajEle;
}
public Iterator getChildElements(Name name) {
QName qName = new QName(name.getURI(), name.getLocalName());
return getChildren(omTarget.getChildrenWithName(qName));
}
public SOAPElement addAttribute(QName qname, String value) throws SOAPException {
OMNamespace omNamespace = this.omTarget.getOMFactory().createOMNamespace(qname.getNamespaceURI(), qname.getPrefix());
this.omTarget.addAttribute(qname.getLocalPart(), value, omNamespace);
return this;
}
public SOAPElement addChildElement(QName qname) throws SOAPException {
if (omTarget.hasFault()) {
throw new SOAPException("A SOAPFault has been already added to this SOAPBody");
}
SOAPBodyElementImpl<OMElement> childEle;
if (qname.getNamespaceURI() == null || "".equals(qname.getNamespaceURI())) {
childEle = new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(null, qname.getLocalPart()));
}else if(null == qname.getPrefix() || "".equals(qname.getPrefix().trim())) {
childEle = new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(qname.getNamespaceURI(),
qname.getLocalPart()));
}else {
childEle = new SOAPBodyElementImpl<OMElement>(
(OMElement)target.getOwnerDocument().createElementNS(qname.getNamespaceURI(),
qname.getPrefix() + ":" +
qname.getLocalPart()));
}
childEle.omTarget.setNamespace(omTarget.getOMFactory().createOMNamespace(qname.getNamespaceURI(), qname.getPrefix()));
target.appendChild(childEle.target);
isBodyElementAdded = true;
childEle.setParentElement(this);
return childEle;
}
public QName createQName(String localName, String prefix) throws SOAPException {
if (((SOAPFactory)this.omTarget.getOMFactory()).getSOAPVersion() == SOAPVersion.SOAP11) {
return super.createQName(localName, prefix);
} else if (((SOAPFactory)this.omTarget.getOMFactory()).getSOAPVersion() == SOAPVersion.SOAP12) {
if (this.omTarget.findNamespaceURI(prefix) == null) {
throw new SOAPException("Only Namespace Qualified elements are allowed");
} else {
return super.createQName(localName, prefix);
}
} else {
throw new UnsupportedOperationException();
}
}
public Iterator getAllAttributesAsQNames() {
return super.getAllAttributesAsQNames();
}
public String getAttributeValue(QName qname) {
return super.getAttributeValue(qname);
}
public Iterator getChildElements(QName qname) {
return super.getChildElements(qname);
}
public QName getElementQName() {
return super.getElementQName();
}
public boolean removeAttribute(QName qname) {
return super.removeAttribute(qname);
}
public SOAPElement setElementQName(QName qname) throws SOAPException {
return super.setElementQName(qname);
}
public Iterator getChildElements() {
return getChildren(omTarget.getChildren());
}
public SOAPElement addTextNode(String text) throws SOAPException {
return super.addTextNode(text);
}
private Iterator getChildren(Iterator<? extends OMNode> childIter) {
Collection childElements = new ArrayList();
while (childIter.hasNext()) {
org.w3c.dom.Node domNode = (org.w3c.dom.Node)childIter.next();
org.w3c.dom.Node saajNode = toSAAJNode(domNode);
if (saajNode instanceof javax.xml.soap.Text) {
childElements.add(saajNode);
} else if (!(saajNode instanceof SOAPBodyElement)) {
// silently replace node, as per saaj 1.2 spec
if (domNode instanceof Element) {
if (omTarget.hasFault()) {
SOAPFactory omFactory = (SOAPFactory)this.omTarget.getOMFactory();
org.apache.axiom.soap.SOAPFault fault = omFactory.createSOAPFault(omTarget);
childElements.add(new SOAPFaultImpl(fault));
} else {
childElements.add(new SOAPBodyElementImpl<OMElement>((OMElement)domNode));
}
}
} else {
childElements.add(saajNode);
}
}
return childElements.iterator();
}
}