/*
* Copyright (c) 2012, 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.humantask.core.integration;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.bpel.common.SOAPHelper;
import org.wso2.carbon.bpel.common.config.EndpointConfiguration;
import org.wso2.carbon.humantask.core.CallBackService;
import org.wso2.carbon.humantask.core.HumanTaskConstants;
import org.wso2.carbon.humantask.core.deployment.HumanTaskDeploymentException;
import org.wso2.carbon.humantask.core.integration.utils.AxisServiceUtils;
import org.wso2.carbon.humantask.core.integration.utils.SOAPUtils;
import org.wso2.carbon.humantask.core.integration.utils.ServiceInvocationContext;
import org.wso2.carbon.humantask.core.internal.HumanTaskServiceComponent;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpoint;
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.SOAPBinding;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.xml.namespace.QName;
import org.wso2.carbon.utils.CarbonUtils;
import java.util.List;
/**
* Axis based implementation of CallBackService interface
*/
public class CallBackServiceImpl implements CallBackService {
private static Log log = LogFactory.getLog(CallBackServiceImpl.class);
private UnifiedEndpoint uep;
private int tenantId;
private QName serviceName;
private String portName;
private QName taskName;
private Binding binding;
private String operation;
public CallBackServiceImpl(int tenantId, QName serviceName, String portName, QName taskName,
Definition wsdl, String operation,
EndpointConfiguration endpointConfig)
throws HumanTaskDeploymentException {
this.tenantId = tenantId;
this.serviceName = serviceName;
this.portName = portName;
this.taskName = taskName;
this.operation = operation;
inferBindingInformation(wsdl);
if (endpointConfig != null) {
try {
uep = endpointConfig.getUnifiedEndpoint();
} catch (AxisFault axisFault) {
String errMsg = "Error occurred while reading unified endpoint for callback " +
"service: " + serviceName + " of port: " + portName;
log.error(errMsg, axisFault);
throw new HumanTaskDeploymentException(errMsg, axisFault);
}
} else {
uep = new UnifiedEndpoint();
uep.setUepId(this.serviceName.getLocalPart());
uep.setAddressingEnabled(true);
uep.setAddressingVersion(UnifiedEndpointConstants.ADDRESSING_VERSION_FINAL);
uep.setAddress(CarbonUtils.resolveSystemProperty(
AxisServiceUtils.getEPRfromWSDL(wsdl, serviceName, portName)));
}
}
@Override
public void invoke(OMElement payload, long taskId) throws AxisFault {
final MessageContext mctx = new MessageContext();
ServiceInvocationContext invocationContext = new ServiceInvocationContext();
invocationContext.setInMessageContext(mctx);
invocationContext.setUep(uep);
invocationContext.setService(serviceName);
invocationContext.setPort(portName);
invocationContext.setCaller(taskName.getLocalPart());
invocationContext.setWsdlBindingForCurrentMessageFlow(binding);
invocationContext.setOperationName(operation);
if (mctx.getEnvelope() == null) {
mctx.setEnvelope(getSoapFactory().createSOAPEnvelope());
}
if (mctx.getEnvelope().getBody() == null) {
getSoapFactory().createSOAPBody(mctx.getEnvelope());
}
if (mctx.getEnvelope().getHeader() == null) {
getSoapFactory().createSOAPHeader(mctx.getEnvelope());
}
mctx.getEnvelope().getBody().addChild(payload);
OMNamespace ns = OMAbstractFactory.getSOAP11Factory().createOMNamespace(HumanTaskConstants.B4P_NAMESPACE, "b4p");
SOAPHeaderBlock header = mctx.getEnvelope().getHeader().addHeaderBlock(HumanTaskConstants.B4P_CORRELATION_HEADER, ns);
header.addAttribute(HumanTaskConstants.B4P_CORRELATION_HEADER_ATTRIBUTE, Long.toString(taskId), ns);
AxisServiceUtils.invokeService(invocationContext,
HumanTaskServiceComponent.getHumanTaskServer().getTaskStoreManager().
getHumanTaskStore(tenantId).getConfigContext());
}
@Override
public void invokeSkip(long taskID) throws AxisFault {
sendProtocolMessage( taskID, HumanTaskConstants.HT_PROTOCOL_SKIPPED, String.valueOf(taskID));
}
@Override
public void invokeFault(long taskID, String faultMessage) throws AxisFault {
sendProtocolMessage( taskID, HumanTaskConstants.HT_PROTOCOL_FAULT,faultMessage);
}
private void sendProtocolMessage(long taskID, String headerValue,String value) throws AxisFault
{
final MessageContext mctx = new MessageContext();
ServiceInvocationContext invocationContext = new ServiceInvocationContext();
invocationContext.setInMessageContext(mctx);
invocationContext.setUep(uep);
invocationContext.setService(serviceName);
invocationContext.setPort(portName);
invocationContext.setCaller(taskName.getLocalPart());
invocationContext.setWsdlBindingForCurrentMessageFlow(binding);
invocationContext.setOperationName(operation);
if (mctx.getEnvelope() == null) {
mctx.setEnvelope(getSoapFactory().createSOAPEnvelope());
}
if (mctx.getEnvelope().getBody() == null) {
getSoapFactory().createSOAPBody(mctx.getEnvelope());
}
if (mctx.getEnvelope().getHeader() == null) {
getSoapFactory().createSOAPHeader(mctx.getEnvelope());
}
//Creating Dummy Element
// Extracting MessageName
List bindingOperations = binding.getBindingOperations();
String messageName = "";
OMNamespace serviceNS = null;
BindingOperation oper;
for (int i = 0; i < bindingOperations.size(); i++) {
oper = (BindingOperation) bindingOperations.get(i);
if (operation.equals(oper.getName())) {
Message message = oper.getOperation().getInput().getMessage();
messageName = message.getQName().getLocalPart();
for (Object ob : message.getParts().keySet()) { // Here we don't support RPC messages.
Part part = (Part) message.getParts().get(ob);
serviceNS = OMAbstractFactory.getSOAP11Factory().createOMNamespace(
part.getElementName().getNamespaceURI(), part.getElementName().getPrefix());
break;
}
break;
}
}
OMElement payload = OMAbstractFactory.getOMFactory().createOMElement(messageName,serviceNS);
mctx.getEnvelope().getBody().addChild(payload);
OMNamespace htpNS = OMAbstractFactory.getSOAP11Factory().createOMNamespace(HumanTaskConstants.HT_PROTOCOL_NAMESPACE, HumanTaskConstants.HT_PROTOCOL_DEFAULT_PREFIX );
SOAPHeaderBlock protocolHeader = mctx.getEnvelope().getHeader().addHeaderBlock(headerValue, htpNS);
protocolHeader.setText(value);
protocolHeader.addAttribute(HumanTaskConstants.B4P_CORRELATION_HEADER_ATTRIBUTE, Long.toString(taskID), htpNS);
OMNamespace b4pNS = OMAbstractFactory.getSOAP11Factory().createOMNamespace(HumanTaskConstants.B4P_NAMESPACE, "b4p");
SOAPHeaderBlock header = mctx.getEnvelope().getHeader().addHeaderBlock(HumanTaskConstants.B4P_CORRELATION_HEADER, b4pNS);
header.addAttribute(HumanTaskConstants.B4P_CORRELATION_HEADER_ATTRIBUTE, Long.toString(taskID), b4pNS);
AxisServiceUtils.invokeService(invocationContext,
HumanTaskServiceComponent.getHumanTaskServer().getTaskStoreManager().
getHumanTaskStore(tenantId).getConfigContext());
}
private void inferBindingInformation(Definition wsdlDefinition)
throws HumanTaskDeploymentException {
Service serviceDef = wsdlDefinition.getService(serviceName);
if (serviceDef == null) {
throw new HumanTaskDeploymentException("Service element not found for callback service wsdl: " +
serviceName);
}
Port port = serviceDef.getPort(portName);
if (port == null) {
throw new HumanTaskDeploymentException("Port: " + portName + " not found for Service: " +
serviceName + " in the callback service wsdl");
}
binding = port.getBinding();
if (binding == null) {
throw new HumanTaskDeploymentException("Binding not found for port: " + portName +
" and Service: " + serviceName + " in the callback service wsdl");
}
}
public SOAPFactory getSoapFactory() throws AxisFault {
ExtensibilityElement bindingType = SOAPHelper.getBindingExtension(binding);
if (!(bindingType instanceof SOAPBinding || bindingType instanceof SOAP12Binding ||
bindingType instanceof HTTPBinding)) {
throw new AxisFault("Service binding is not supported for service " + serviceName);
}
if (bindingType instanceof SOAPBinding) {
return OMAbstractFactory.getSOAP11Factory();
} else {
return OMAbstractFactory.getSOAP12Factory();
}
}
}