/*
* Copyright (c) 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.coordination.module.handlers;
import java.util.Iterator;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.humantask.coordination.module.utils.Constants;
import org.wso2.carbon.humantask.coordination.module.HumanTaskCoordinationException;
import org.wso2.carbon.humantask.coordination.module.utils.SOAPUtils;
import org.wso2.carbon.humantask.coordination.module.utils.ServiceUtils;
import org.wso2.carbon.humantask.coordination.module.internal.HTCoordinationModuleContentHolder;
import org.wso2.carbon.humantask.core.configuration.HumanTaskServerConfiguration;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
/**
* Axis2 Handler Class for handle HumanTaskCoordination Context
*/
public class HTCoordinationContextHandler extends AbstractHandler implements Handler {
private static Log log = LogFactory.getLog(HTCoordinationContextHandler.class);
private static HumanTaskServerConfiguration serverConfig = null;
static {
if(HTCoordinationModuleContentHolder.getInstance().getHtServer() != null){
serverConfig = HTCoordinationModuleContentHolder.getInstance().getHtServer().getServerConfig();
}
}
public HTCoordinationContextHandler() throws HumanTaskCoordinationException {
super();
}
@Override
public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {
if(serverConfig == null || !serverConfig.isTaskRegistrationEnabled())
{
return InvocationResponse.CONTINUE;
}
SOAPHeader soapHeader;
try {
soapHeader = messageContext.getEnvelope().getHeader();
} catch (OMException ex) {
throw new AxisFault("Error while extracting SOAP header", ex);
}
if (soapHeader == null) {
if (log.isDebugEnabled()) {
log.debug("No SOAP Header received. Continuing as an uncoordinated HumanTask.");
}
return InvocationResponse.CONTINUE;
}
Iterator headers = soapHeader.getChildElements();
SOAPHeaderBlock coordinationHeaderBlock = null;
// Searching for WS-Coor Coordination Context
while (headers.hasNext()) {
SOAPHeaderBlock hb = (SOAPHeaderBlock) headers.next();
if (hb.getLocalName().equals(Constants.WS_COOR_COORDINATION_CONTEXT) &&
hb.getNamespace().getNamespaceURI().equals(Constants.WS_COOR_NAMESPACE)) {
coordinationHeaderBlock = hb;
break;
}
}
if (coordinationHeaderBlock == null) {
if (log.isDebugEnabled()) {
log.debug("No coordination context received. Processing as an uncoordinated HumanTask.");
}
return InvocationResponse.CONTINUE;
}
//We have received a ws-coordination context. Now validate it for HT coordination type
String coordinationType = SOAPUtils.getCoordinationType(coordinationHeaderBlock);
if (!Constants.WS_HT_COORDINATION_TYPE.equals(coordinationType)) {
// Found wrong coordination Type. We Only support http://docs.oasis-open.org/ns/bpel4people/ws-humantask/protocol/200803.
// So we cannot allow message to go forward.
String errorMsg = "Message aborted ! Invalid coordination type" + coordinationType +
" . Support only " + Constants.WS_HT_COORDINATION_TYPE;
log.error(errorMsg);
return InvocationResponse.ABORT;
}
if (log.isDebugEnabled()) {
log.debug("HT coordination context received.");
}
String identifier = SOAPUtils.getCoordinationIdentifier(coordinationHeaderBlock);
String registrationService = SOAPUtils.getRegistrationService(coordinationHeaderBlock);
//validating values. These values cannot be empty
if (identifier == null || identifier.isEmpty() || registrationService == null || registrationService.isEmpty()) {
String errorMsg = "Message aborted ! Invalid coordination context parameters.";
log.error(errorMsg);
return InvocationResponse.ABORT;
}
//Service URL of the HumanTask Coordination Protocol Handler AdminService
String humanTaskProtocolHandlerServiceURL;
try {
humanTaskProtocolHandlerServiceURL = ServiceUtils.getTaskProtocolHandlerURL(messageContext.getConfigurationContext());
} catch (HumanTaskCoordinationException e) {
String errorMsg = "Error while generating HumanTask engine's protocol Handler Service URL.";
log.error(errorMsg);
throw new AxisFault(e.getLocalizedMessage(), e);
}
// We are OK to invokeRegistrationService Registration service
try {
OMElement response = invokeRegistrationServiceUsingServiceClient(identifier, humanTaskProtocolHandlerServiceURL, registrationService);
// We just discard registration response, since we are using CallBack service as TaskParent's Protocol Handler.
// But we are validating it for successful completion.
if (!SOAPUtils.validateResponse(response, identifier)) {
String errorMsg = "Message aborted ! registration response validation failed.";
log.error(errorMsg);
return InvocationResponse.ABORT;
}
//successful coordination
if (log.isDebugEnabled()) {
log.debug("RegistrationResponse received. Task is successfully coordinated with Task parent.");
}
} catch (AxisFault e) {
String errorMsg = "Error while invoking registration service";
log.error(errorMsg);
throw new AxisFault(e.getLocalizedMessage(), e);
}
return InvocationResponse.CONTINUE;
}
@Override
public String getName() {
return "HumanTask Coordination Protocol Handler";
}
private OMElement invokeRegistrationServiceUsingServiceClient(String identifier, String taskProtocolHandlerServiceURL, String registrationService) throws AxisFault{
OMElement payload = SOAPUtils.getRegistrationPayload(identifier, taskProtocolHandlerServiceURL);
Options options = new Options();
options.setTo(new EndpointReference(registrationService)); // this sets the location of registration service
options.setAction(Constants.WS_COOR_REGISTERATION_ACTION);
options.setTransportInProtocol(org.apache.axis2.Constants.TRANSPORT_HTTPS);
ServiceClient serviceClient = new ServiceClient();
serviceClient.setOptions(options);
//Setting basic auth headers. Reading those information using HT server config.
String tenantDomain = MultitenantUtils.getTenantDomainFromUrl(registrationService);
if (registrationService.equals(tenantDomain)) {
//this is a Super tenant registration service
CarbonUtils.setBasicAccessSecurityHeaders(serverConfig.getRegistrationServiceAuthUsername(), serverConfig.getRegistrationServiceAuthPassword(), serviceClient);
} else {
if (log.isDebugEnabled()) {
log.debug("Sending ws-coor Registration request to tenant domain: " + tenantDomain);
}
// Tenant's registration service
CarbonUtils.setBasicAccessSecurityHeaders(
serverConfig.getRegistrationServiceAuthUsername() + "@" + tenantDomain,
serverConfig.getRegistrationServiceAuthPassword(),
serviceClient);
}
return serviceClient.sendReceive(payload);
}
private OMElement invokeRegistrationService(String identifier, String taskProtocolHandlerServiceURL, String registrationService) throws AxisFault {
OMElement payload = SOAPUtils.getRegistrationPayload(identifier, taskProtocolHandlerServiceURL);
SOAPFactory soap11Factory = OMAbstractFactory.getSOAP11Factory();
MessageContext mctx = new MessageContext();
if (mctx.getEnvelope() == null) {
mctx.setEnvelope(soap11Factory.createSOAPEnvelope());
}
if (mctx.getEnvelope().getBody() == null) {
soap11Factory.createSOAPBody(mctx.getEnvelope());
}
if (mctx.getEnvelope().getHeader() == null) {
soap11Factory.createSOAPHeader(mctx.getEnvelope());
}
mctx.getEnvelope().getBody().addChild(payload);
// //Setting basic auth headers. Reading those information using HT server config.
// HumanTaskServerConfiguration serverConfig = HTCoordinationModuleContentHolder.getInstance().getHtServer().getServerConfig();
// String tenantDomain = MultitenantUtils.getTenantDomainFromUrl(registrationService);
// if (registrationService.equals(tenantDomain)) {
// //this is a Super tenant registration service
// if (log.isDebugEnabled()) {
// log.debug("Sending Username" + serverConfig.getRegistrationServiceAuthUsername() + " - " + serverConfig.getRegistrationServiceAuthPassword()); //TODO REMOVE this
// }
// CarbonUtils.setBasicAccessSecurityHeaders(serverConfig.getRegistrationServiceAuthUsername(), serverConfig.getRegistrationServiceAuthPassword(), true, mctx);
// } else {
// if (log.isDebugEnabled()) {
// log.debug("Sending ws-coor Registration request to tenant domain: " + tenantDomain);
// }
// // Tenant's registration service
//
// String username = serverConfig.getRegistrationServiceAuthUsername() + "@" + tenantDomain;
// String pass = serverConfig.getRegistrationServiceAuthPassword();
// if (log.isDebugEnabled()) {
// log.debug("Sending Username" + username + " - " + pass); //TODO REMOVE this
// }
// CarbonUtils.setBasicAccessSecurityHeaders(
// username,
// pass,
// true,
// mctx);
// }
MessageContext responseMsgContext = ServiceUtils.invokeRegistrationService(mctx, registrationService);
if (responseMsgContext.getEnvelope() != null) {
if (responseMsgContext.getEnvelope().getBody() != null) {
return responseMsgContext.getEnvelope().getBody();
}
}
return null;
}
}