/*
* Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.ode.integration;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.context.ServiceGroupContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyEngine;
import org.apache.ode.bpel.epr.EndpointFactory;
import org.apache.ode.bpel.epr.MutableEndpoint;
import org.apache.ode.bpel.epr.WSAEndpoint;
import org.apache.ode.bpel.epr.WSDL11Endpoint;
import org.apache.ode.bpel.iapi.EndpointReference;
import org.apache.ode.bpel.iapi.Message;
import org.apache.ode.bpel.iapi.MessageExchange;
import org.apache.ode.bpel.iapi.PartnerRoleChannel;
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
import org.apache.ode.bpel.iapi.ProcessConf;
import org.apache.ode.il.OMUtils;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.stl.CollectionsX;
import org.apache.ode.utils.uuid.UUID;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.wso2.carbon.bpel.ode.integration.axis2.WSDLAwareSOAPProcessor;
import org.wso2.carbon.bpel.ode.integration.config.EndpointConfiguration;
import org.wso2.carbon.bpel.ode.integration.store.ProcessConfigurationImpl;
import org.wso2.carbon.bpel.ode.integration.utils.*;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpoint;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpointFactory;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpointConstants;
import javax.wsdl.*;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.http.HTTPBinding;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* Implements the BPEL Process Partner Endpoint. This will handle all the communication between
* partner services and BPEL process. This implements PartnerRoleChanel interface in-addition
* to providing methods used to invoke external partner endpoints.
*/
public class PartnerService implements PartnerRoleChannel {
private static final Log log = LogFactory.getLog(PartnerService.class);
private static Log messageTraceLog = LogFactory.getLog(BPELConstants.MESSAGE_TRACE);
// WSDL Definition for partner service
private Definition wsdlDefinition;
// Service QName of the partner service
private QName serviceName;
// Port name in the service definition of the WSDL
private String portName;
// Client side configuration context to use with external service invocations
private ConfigurationContext clientConfigCtx;
// Process configuration
private ProcessConf processConfiguration;
private WSAEndpoint endpointReference;
private String endpointUrl;
// Client side AxisConfiguration
private AxisConfiguration axisConfig;
// WSDL Binding to use for this service invocation
private Binding binding;
public PartnerService(Definition wsdlDefinition,
QName serviceName,
String portName,
ConfigurationContext clientConfigCtx,
ProcessConf pconf,
HttpConnectionManager connManager) throws AxisFault {
this.wsdlDefinition = wsdlDefinition;
this.serviceName = serviceName;
this.portName = portName;
this.clientConfigCtx = clientConfigCtx;
this.processConfiguration = pconf;
this.axisConfig = clientConfigCtx.getAxisConfiguration();
inferBindingInformation();
this.clientConfigCtx.setProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER,
connManager);
this.clientConfigCtx.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "false");
Element eprEle = BPELProcessProxy.genEPRfromWSDL(this.wsdlDefinition, this.serviceName,
this.portName);
if (eprEle == null) {
throw new IllegalArgumentException("Service Port definition not found for service:"
+ this.serviceName + " and port:" + this.portName);
}
this.endpointReference = EndpointFactory.convertToWSA(
BPELProcessProxy.createServiceRef(eprEle));
endpointUrl = endpointReference.getUrl();
}
public Definition getWsdlDefinition() {
return wsdlDefinition;
}
public Binding getBinding() {
return binding;
}
public void invoke(final PartnerRoleMessageExchange partnerRoleMessageExchange) {
boolean isTwoWay = (partnerRoleMessageExchange.getMessageExchangePattern() ==
MessageExchange.MessageExchangePattern.REQUEST_RESPONSE);
try {
// Override options are passed to the axis MessageContext so we can
// retrieve them in our session out changeHandler.
final MessageContext mctx = new MessageContext();
BPELMessageContext partnerInvocationContext =
BPELMessageContextFactory.createBPELMessageContext(mctx, this);
ExtensibilityElement bindingType =
WSDLAwareSOAPProcessor.getBindingExtension(binding);
try {
if (bindingType instanceof HTTPBinding) {
/**
* In the current HTTP binding support implementation we only support GET, DELETE with
* x-form-url-encoded and POST, PUT with application/xml content types. And as the return(out put)
* we only support mime cotent text/xml with part name. Example HTTP Binding definition:
* <wsdl:binding name="RESTServiceHttpBinding" type="ns:RESTServicePortType">
* <http:binding verb="POST" />
* <wsdl:operation name="modifyMobileNumber">
* <http:operation location="modifyMobileNumber" />
* <wsdl:input>
* <mime:content type="application/x-www-form-urlencoded"/>
* </wsdl:input>
* <wsdl:output>
* <mime:content type="text/xml" part="parameters" />
* </wsdl:output>
* </wsdl:operation>
* </wsdl:binding>
*
* *** We ignore mime:content inside input element. We infer the content type based on HTTP verb.
*
*
*/
HTTPBindingHandler httpBindingHandler =
new HTTPBindingHandler(clientConfigCtx, serviceName, portName, wsdlDefinition);
HTTPBindingHandler.HTTPBindingResponse response =
httpBindingHandler.invoke(partnerRoleMessageExchange, partnerInvocationContext);
if (isTwoWay) {
final Operation operation = partnerRoleMessageExchange.getOperation();
MessageContext responseMessageContext = response.getReponseMessageContext();
partnerInvocationContext.setInMessageContext(responseMessageContext);
MessageContext fltMessageContext = response.getFaultMessageContext();
if (messageTraceLog.isTraceEnabled()) {
messageTraceLog.trace("Response message: MEXId: " +
partnerRoleMessageExchange.getMessageExchangeId() +
" :: " + responseMessageContext.getEnvelope());
}
if (fltMessageContext != null) {
replyHTTP(partnerInvocationContext, partnerRoleMessageExchange, operation,
fltMessageContext, true);
} else {
replyHTTP(partnerInvocationContext, partnerRoleMessageExchange, operation,
responseMessageContext, response.isFault());
}
} else { /* one-way case */
partnerRoleMessageExchange.replyOneWayOk();
}
} else {
/* make the given options the parent so it becomes the defaults of the
* MessageContext. That allows the user to override specific options on a given
* message context and not affect the overall options.
*/
EndpointConfiguration endpointConf =
((ProcessConfigurationImpl) processConfiguration).getEndpointConfiguration(
new WSDL11Endpoint(this.serviceName, portName));
UnifiedEndpoint partnerEndpoint = buildUnifiedEndpoint(endpointConf);
SOAPUtils.createSOAPRequest(partnerInvocationContext, partnerRoleMessageExchange);
String mexEndpointUrl =
((MutableEndpoint) partnerRoleMessageExchange.getEndpointReference())
.getUrl();
if (!endpointUrl.equals(mexEndpointUrl)) {
partnerEndpoint.setAddress(mexEndpointUrl);
}
OperationClient opClient = getOperationClient(isTwoWay, mctx);
mctx.getOptions().setParent(opClient.getOptions());
/*
Else we assume that the epr is not changed by the process.
In this case there's a limitation we cannot invoke the epr in the wsdl
(by assingning that epr by partnerlink assign) if there is a endpoint
configuration available for that particular service
*/
opClient.addMessageContext(mctx);
Options operationOptions = opClient.getOptions();
if (partnerEndpoint.isAddressingEnabled()) {
//Currently we set the action manually, but this should be handled by
// addressing module it-self?
String action = getAction(partnerRoleMessageExchange.getOperationName());
if (log.isDebugEnabled()) {
log.debug("Soap action: " + action + " found");
}
operationOptions.setAction(action);
//TODO set replyto as well
//operationOptions.setReplyTo(mctx.getReplyTo());
}
operationOptions.setTo(partnerEndpoint);
if (bindingType instanceof HTTPBinding) {
operationOptions.setProperty(Constants.Configuration.ENABLE_REST,
Constants.VALUE_TRUE);
}
if (messageTraceLog.isDebugEnabled()) {
messageTraceLog.debug("Invoking service: MEXId: " +
partnerRoleMessageExchange.getMessageExchangeId() +
" :: " + serviceName + "." +
partnerRoleMessageExchange.getOperationName());
if (messageTraceLog.isTraceEnabled()) {
messageTraceLog.trace("Request message: MEXId: " +
partnerRoleMessageExchange.getMessageExchangeId() +
" :: " +
partnerInvocationContext.getInMessageContext().
getEnvelope());
}
}
opClient.execute(true);
if (messageTraceLog.isDebugEnabled()) {
messageTraceLog.debug("Service invocation completed: MEXId: " +
partnerRoleMessageExchange.getMessageExchangeId() +
" :: " + serviceName + "." +
partnerRoleMessageExchange.getOperationName());
}
if (isTwoWay) {
final Operation operation = partnerRoleMessageExchange.getOperation();
MessageContext response = opClient.getMessageContext(
WSDLConstants.MESSAGE_LABEL_IN_VALUE);
partnerInvocationContext.setInMessageContext(response);
MessageContext flt = opClient.getMessageContext(
WSDLConstants.MESSAGE_LABEL_FAULT_VALUE);
if (messageTraceLog.isTraceEnabled()) {
messageTraceLog.trace("Response message: MEXId: " +
partnerRoleMessageExchange.getMessageExchangeId() +
" :: " + response.getEnvelope());
}
if (flt != null) {
reply(partnerInvocationContext, partnerRoleMessageExchange, operation,
flt, true);
} else {
reply(partnerInvocationContext, partnerRoleMessageExchange, operation,
response, response.isFault());
}
} else { /* one-way case */
partnerRoleMessageExchange.replyOneWayOk();
}
}
} finally {
// make sure the HTTP connection is released to the pool!
TransportOutDescription out = mctx.getTransportOut();
if (out != null && out.getSender() != null) {
out.getSender().cleanup(mctx);
}
}
} catch (Throwable t) {
String errmsg = Messages.msgErrorSendingMessageToAxisForODEMex(
partnerRoleMessageExchange.toString());
log.error(errmsg, t);
replyWithFailure(partnerRoleMessageExchange,
MessageExchange.FailureType.COMMUNICATION_ERROR, errmsg);
}
}
private UnifiedEndpoint buildUnifiedEndpoint(EndpointConfiguration endpointConfiguration) throws AxisFault {
UnifiedEndpointFactory uepFactory = new UnifiedEndpointFactory();
UnifiedEndpoint partnerEndpoint;
if (endpointConfiguration != null && (endpointConfiguration.getUnifiedEndPoint() != null ||
endpointConfiguration.getUnifiedEndPointReference() != null)) {
if (endpointConfiguration.getUnifiedEndPoint() != null) {
partnerEndpoint = uepFactory.createEndpoint(endpointConfiguration.getUnifiedEndPoint());
} else {
String uepConfPath = endpointConfiguration.getUnifiedEndPointReference();
if (!uepConfPath.startsWith(UnifiedEndpointConstants.VIRTUAL_GOV_REG) ||
!uepConfPath.startsWith(UnifiedEndpointConstants.VIRTUAL_CONF_REG) ||
!uepConfPath.startsWith(UnifiedEndpointConstants.VIRTUAL_REG)) {
if (uepConfPath.startsWith(UnifiedEndpointConstants.VIRTUAL_FILE)) {
uepConfPath = uepConfPath.substring(UnifiedEndpointConstants.VIRTUAL_FILE.
length());
}
if (isAbsoutePath(uepConfPath)) {
uepConfPath = UnifiedEndpointConstants.VIRTUAL_FILE + uepConfPath;
} else {
uepConfPath = getAbsolutePath(endpointConfiguration.getBasePath(), uepConfPath);
}
}
partnerEndpoint = uepFactory.createVirtualEndpoint(uepConfPath);
}
} else {
partnerEndpoint = new UnifiedEndpoint();
partnerEndpoint.setUepId(this.serviceName.getLocalPart());
partnerEndpoint.setAddressingEnabled(true);
partnerEndpoint.setAddressingVersion(UnifiedEndpointConstants.
ADDRESSING_VERSION_FINAL);
}
if (partnerEndpoint.getAddress() == null) {
partnerEndpoint.setAddress(endpointUrl);
}
if (partnerEndpoint.isSecurityEnabled()) {
String secPolicyKey = partnerEndpoint.getWsSecPolicyKey();
if (secPolicyKey.startsWith(UnifiedEndpointConstants.VIRTUAL_FILE)) {
String secPolicyLocation = secPolicyKey.substring(
UnifiedEndpointConstants.VIRTUAL_FILE.length());
if (!isAbsoutePath(secPolicyLocation)) {
secPolicyKey = getAbsolutePath(endpointConfiguration.getBasePath(),
secPolicyLocation);
} else {
secPolicyKey = UnifiedEndpointConstants.VIRTUAL_FILE + secPolicyLocation;
}
partnerEndpoint.setWsSecPolicyKey(secPolicyKey);
}
}
return partnerEndpoint;
}
private String getAbsolutePath(String basePath, String filePath) {
return UnifiedEndpointConstants.VIRTUAL_FILE + basePath + File.separator + filePath;
}
public static boolean isAbsoutePath(String filePath) {
return filePath.startsWith("/") ||
(filePath.length() > 1 && filePath.charAt(1) == ':');
}
private void inferBindingInformation() {
Service serviceDef = wsdlDefinition.getService(serviceName);
if (serviceDef == null) {
throw new NullPointerException(Messages.msgServiceDefinitionNotFound(
serviceName.getLocalPart()));
}
Port port = serviceDef.getPort(portName);
if (port == null) {
throw new NullPointerException(Messages.msgServicePortNotFound(
serviceName.getLocalPart(), portName));
}
binding = port.getBinding();
if (binding == null) {
throw new NullPointerException(Messages.msgBindingNotFound(
serviceName.getLocalPart(), portName));
}
}
private void replyWithFailure(final PartnerRoleMessageExchange odeMex,
final MessageExchange.FailureType error, final String errmsg) {
try {
odeMex.replyWithFailure(error, errmsg, null);
} catch (Exception e) {
String emsg = "Error executing replyWithFailure; reply will be lost.";
log.error(emsg, e);
}
}
private void reply(final BPELMessageContext partnerInvocationContext,
final PartnerRoleMessageExchange odeMex, final Operation operation,
final MessageContext reply, final boolean isFault) {
try {
if (log.isDebugEnabled()) {
log.debug("Received response for MEX " + odeMex);
}
if (isFault) {
Document odeMsg = DOMUtils.newDocument();
Element odeMsgEl = odeMsg.createElementNS(null, "message");
odeMsg.appendChild(odeMsgEl);
Fault fault = SOAPUtils.parseSoapFault(odeMsgEl, reply.getEnvelope(), operation);
if (fault != null) {
if (log.isWarnEnabled()) {
log.warn("Fault response: faultName=" + fault.getName() + " faultType="
+ fault.getMessage().getQName() + "\n"
+ DOMUtils.domToString(odeMsgEl));
}
QName faultType = fault.getMessage().getQName();
QName faultName = new QName(wsdlDefinition.getTargetNamespace(),
fault.getName());
Message response = odeMex.createMessage(faultType);
response.setMessage(odeMsgEl);
odeMex.replyWithFault(faultName, response);
} else {
SOAPFault soapFault = reply.getEnvelope().getBody().getFault();
QName faultType = new QName(wsdlDefinition.getTargetNamespace(),
"UnknownFault");
Message response = odeMex.createMessage(faultType);
Element actAsPart = odeMsgEl.getOwnerDocument().createElementNS(null,
soapFault.getLocalName());
odeMsgEl.appendChild(actAsPart);
if (soapFault.getCode() != null) {
actAsPart.appendChild(odeMsgEl.getOwnerDocument().importNode(
OMUtils.toDOM(soapFault.getCode()), true));
}
if (soapFault.getReason() != null) {
actAsPart.appendChild(odeMsgEl.getOwnerDocument().importNode(
OMUtils.toDOM(soapFault.getReason()), true));
}
if (log.isWarnEnabled()) {
log.warn("Fault response: " + DOMUtils.domToString(odeMsgEl));
}
response.setMessage(odeMsgEl);
odeMex.replyWithFault(faultType, response);
}
} else {
Message response =
SOAPUtils.parseSOAPResponseFromPartner(partnerInvocationContext, odeMex);
if (log.isDebugEnabled()) {
log.debug("Response:\n" + (response.getMessage() != null ?
DOMUtils.domToString(response.getMessage()) : "empty"));
}
odeMex.reply(response);
}
} catch (Exception ex) {
String errmsg = "Unable to process response: " + ex.getMessage();
log.error(errmsg, ex);
odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
}
}
private void replyHTTP(final BPELMessageContext partnerInvocationContext,
final PartnerRoleMessageExchange odeMex, final Operation operation,
final MessageContext reply, final boolean isFault) {
try {
if (log.isDebugEnabled()) {
log.debug("Received response for MEX " + odeMex);
}
if (isFault) {
Document odeMsg = DOMUtils.newDocument();
Element odeMsgEl = odeMsg.createElementNS(null, "message");
odeMsg.appendChild(odeMsgEl);
QName faultType = new QName("http://wso2.org/bps/fault", "HTTPBindingFault");
QName faultName = new QName("http://wso2.org/bps/fault", "RESTPartnerServiceError");
Element fault = odeMsg.createElementNS(null, "fault");
fault.setTextContent("Error returned from REST Partner");
odeMsgEl.appendChild(fault);
Message response = odeMex.createMessage(faultType);
response.setMessage(odeMsgEl);
odeMex.replyWithFault(faultName, response);
} else {
Message response =
SOAPUtils.parseResponseFromRESTService(partnerInvocationContext, odeMex);
if (log.isDebugEnabled()) {
log.debug("Response:\n" + (response.getMessage() != null ?
DOMUtils.domToString(response.getMessage()) : "empty"));
}
odeMex.reply(response);
}
} catch (Exception ex) {
String errmsg = "Unable to process response: " + ex.getMessage();
log.error(errmsg, ex);
odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
}
}
/**
* Extracts endpoint information from ODE message exchange to stuff them into Axis MessageContext.
*/
private void populateWSAddressingOptions(MessageContext ctxt,
PartnerRoleMessageExchange odeMex) {
WSAEndpoint targetWSAEPR = EndpointFactory.convertToWSA(
(MutableEndpoint) odeMex.getEndpointReference());
WSAEndpoint myRoleWSAEPR = EndpointFactory.convertToWSA(
(MutableEndpoint) odeMex.getMyRoleEndpointReference());
WSAEndpoint targetEPR = new WSAEndpoint(targetWSAEPR);
String partnerSessionId = odeMex.getProperty(
MessageExchange.PROPERTY_SEP_PARTNERROLE_SESSIONID);
String myRoleSessionId = odeMex.getProperty(MessageExchange.PROPERTY_SEP_MYROLE_SESSIONID);
if (partnerSessionId != null) {
if (log.isDebugEnabled()) {
log.debug("Partner session identifier found for WSA endpoint: " + partnerSessionId);
}
targetEPR.setSessionId(partnerSessionId);
}
//options.setProperty(ODEService.TARGET_SESSION_ENDPOINT, targetEPR);
if (myRoleWSAEPR != null) { //Asynchronous call??
WSAEndpoint myRoleEPR = new WSAEndpoint(myRoleWSAEPR);
if (myRoleSessionId != null) {
if (log.isDebugEnabled()) {
log.debug("MyRole session identifier found for myrole (callback) WSA endpoint: "
+ myRoleSessionId);
}
myRoleEPR.setSessionId(myRoleSessionId);
}
//options.setProperty(ODEService.CALLBACK_SESSION_ENDPOINT, myRoleEPR);
org.apache.axis2.addressing.EndpointReference replyToEP =
new org.apache.axis2.addressing.EndpointReference();
replyToEP.setAddress(myRoleEPR.getUrl());
ctxt.setReplyTo(replyToEP);
} else {
if (log.isDebugEnabled()) {
log.debug("My-Role EPR not specified, SEP will not be used.");
}
}
String action = getAction(odeMex.getOperationName());
ctxt.setSoapAction(action);
if (MessageExchange.MessageExchangePattern.REQUEST_RESPONSE
== odeMex.getMessageExchangePattern()) {
org.apache.axis2.addressing.EndpointReference annonEpr =
new org.apache.axis2.addressing.EndpointReference(Namespaces.WS_ADDRESSING_ANON_URI);
ctxt.setReplyTo(annonEpr);
ctxt.setMessageID("uuid:" + new UUID().toString());
}
}
private OperationClient getOperationClient(boolean isTwoWay, MessageContext msgCtx)
throws AxisFault {
AxisService anonymousService = AnonymousServiceFactory.getAnonymousService(serviceName,
portName,
axisConfig);
anonymousService.engageModule(axisConfig.getModule("UEPModule"));
anonymousService.getParent().addParameter(
BPELConstants.HIDDEN_SERVICE_PARAM, "true");
ServiceGroupContext sgc = new ServiceGroupContext(
clientConfigCtx, (AxisServiceGroup) anonymousService.getParent());
ServiceContext serviceCtx = sgc.getServiceContext(anonymousService);
// get a reference to the DYNAMIC operation of the Anonymous Axis2 service
AxisOperation axisAnonymousOperation = anonymousService.getOperation(
isTwoWay ? ServiceClient.ANON_OUT_IN_OP : ServiceClient.ANON_OUT_ONLY_OP);
Options clientOptions = cloneOptions(msgCtx.getOptions());
clientOptions.setExceptionToBeThrownOnSOAPFault(false);
/* This value doesn't overrideend point config. */
clientOptions.setTimeOutInMilliSeconds(60000);
return axisAnonymousOperation.createClient(serviceCtx, clientOptions);
}
private Policy loadPolicy(String fileName, String basePath) {
Policy policyDoc = null;
FileLoadingUtil fileLoader = new FileLoadingUtil(basePath);
if (log.isDebugEnabled()) {
log.debug("Applying security policy: " + fileName);
}
try {
InputStream policyStream = fileLoader.load(fileName);
try {
policyDoc = PolicyEngine.getPolicy(policyStream);
} finally {
policyStream.close();
}
} catch (IOException e) {
String errMsg = "Exception while parsing policy: " + fileName;
log.error(errMsg, e);
throw new IllegalArgumentException("Exception while parsing policy: " + fileName, e);
} catch (FileLoadingUtilException e) {
String errMsg = "File Loading Exception";
log.error(errMsg, e);
throw new IllegalArgumentException(errMsg, e);
}
return policyDoc;
}
/**
* Extracts the action to be used for the given operation. It first checks to see
* if a value is specified using WS-Addressing in the portType, it then falls back onto
* getting it from the SOAP Binding.
*
* @param operation the name of the operation to get the Action for
* @return The action value for the specified operation
*/
private String getAction(String operation) {
String action = getWSAInputAction(operation);
if (action == null || "".equals(action)) {
action = getSoapAction(operation);
}
return action;
}
/**
* Attempts to extract the WS-Addressing "Action" attribute value from the operation definition.
* When WS-Addressing is being used by a service provider, the "Action" is specified in the
* portType->operation instead of the SOAP binding->operation.
*
* @param operation The name of the operation to extract the SOAP Action from
* @return the SOAPAction value if one is specified, otherwise empty string
*/
public String getWSAInputAction(String operation) {
BindingOperation bop = binding.getBindingOperation(operation, null, null);
if (bop == null) {
return "";
}
Input input = bop.getOperation().getInput();
if (input != null) {
Object actionQName = input.getExtensionAttribute(new QName(Namespaces.WS_ADDRESSING_NS,
"Action"));
if (actionQName != null && actionQName instanceof QName) {
return ((QName) actionQName).getLocalPart();
}
}
return "";
}
/**
* Attempts to extract the SOAP Action is defined in the WSDL document.
*
* @param operation The name of the operation to extract the SOAP Action from
* @return the SOAPAction value if one is specified, otherwise empty string
*/
public String getSoapAction(String operation) {
BindingOperation bop = binding.getBindingOperation(operation, null, null);
if (bop == null) {
return "";
}
for (SOAPOperation soapOp : CollectionsX.filter(bop.getExtensibilityElements(),
SOAPOperation.class)) {
return soapOp.getSoapActionURI();
}
return "";
}
/**
* Clones the given {@link org.apache.axis2.client.Options} object. This is not a deep copy
* because this will be called for each and every message going out from synapse. The parent
* of the cloning options object is kept as a reference.
*
* @param options clonning object
* @return clonned Options object
*/
public static Options cloneOptions(Options options) {
// create new options object and set the parent
Options clonedOptions = new Options(options.getParent());
// copy general options
clonedOptions.setCallTransportCleanup(options.isCallTransportCleanup());
clonedOptions.setExceptionToBeThrownOnSOAPFault(options.isExceptionToBeThrownOnSOAPFault());
clonedOptions.setManageSession(options.isManageSession());
clonedOptions.setSoapVersionURI(options.getSoapVersionURI());
clonedOptions.setTimeOutInMilliSeconds(options.getTimeOutInMilliSeconds());
clonedOptions.setUseSeparateListener(options.isUseSeparateListener());
// copy transport related options
clonedOptions.setListener(options.getListener());
clonedOptions.setTransportIn(options.getTransportIn());
clonedOptions.setTransportInProtocol(options.getTransportInProtocol());
clonedOptions.setTransportOut(clonedOptions.getTransportOut());
// copy username and password options
clonedOptions.setUserName(options.getUserName());
clonedOptions.setPassword(options.getPassword());
// cloen the property set of the current options object
for (Object o : options.getProperties().keySet()) {
String key = (String) o;
clonedOptions.setProperty(key, options.getProperty(key));
}
return clonedOptions;
}
public EndpointReference getInitialEndpointReference() {
return endpointReference;
}
public void close() {
//Don't we need to implement this method?? pls comment
}
}