/**
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.wso2.carbon.bpel.core.ode.integration.utils;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPFaultCode;
import org.apache.axiom.soap.SOAPFaultDetail;
import org.apache.axiom.soap.SOAPFaultReason;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.ode.bpel.iapi.MessageExchange;
import org.apache.ode.bpel.iapi.MyRoleMessageExchange;
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
import org.apache.ode.il.OMUtils;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.NSContext;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.stl.CollectionsX;
import org.apache.ode.utils.wsdl.WsdlUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.wso2.carbon.bpel.core.ode.integration.BPELFault;
import org.wso2.carbon.bpel.core.ode.integration.BPELMessageContext;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.OperationType;
import javax.wsdl.Part;
import javax.wsdl.extensions.ElementExtensible;
import javax.wsdl.extensions.mime.MIMEContent;
import javax.wsdl.extensions.soap12.SOAP12Body;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
/**
* Utility class which contains methods for creating response SOAP messages and
* SOAP faults.
*/
public final class SOAPUtils {
// Utility classes should not have a public or default constructor.
private SOAPUtils() {
}
/**
* Create SOAP Response message from response returned byBPELServer ODE engine.
*
* @param bpelMessageContext DTO contains details on current messageflow.
* @param odeMessageExchange ODE MyRoleMessageExchange contains data on the current process
* invocation
* @throws AxisFault in case of a error while creating SOAP response.
*/
public static void createSOAPResponse(
final BPELMessageContext bpelMessageContext,
final MyRoleMessageExchange odeMessageExchange) throws AxisFault {
checkForNullValuesInResponse(bpelMessageContext, odeMessageExchange);
BindingOperation bindingOp = getBindingOperation(bpelMessageContext,
odeMessageExchange.getOperationName());
BindingOutput bindingOutput = getBindingOutPut(bindingOp);
SOAPEnvelope soapEnv = bpelMessageContext.getOutMessageContext().getEnvelope();
if (soapEnv == null) {
soapEnv = bpelMessageContext.getSoapFactoryForCurrentMessageFlow().getDefaultEnvelope();
bpelMessageContext.getOutMessageContext().setEnvelope(soapEnv);
}
populateSOAPHeaders(
odeMessageExchange.getResponse(),
soapEnv,
bpelMessageContext.getSoapFactoryForCurrentMessageFlow(),
getSOAPHeaders(bindingOutput),
odeMessageExchange.getOperation());
populateSOAPBody(
soapEnv,
bindingOutput,
bpelMessageContext.isSoap12(),
bpelMessageContext.getSoapFactoryForCurrentMessageFlow(),
odeMessageExchange.getOperation(),
odeMessageExchange.getOperation().getOutput().getMessage(),
odeMessageExchange.getResponse(),
bpelMessageContext.isRPCStyleOperation(),
false);
}
/**
* Create SOAP Request message from request submitted by ODE engine.
*
* @param bpelMessageContext DTO containing details about current message flow
* @param odePartnerMessageExchange ODE PartnerRoleMessageExchange containing information about
* current external service invocation.
* @throws AxisFault If an error occurred while creating the SOAP request
*/
public static void createSOAPRequest(
final BPELMessageContext bpelMessageContext,
final PartnerRoleMessageExchange odePartnerMessageExchange) throws AxisFault {
checkForNullValuesInRequest(bpelMessageContext, odePartnerMessageExchange);
BindingOperation bindingOp = getBindingOperation(bpelMessageContext,
odePartnerMessageExchange.getOperationName());
BindingInput bindingInput = getBindingInput(bindingOp);
SOAPEnvelope soapEnvelope = bpelMessageContext.getInMessageContext().getEnvelope();
if (soapEnvelope == null) {
soapEnvelope =
bpelMessageContext.getSoapFactoryForCurrentMessageFlow().getDefaultEnvelope();
bpelMessageContext.getInMessageContext().setEnvelope(soapEnvelope);
}
populateSOAPHeaders(
odePartnerMessageExchange.getRequest(),
soapEnvelope,
bpelMessageContext.getSoapFactoryForCurrentMessageFlow(),
getSOAPHeaders(bindingInput),
odePartnerMessageExchange.getOperation());
populateSOAPBody(
soapEnvelope,
bindingInput,
bpelMessageContext.isSoap12(),
bpelMessageContext.getSoapFactoryForCurrentMessageFlow(),
odePartnerMessageExchange.getOperation(),
odePartnerMessageExchange.getOperation().getInput().getMessage(),
odePartnerMessageExchange.getRequest(),
bpelMessageContext.isRPCStyleOperation(),
true);
}
private static BindingInput getBindingInput(BindingOperation bindingOp) {
BindingInput bindingInput = bindingOp.getBindingInput();
if (bindingInput == null) {
throw new NullPointerException("BindingInput is null.");
}
return bindingInput;
}
@SuppressWarnings("unchecked")
private static void populateSOAPBody(
SOAPEnvelope soapEnvelope,
ElementExtensible bindingInput,
boolean soap12,
SOAPFactory soapFactory,
Operation operation,
Message messageDefinition,
org.apache.ode.bpel.iapi.Message messageFromODE,
boolean isRPC,
boolean isRequest) throws BPELFault {
if (soap12) {
SOAP12Body soapBodyDefinition = getSOAP12Body(bindingInput);
if (soapBodyDefinition != null) {
SOAPBody soapBody;
if (soapEnvelope.getBody() != null) {
soapBody = soapEnvelope.getBody();
} else {
soapBody = soapFactory.createSOAPBody(soapEnvelope);
}
OMElement partHolder;
if (isRPC) {
String rpcWrapperElementName;
if (isRequest) {
rpcWrapperElementName = operation.getName();
} else {
rpcWrapperElementName = operation.getName() + "Response";
}
partHolder = createRPCWrapperElement(
soapBody,
soapFactory,
new QName(soapBodyDefinition.getNamespaceURI(), rpcWrapperElementName));
} else {
partHolder = soapBody;
}
List<Part> parts = messageDefinition.getOrderedParts(soapBodyDefinition.getParts());
for (Part p : parts) {
Element partContent = DOMUtils.findChildByName(
messageFromODE.getMessage(),
new QName(null, p.getName()));
if (partContent == null) {
throw new BPELFault("Missing required part in ODE Message: " +
new QName(null, p.getName()));
}
OMElement omPartContent = OMUtils.toOM(partContent, soapFactory);
if (isRPC) {
partHolder.addChild(omPartContent);
} else {
for (Iterator<OMNode> i = omPartContent.getChildren(); i.hasNext(); ) {
partHolder.addChild(i.next());
}
}
}
}
} else {
javax.wsdl.extensions.soap.SOAPBody soapBodyDefinition = getSOAP11Body(bindingInput);
if (soapBodyDefinition != null) {
SOAPBody soapBody;
if (soapEnvelope.getBody() != null) {
soapBody = soapEnvelope.getBody();
} else {
soapBody = soapFactory.createSOAPBody(soapEnvelope);
}
OMElement partHolder;
if (isRPC) {
String rpcWrapperElementName;
if (isRequest) {
rpcWrapperElementName = operation.getName();
} else {
rpcWrapperElementName = operation.getName() + "Response";
}
partHolder = createRPCWrapperElement(
soapBody,
soapFactory,
new QName(soapBodyDefinition.getNamespaceURI(), rpcWrapperElementName));
} else {
partHolder = soapBody;
}
List<Part> parts = messageDefinition.getOrderedParts(soapBodyDefinition.getParts());
for (Part p : parts) {
Element partContent = DOMUtils.findChildByName(
messageFromODE.getMessage(),
new QName(null, p.getName()));
if (partContent == null) {
throw new BPELFault("Missing required part in ODE Message: " +
new QName(null, p.getName()));
}
OMElement omPartContent = OMUtils.toOM(partContent, soapFactory);
if (isRPC) {
partHolder.addChild(omPartContent);
} else {
for (Iterator<OMNode> i = omPartContent.getChildren(); i.hasNext(); ) {
partHolder.addChild(i.next());
}
}
}
}
}
}
private static OMElement createRPCWrapperElement(
SOAPBody soapBody,
SOAPFactory soapFactory,
QName wrapperElementName) {
return soapFactory.createOMElement(wrapperElementName, soapBody);
}
private static void populateSOAPHeaders(
org.apache.ode.bpel.iapi.Message messageFromOde,
SOAPEnvelope soapEnvelope,
SOAPFactory soapFactory,
List<javax.wsdl.extensions.soap.SOAPHeader> soapHaderDefinitions,
Operation operation
) throws BPELFault {
if (messageFromOde.getHeaderParts().size() > 0
|| soapHaderDefinitions.size() > 0) {
for (javax.wsdl.extensions.soap.SOAPHeader soapHeaderDefinition : soapHaderDefinitions) {
handleSOAPHeaderElementsInBindingOperation(
soapEnvelope,
soapFactory,
messageFromOde,
operation,
soapHeaderDefinition);
}
org.apache.axiom.soap.SOAPHeader soapHeader = soapEnvelope.getHeader();
if (soapHeader == null) {
soapHeader = soapFactory.createSOAPHeader(soapEnvelope);
}
for (Node headerNode : messageFromOde.getHeaderParts().values()) {
if (headerNode.getNodeType() == Node.ELEMENT_NODE) {
addSOAPHeaderBock(soapHeader, headerNode, soapFactory);
} else {
throw new BPELFault("SOAP Header Must be an Element");
}
}
}
}
private static void addSOAPHeaderBock(
final org.apache.axiom.soap.SOAPHeader soapHeader,
final Node headerNode,
final SOAPFactory soapFactory) {
if (soapHeader.getFirstChildWithName(new QName(headerNode.getNamespaceURI(),
headerNode.getLocalName())) == null) {
OMNamespace ns = null;
if (headerNode.getNamespaceURI() != null) {
if (headerNode.getPrefix() != null) {
ns = soapFactory.createOMNamespace(headerNode.getNamespaceURI(), headerNode.getPrefix());
} else {
ns = soapFactory.createOMNamespace(headerNode.getNamespaceURI(), "");
}
}
SOAPHeaderBlock hb = soapHeader.addHeaderBlock(headerNode.getLocalName(),
ns);
NSContext nscontext = DOMUtils.getMyNSContext((Element) headerNode);
injectNamespaces(hb, nscontext.toMap());
NamedNodeMap attrs = headerNode.getAttributes();
for (int i = 0; i < attrs.getLength(); ++i) {
Attr attr = (Attr) attrs.item(i);
if (attr.getLocalName().equals("xmlns")
|| (attr.getNamespaceURI() != null && attr.getNamespaceURI().equals(DOMUtils.NS_URI_XMLNS))) {
continue;
}
OMNamespace attrOmNs = null;
String attrNs = attr.getNamespaceURI();
String attrPrefix = attr.getPrefix();
if (attrNs != null) {
attrOmNs = hb.findNamespace(attrNs, null);
}
if (attrOmNs == null && attrPrefix != null) {
attrOmNs = hb.findNamespace(null, attrPrefix);
}
hb.addAttribute(attr.getLocalName(), attr.getValue(), attrOmNs);
}
NodeList childNodes = headerNode.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
switch (childNodes.item(i).getNodeType()) {
case Node.CDATA_SECTION_NODE:
hb.addChild(soapFactory.createOMText(node.getTextContent(), XMLStreamConstants.CDATA));
break;
case Node.TEXT_NODE:
hb.addChild(soapFactory.createOMText(node.getTextContent(), XMLStreamConstants.CHARACTERS));
break;
case Node.ELEMENT_NODE:
OMUtils.toOM((Element) node, soapFactory, hb);
break;
}
}
}
}
private static void injectNamespaces(OMElement omElement, Map<String, String> nscontext) {
for (String prefix : nscontext.keySet()) {
String uri = nscontext.get(prefix);
if (prefix.equals("")) {
omElement.declareDefaultNamespace(uri);
} else {
omElement.declareNamespace(uri, prefix);
}
}
}
public static BindingOperation getBindingOperation(
final BPELMessageContext bpelMessageContext, final String operationName) {
BindingOperation bOp = bpelMessageContext.getWsdlBindingForCurrentMessageFlow()
.getBindingOperation(operationName, null, null);
if (bOp == null) {
throw new NullPointerException("BindingOperation not found for operation "
+ operationName + ".");
}
return bOp;
}
private static BindingOutput getBindingOutPut(final BindingOperation bOp) {
BindingOutput bOutput = bOp.getBindingOutput();
if (bOutput == null) {
throw new NullPointerException("BindingOutput cannot be null for operation "
+ bOp.getName() + ".");
}
return bOutput;
}
private static void checkForNullValuesInResponse(
final BPELMessageContext bpelMessageContext,
final MessageExchange odeMessageExchange) {
if (odeMessageExchange.getOperation() == null) {
throw new NullPointerException("Null operation");
}
if (odeMessageExchange.getResponse() == null) {
throw new NullPointerException("Null message.");
}
if (bpelMessageContext.getOutMessageContext() == null) {
throw new NullPointerException("Null msgCtx");
}
}
public static void checkForNullValuesInRequest(
final BPELMessageContext bpelMessageContext,
final MessageExchange odeMessageExchange) {
if (odeMessageExchange.getOperation() == null) {
throw new NullPointerException("Null operation");
}
if (odeMessageExchange.getRequest() == null) {
throw new NullPointerException("Null message.");
}
if (bpelMessageContext.getInMessageContext() == null) {
throw new NullPointerException("Null msgCtx");
}
}
@SuppressWarnings("unchecked")
private static void handleSOAPHeaderElementsInBindingOperation(
SOAPEnvelope soapEnvelope,
SOAPFactory soapFactory,
org.apache.ode.bpel.iapi.Message messageFromOde,
Operation wsdlOperation,
final javax.wsdl.extensions.soap.SOAPHeader soapHeaderElementDefinition)
throws BPELFault {
Map<String, Node> headerParts = messageFromOde.getHeaderParts();
Message responseMessageDefinition = wsdlOperation.getOutput() != null ?
wsdlOperation.getOutput().getMessage() : null;
// If there isn't a message attribute in header element definition or if the
// message attribute value is equal to the response message QName, then this
// header element is part of the actual payload.
// Refer SOAP Binding specification at http://www.w3.org/TR/wsdl#_soap-b.
final boolean isHeaderElementAPartOfPayload =
soapHeaderElementDefinition.getMessage() == null
|| ((wsdlOperation.getStyle() != OperationType.ONE_WAY) && soapHeaderElementDefinition
.getMessage().equals(
responseMessageDefinition.getQName()));
if (soapHeaderElementDefinition.getPart() == null) {
// Part information not found. Ignoring this header definition.
return;
}
if (isHeaderElementAPartOfPayload
&& (responseMessageDefinition != null && responseMessageDefinition.getPart
(soapHeaderElementDefinition.getPart())
== null)) {
// If SOAP Header element is part of the actual payload and
// if we couldn't find part in the response message definition equals to
// name of the SOAP header element definition part attribute value,
// we should throw a exception.
throw new BPELFault("SOAP Header Element Definition refer unknown part.");
}
Element partElement = null;
if (headerParts.size() > 0 && isHeaderElementAPartOfPayload) {
try {
partElement = (Element) headerParts.get(soapHeaderElementDefinition.getPart());
} catch (ClassCastException e) {
throw new BPELFault("SOAP Header must be a DOM Element.", e);
}
}
// We only complain about missing header data if that data is a part of the actual
// message payload. This is because, some headers will provided by SOAP engine.
if (partElement == null && isHeaderElementAPartOfPayload) {
if (messageFromOde.getPart(soapHeaderElementDefinition.getPart())
!= null) {
partElement = messageFromOde.getPart(
soapHeaderElementDefinition.getPart());
} else {
throw new BPELFault("Missing Required part in response message.");
}
}
// Handle headers defined as abstract message parts. In this scenario, the header is not part of the payload,
// and can be found and extracted from the odeMessage object
if (partElement == null && messageFromOde.getParts().size() > 0 && !isHeaderElementAPartOfPayload) {
try {
partElement = (Element) messageFromOde.getPart(soapHeaderElementDefinition.getPart());
} catch (ClassCastException e) {
throw new BPELFault("Soap header must be an element" + messageFromOde.getPart
(soapHeaderElementDefinition.getPart()));
}
}
// If header is not part of the payload and if header element is null,
// just ignore this case.
if (partElement == null) {
return;
}
org.apache.axiom.soap.SOAPHeader soapHeader = soapEnvelope.getHeader();
if (soapHeader == null) {
soapHeader = soapFactory
.createSOAPHeader(soapEnvelope);
}
OMElement omPart = OMUtils.toOM(partElement, soapFactory);
for (Iterator<OMNode> i = omPart.getChildren(); i.hasNext(); ) {
soapHeader.addChild(i.next());
}
}
/**
* Crete SOAP Fault from fault information returned from ODE.
*
* @param bpelMessageContext DTO containing information on current messageflow.
* @param odeMessageContext ODE MyRoleMessageExchange containing information on current process
* invocation.
* @return SOAPFault instance
* @throws AxisFault in case of a error while creating SOAP Fault.
*/
public static SOAPFault createSoapFault(final BPELMessageContext bpelMessageContext,
final MessageExchange odeMessageContext)
throws AxisFault {
SOAPFactory soapFactory = bpelMessageContext.getSoapFactoryForCurrentMessageFlow();
OMElement detail = buildSoapDetail(bpelMessageContext, odeMessageContext);
SOAPFault fault = soapFactory.createSOAPFault();
SOAPFaultCode code = soapFactory.createSOAPFaultCode(fault);
code.setText(new QName(Namespaces.SOAP_ENV_NS, "Server"));
SOAPFaultReason reason = soapFactory.createSOAPFaultReason(fault);
reason.setText(odeMessageContext.getFault());
SOAPFaultDetail soapDetail = soapFactory.createSOAPFaultDetail(fault);
if (detail != null) {
soapDetail.addDetailEntry(detail);
}
return fault;
}
private static OMElement buildSoapDetail(
final BPELMessageContext bpelMessageContext,
final MessageExchange odeMessageContext) throws AxisFault {
Element message = odeMessageContext.getResponse().getMessage();
QName faultName = odeMessageContext.getFault();
Operation operation = odeMessageContext.getOperation();
SOAPFactory soapFactory = bpelMessageContext.getSoapFactoryForCurrentMessageFlow();
if (faultName.getNamespaceURI() == null) {
return toFaultDetail(message, soapFactory);
}
Fault f = operation.getFault(faultName.getLocalPart());
if (f == null) {
return toFaultDetail(message, soapFactory);
}
// For faults, there will be exactly one part.
Part p = (Part) f.getMessage().getParts().values().iterator().next();
if (p == null) {
return toFaultDetail(message, soapFactory);
}
Element partEl = DOMUtils.findChildByName(message, new QName(null, p.getName()));
if (partEl == null) {
return toFaultDetail(message, soapFactory);
}
Element detail = DOMUtils.findChildByName(partEl, p.getElementName());
if (detail == null) {
return toFaultDetail(message, soapFactory);
}
return OMUtils.toOM(detail, soapFactory);
}
private static OMElement toFaultDetail(final Element message, final SOAPFactory soapFactory) {
if (message == null) {
return null;
}
Element firstPart = DOMUtils.getFirstChildElement(message);
if (firstPart == null) {
return null;
}
Element detail = DOMUtils.getFirstChildElement(firstPart);
if (detail == null) {
return OMUtils.toOM(firstPart, soapFactory);
}
return OMUtils.toOM(detail, soapFactory);
}
public static org.apache.ode.bpel.iapi.Message parseSOAPResponseFromPartner(
BPELMessageContext partnerInvocationContext,
MessageExchange partnerRoleMessageExchange) throws BPELFault {
org.apache.ode.bpel.iapi.Message messageToODE = partnerRoleMessageExchange.createMessage(
partnerRoleMessageExchange.getOperation().getOutput().getMessage().getQName());
BindingOperation bindingOp = getBindingOperation(partnerInvocationContext,
partnerRoleMessageExchange.getOperationName());
BindingOutput bindingOutPut = getBindingOutPut(bindingOp);
SOAPEnvelope responseFromPartnerService =
partnerInvocationContext.getOutMessageContext().getEnvelope();
if (partnerInvocationContext.isSoap12()) {
javax.wsdl.extensions.soap12.SOAP12Body soapBodyDefinition = getSOAP12Body(bindingOutPut);
if (soapBodyDefinition != null) {
if (responseFromPartnerService.getBody() != null) {
extractSOAPBodyParts(partnerRoleMessageExchange,
messageToODE,
responseFromPartnerService.getBody(),
soapBodyDefinition.getParts(),
soapBodyDefinition.getNamespaceURI(),
partnerInvocationContext.isRPCStyleOperation());
} else {
throw new BPELFault("SOAP Body cannot be null for WSDL operation which "
+ "requires SOAP Body.");
}
}
} else {
javax.wsdl.extensions.soap.SOAPBody soapBodyDefinition = getSOAP11Body(bindingOutPut);
if (soapBodyDefinition != null) {
if (responseFromPartnerService.getBody() != null) {
extractSOAPBodyParts(partnerRoleMessageExchange,
messageToODE,
responseFromPartnerService.getBody(),
soapBodyDefinition.getParts(),
soapBodyDefinition.getNamespaceURI(),
partnerInvocationContext.isRPCStyleOperation());
} else {
throw new BPELFault("SOAP Body cannot be null for WSDL operation which "
+ "requires SOAP Body.");
}
}
}
if (getSOAPHeaders(bindingOutPut) != null &&
responseFromPartnerService.getHeader() != null) {
extractSoapHeaderParts(messageToODE,
partnerInvocationContext.getBpelServiceWSDLDefinition(),
responseFromPartnerService.getHeader(),
getSOAPHeaders(bindingOutPut),
partnerRoleMessageExchange.getOperation().getOutput().getMessage());
}
return messageToODE;
}
public static org.apache.ode.bpel.iapi.Message parseResponseFromRESTService(BPELMessageContext
partnerInvocationContext,
PartnerRoleMessageExchange
odePartnerMex) {
org.apache.ode.bpel.iapi.Message messageToODE = odePartnerMex.createMessage(
odePartnerMex.getOperation().getOutput().getMessage().getQName());
BindingOperation bindingOp = getBindingOperation(partnerInvocationContext,
odePartnerMex.getOperationName());
BindingOutput bindingOutPut = getBindingOutPut(bindingOp);
javax.wsdl.extensions.mime.MIMEContent mimeContent = getFirstExtensibilityElement(bindingOutPut, MIMEContent
.class);
if (mimeContent != null) {
SOAPEnvelope soapEnv = partnerInvocationContext.getOutMessageContext().getEnvelope();
Iterator childElementsItr = soapEnv.getBody().getChildElements();
while (childElementsItr.hasNext()) {
OMNode child = (OMNode) childElementsItr.next();
if (child.getType() == OMNode.ELEMENT_NODE) {
Document doc = DOMUtils.newDocument();
Element domPart = doc.createElementNS(null, mimeContent.getPart());
domPart.appendChild(doc.importNode(OMUtils.toDOM((OMElement) child), true));
messageToODE.setPart(mimeContent.getPart(), domPart);
return messageToODE;
}
}
}
throw new IllegalArgumentException("WSO2 BPS only support HTTP binding with mime output.");
}
private static void extractSOAPBodyParts(
MessageExchange partnerRoleMessageExchange,
org.apache.ode.bpel.iapi.Message messageToODE,
SOAPBody omSOAPBody,
List parts,
String namespace,
boolean isRPC) throws BPELFault {
List<Part> messageBodyParts = partnerRoleMessageExchange.getOperation()
.getOutput().getMessage().getOrderedParts(parts);
if (isRPC) {
String rpcWrapperElementName = partnerRoleMessageExchange.getOperationName()
+ "Response";
OMElement rpcWrapperElement = omSOAPBody.getFirstChildWithName(
new QName(namespace, rpcWrapperElementName));
if (rpcWrapperElement == null) {
throw new BPELFault("Message body doesn't contain expected part wrapper: " +
new QName(namespace, rpcWrapperElementName));
}
// In RPC the body element is the operation name, wrapping parts. Order doesn't
// really matter as far as we're concerned. All we need to do is copy the soap:body
// children, since doc-lit rpc looks the same in ode and soap.
for (Part partDef : messageBodyParts) {
OMElement omPartElement = rpcWrapperElement.getFirstChildWithName(
new QName(null, partDef.getName()));
if (omPartElement == null) {
throw new BPELFault("SOAP body doesn't contain required part: " +
new QName(null, partDef.getName()));
}
messageToODE.setPart(omPartElement.getLocalName(), OMUtils.toDOM(omPartElement));
}
} else {
// In doc-literal style, we expect the elements in the body to correspond (in order)
// to the parts defined in the binding. All the parts should be element-typed,
// otherwise it is a mess.
Iterator<OMElement> omParts = omSOAPBody.getChildElements();
for (Part partDef : messageBodyParts) {
if (!omParts.hasNext()) {
throw new BPELFault("SOAP body doesn't contain required part.");
}
OMElement omPart = omParts.next();
if (partDef.getElementName() == null) {
throw new BPELFault("Binding defines non element document list parts.");
}
if (!omPart.getQName().equals(partDef.getElementName())) {
throw new BPELFault("Unexpected element in SOAP body: " + omPart.getQName());
}
Document doc = DOMUtils.newDocument();
Element domPart = doc.createElementNS(null, partDef.getName());
domPart.appendChild(doc.importNode(OMUtils.toDOM(omPart), true));
messageToODE.setPart(partDef.getName(), domPart);
}
}
}
private static void extractSoapHeaderParts(org.apache.ode.bpel.iapi.Message message,
Definition wsdl,
org.apache.axiom.soap.SOAPHeader soapHeader,
List<javax.wsdl.extensions.soap.SOAPHeader> headerDefs,
Message msg) throws BPELFault {
// Checking that the definitions we have are at least there
for (javax.wsdl.extensions.soap.SOAPHeader headerDef : headerDefs) {
handleSoapHeaderPartDef(message, wsdl, soapHeader, headerDef, msg);
}
// Extracting whatever header elements we find in the message, binding and abstract parts
// aren't reliable enough given what people do out there.
Iterator headersIter = soapHeader.getChildElements();
while (headersIter.hasNext()) {
OMElement header = (OMElement) headersIter.next();
String partName = findHeaderPartName(headerDefs, wsdl, header.getQName());
message.setHeaderPart(partName, OMUtils.toDOM(header));
}
}
private static void handleSoapHeaderPartDef(org.apache.ode.bpel.iapi.Message odeMessage,
Definition wsdl,
SOAPHeader header,
javax.wsdl.extensions.soap.SOAPHeader headerdef,
Message msgType) throws BPELFault {
// Is this header part of the "payload" messsage?
boolean payloadMessageHeader = headerdef.getMessage() == null
|| headerdef.getMessage().equals(msgType.getQName());
boolean requiredHeader = payloadMessageHeader
|| (headerdef.getRequired() != null && headerdef.getRequired());
if (requiredHeader && header == null) {
throw new BPELFault("SOAP Header missing required element.");
}
if (header == null) {
return;
}
Message hdrMsg = wsdl.getMessage(headerdef.getMessage());
if (hdrMsg == null) {
return;
}
Part p = hdrMsg.getPart(headerdef.getPart());
if (p == null || p.getElementName() == null) {
return;
}
OMElement headerEl = header.getFirstChildWithName(p.getElementName());
if (requiredHeader && headerEl == null) {
throw new BPELFault("SOAP Header missing required element: " + p.getElementName());
}
if (headerEl == null) {
return;
}
odeMessage.setHeaderPart(p.getName(), OMUtils.toDOM(headerEl));
}
private static String findHeaderPartName(List<javax.wsdl.extensions.soap.SOAPHeader> headerDefs,
Definition wsdl,
QName elmtName) {
for (javax.wsdl.extensions.soap.SOAPHeader headerDef : headerDefs) {
Message hdrMsg = wsdl.getMessage(headerDef.getMessage());
for (Object o : hdrMsg.getParts().values()) {
Part p = (Part) o;
if (p.getElementName().equals(elmtName)) {
return p.getName();
}
}
}
return elmtName.getLocalPart();
}
public static Fault parseSoapFault(Element odeMsgEl, SOAPEnvelope envelope, Operation operation)
throws AxisFault {
SOAPFault flt = envelope.getBody().getFault();
SOAPFaultDetail detail = flt.getDetail();
Fault fdef = inferFault(operation, flt);
if (fdef == null) {
return null;
}
Part pdef = (Part) fdef.getMessage().getParts().values().iterator().next();
Element partel = odeMsgEl.getOwnerDocument().createElementNS(null, pdef.getName());
odeMsgEl.appendChild(partel);
if (detail.getFirstChildWithName(pdef.getElementName()) != null) {
partel.appendChild(odeMsgEl.getOwnerDocument().importNode(
OMUtils.toDOM(detail.getFirstChildWithName(pdef.getElementName())), true));
} else {
partel.appendChild(odeMsgEl.getOwnerDocument().importNode(OMUtils.toDOM(detail), true));
}
return fdef;
}
private static Fault inferFault(Operation operation, SOAPFault flt) {
if (flt.getDetail() == null) {
return null;
}
if (flt.getDetail().getFirstElement() == null) {
return null;
}
// The detail is a dummy <detail> node containing the interesting fault element
QName elName = flt.getDetail().getFirstElement().getQName();
return WsdlUtils.inferFault(operation, elName);
}
public static javax.wsdl.extensions.soap.SOAPBody getSOAP11Body(final ElementExtensible ee) {
return getFirstExtensibilityElement(ee, javax.wsdl.extensions.soap.SOAPBody.class);
}
public static javax.wsdl.extensions.soap12.SOAP12Body getSOAP12Body(final ElementExtensible ee) {
return getFirstExtensibilityElement(ee, javax.wsdl.extensions.soap12.SOAP12Body.class);
}
public static <T> T getFirstExtensibilityElement(final ElementExtensible parent,
final Class<T> cls) {
Collection<T> ee = CollectionsX.filter(parent.getExtensibilityElements(), cls);
return ee.isEmpty() ? null : ee.iterator().next();
}
@SuppressWarnings("unchecked")
public static List<javax.wsdl.extensions.soap.SOAPHeader> getSOAPHeaders(
final ElementExtensible eee) {
return CollectionsX.filter(new ArrayList<javax.wsdl.extensions.soap.SOAPHeader>(),
(Collection<Object>) eee.getExtensibilityElements(),
javax.wsdl.extensions.soap.SOAPHeader.class);
}
}