org.wso2.carbon.identity.workflow.impl.WorkflowImplServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.workflow.impl.WorkflowImplServiceImpl.java

Source

/*
 * Copyright (c) 2015, 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.identity.workflow.impl;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.llom.OMElementImpl;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.bpel.stub.mgt.PackageManagementException;
import org.wso2.carbon.bpel.stub.mgt.ProcessManagementException;
import org.wso2.carbon.bpel.stub.mgt.types.DeployedPackagesPaginated;
import org.wso2.carbon.bpel.stub.mgt.types.PackageType;
import org.wso2.carbon.bpel.stub.mgt.types.Version_type0;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.humantask.stub.types.TSimpleQueryCategory;
import org.wso2.carbon.humantask.stub.types.TSimpleQueryInput;
import org.wso2.carbon.humantask.stub.types.TStatus;
import org.wso2.carbon.humantask.stub.types.TTaskSimpleQueryResultRow;
import org.wso2.carbon.humantask.stub.types.TTaskSimpleQueryResultSet;
import org.wso2.carbon.humantask.stub.ui.task.client.api.IllegalAccessFault;
import org.wso2.carbon.humantask.stub.ui.task.client.api.IllegalArgumentFault;
import org.wso2.carbon.humantask.stub.ui.task.client.api.IllegalOperationFault;
import org.wso2.carbon.humantask.stub.ui.task.client.api.IllegalStateFault;
import org.wso2.carbon.identity.workflow.impl.bean.BPSProfile;
import org.wso2.carbon.identity.workflow.impl.dao.BPSProfileDAO;
import org.wso2.carbon.identity.workflow.impl.internal.WorkflowImplServiceDataHolder;
import org.wso2.carbon.identity.workflow.impl.listener.WorkflowImplServiceListener;
import org.wso2.carbon.identity.workflow.impl.util.BPELPackageManagementServiceClient;
import org.wso2.carbon.identity.workflow.impl.util.HumanTaskClientAPIAdminClient;
import org.wso2.carbon.identity.workflow.impl.util.ProcessManagementServiceClient;
import org.wso2.carbon.identity.workflow.mgt.WorkflowManagementService;
import org.wso2.carbon.identity.workflow.mgt.bean.Parameter;
import org.wso2.carbon.identity.workflow.mgt.bean.Workflow;
import org.wso2.carbon.identity.workflow.mgt.bean.WorkflowRequest;
import org.wso2.carbon.identity.workflow.mgt.exception.WorkflowException;
import org.wso2.carbon.identity.workflow.mgt.util.WFConstant;
import org.wso2.carbon.identity.workflow.mgt.util.WorkflowManagementUtil;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.List;

public class WorkflowImplServiceImpl implements WorkflowImplService {

    private static final Log log = LogFactory.getLog(WorkflowImplServiceImpl.class);

    BPSProfileDAO bpsProfileDAO = new BPSProfileDAO();

    @Override
    public void addBPSProfile(BPSProfile bpsProfileDTO, int tenantId) throws WorkflowImplException {

        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreAddBPSProfile(bpsProfileDTO, tenantId);
            }

        }
        bpsProfileDAO.addProfile(bpsProfileDTO, tenantId);
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostAddBPSProfile(bpsProfileDTO, tenantId);
            }
        }

    }

    @Override
    public List<BPSProfile> listBPSProfiles(int tenantId) throws WorkflowImplException {

        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreListBPSProfiles(tenantId);
            }
        }
        List<BPSProfile> bpsProfiles = bpsProfileDAO.listBPSProfiles(tenantId);
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostListBPSProfiles(tenantId, bpsProfiles);
            }
        }

        return bpsProfiles;
    }

    @Override
    public void removeBPSProfile(String profileName) throws WorkflowImplException {

        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreRemoveBPSProfile(profileName);
            }
        }
        bpsProfileDAO.removeBPSProfile(profileName);
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostRemoveBPSProfile(profileName);
            }
        }

    }

    @Override
    public BPSProfile getBPSProfile(String profileName, int tenantId) throws WorkflowImplException {

        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreGetBPSProfile(profileName, tenantId);
            }
        }
        BPSProfile bpsProfile = bpsProfileDAO.getBPSProfile(profileName, tenantId, true);
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostGetBPSProfile(profileName, tenantId, bpsProfile);
            }
        }
        return bpsProfile;
    }

    @Override
    public void updateBPSProfile(BPSProfile bpsProfileDTO, int tenantId) throws WorkflowImplException {

        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreUpdateBPSProfile(bpsProfileDTO, tenantId);
            }
        }
        BPSProfile currentBpsProfile = bpsProfileDAO.getBPSProfile(bpsProfileDTO.getProfileName(), tenantId, true);
        if (ArrayUtils.isEmpty(bpsProfileDTO.getPassword())) {
            bpsProfileDTO.setPassword(currentBpsProfile.getPassword());
        }
        bpsProfileDAO.updateProfile(bpsProfileDTO, tenantId);
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostUpdateBPSProfile(bpsProfileDTO, tenantId);
            }
        }
    }

    @Override
    public void deleteHumanTask(WorkflowRequest workflowRequest) throws WorkflowImplException {
        BPSProfileDAO bpsProfileDAO = new BPSProfileDAO();
        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();

        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreDeleteHumanTask(workflowRequest);
            }
        }
        int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
        List<BPSProfile> bpsProfiles = bpsProfileDAO.listBPSProfiles(tenantId);
        HumanTaskClientAPIAdminClient client = null;
        TSimpleQueryInput input = new TSimpleQueryInput();
        TStatus reservedState = new TStatus();
        reservedState.setTStatus(WFImplConstant.HT_STATE_RESERVED);
        input.addStatus(reservedState);
        TStatus readyState = new TStatus();
        readyState.setTStatus(WFImplConstant.HT_STATE_READY);
        input.addStatus(readyState);
        input.setPageSize(WFImplConstant.DEFAULT_PAGE_SIZE_FOR_HT_LIST);
        input.setPageNumber(WFImplConstant.PAGE_0);
        input.setSimpleQueryCategory(TSimpleQueryCategory.ALL_TASKS);
        for (BPSProfile bpsProfile : bpsProfiles) {
            try {
                String host = bpsProfile.getWorkerHostURL();

                if (bpsProfile.getProfileName().equals(WFImplConstant.DEFAULT_BPS_PROFILE_NAME)) {

                    client = new HumanTaskClientAPIAdminClient(host, bpsProfile.getUsername());
                } else {
                    client = new HumanTaskClientAPIAdminClient(host, bpsProfile.getUsername(),
                            bpsProfile.getPassword());
                }
                TTaskSimpleQueryResultSet results = client.simpleQuery(input);
                TTaskSimpleQueryResultRow[] humanTasks = results.getRow();
                if (ArrayUtils.isNotEmpty(humanTasks)) {
                    for (int j = 0; j < humanTasks.length; j++) {
                        try {
                            Object task = client.getInput(humanTasks[j].getId());
                            InputStream stream = new ByteArrayInputStream(
                                    task.toString().getBytes(StandardCharsets.UTF_8));
                            OMElement taskXML = new StAXOMBuilder(stream).getDocumentElement();
                            Iterator<OMElementImpl> iterator = taskXML.getChildElements();
                            while (iterator.hasNext()) {
                                OMElementImpl child = iterator.next();
                                checkMatchingTaskAndDelete(workflowRequest.getRequestId(), client, humanTasks, j,
                                        child);
                            }
                        } catch (IllegalStateFault | XMLStreamException | IllegalArgumentFault | RemoteException
                                | IllegalOperationFault | IllegalAccessFault e) {
                            //If exception throws when retrieving and deleting a specific task, it will continue with
                            // other tasks without terminating.
                            log.warn("Failed to retrieve information of human task : " + humanTasks[j].getName()
                                    + ".");
                        }
                    }
                }
            } catch (IllegalArgumentFault | RemoteException | IllegalStateFault e) {
                //If exception throws at one iteration of loop, which is testing 1 BPS profile, it will continue with
                // other profiles without terminating.
                log.warn("Failed to delete human task associated for this request in BPS profile : "
                        + bpsProfile.getProfileName());
            }
        }
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostDeleteHumanTask(workflowRequest);
            }
        }
    }

    /**
     * This method is used to remove the BPS Artifacts upon a deletion of
     * a Workflow.
     *
     * @param workflow - Workflow request to be deleted.
     * @throws WorkflowImplException
     */

    @Override
    public void removeBPSPackage(Workflow workflow) throws WorkflowImplException {

        List<WorkflowImplServiceListener> workflowListenerList = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowListenerList();
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPreRemoveBPSPackage(workflow);
            }
        }
        WorkflowImplService workflowImplService = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowImplService();
        WorkflowManagementService workflowManagementService = WorkflowImplServiceDataHolder.getInstance()
                .getWorkflowManagementService();

        if (workflowImplService == null || workflowManagementService == null) {
            throw new WorkflowImplException(
                    "Error while deleting the BPS artifacts of: " + workflow.getWorkflowName());
        }

        try {
            List<Parameter> workflowParameters = workflowManagementService
                    .getWorkflowParameters(workflow.getWorkflowId());
            Parameter bpsParameter = WorkflowManagementUtil.getParameter(workflowParameters,
                    WFImplConstant.ParameterName.BPS_PROFILE, WFConstant.ParameterHolder.WORKFLOW_IMPL);
            if (bpsParameter == null) {
                throw new WorkflowImplException(
                        "Error while deleting the BPS artifacts of: " + workflow.getWorkflowName());
            }
            String bpsProfileName = bpsParameter.getParamValue();
            if (StringUtils.isEmpty(bpsProfileName)) {
                throw new WorkflowImplException(
                        "Error while deleting the BPS artifacts of: " + workflow.getWorkflowName());
            }

            int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
            BPSProfile bpsProfile = workflowImplService.getBPSProfile(bpsProfileName, tenantId);

            if (log.isDebugEnabled()) {
                log.debug("Removing BPS Artifacts of " + bpsProfileName + " " + "for Tenant ID : " + tenantId);
            }

            BPELPackageManagementServiceClient bpsPackageClient;
            ProcessManagementServiceClient bpsProcessClient;

            //Authorizing BPS Package Management & BPS Process Management Stubs.
            String host = bpsProfile.getManagerHostURL();
            if (bpsProfileName.equals(WFImplConstant.DEFAULT_BPS_PROFILE_NAME)) {
                //If emebeded_bps, use mutual ssl authentication
                bpsPackageClient = new BPELPackageManagementServiceClient(host, bpsProfile.getUsername());
                bpsProcessClient = new ProcessManagementServiceClient(host, bpsProfile.getUsername());
            } else {
                //For external BPS profiles, use password authentication
                bpsPackageClient = new BPELPackageManagementServiceClient(host, bpsProfile.getUsername(),
                        bpsProfile.getPassword());
                bpsProcessClient = new ProcessManagementServiceClient(host, bpsProfile.getUsername(),
                        bpsProfile.getPassword());
            }

            DeployedPackagesPaginated deployedPackagesPaginated = bpsPackageClient.listDeployedPackagesPaginated(0,
                    workflow.getWorkflowName());
            PackageType[] packageTypes = deployedPackagesPaginated.get_package();
            if (packageTypes == null || packageTypes.length == 0) {
                throw new WorkflowImplException(
                        "Error while deleting the BPS artifacts of: " + workflow.getWorkflowName());
            }
            int numberOfPackages = packageTypes.length;
            for (int i = 0; i < numberOfPackages; i++) {
                PackageType packageType = deployedPackagesPaginated.get_package()[i];
                int numberOfVersions = packageType.getVersions().getVersion().length;
                //Iterating through BPS Packages deployed for the Workflow and retires each associated active processes.
                for (int j = 0; j < numberOfVersions; j++) {
                    Version_type0 versionType = packageType.getVersions().getVersion()[j];
                    if (versionType.getIsLatest()) {
                        int numberOfProcesses = versionType.getProcesses().getProcess().length;
                        if (numberOfProcesses == 0) {
                            throw new WorkflowImplException(
                                    "Error while deleting the BPS artifacts of: " + workflow.getWorkflowName());
                        }
                        for (int k = 0; k < numberOfProcesses; k++) {
                            QName pid = null;
                            try {
                                String processStatus = versionType.getProcesses().getProcess()[k].getStatus()
                                        .getValue();
                                if (StringUtils.equals(processStatus, WFImplConstant.BPS_STATUS_ACTIVE)) {
                                    String processID = versionType.getProcesses().getProcess()[k].getPid();
                                    pid = QName.valueOf(processID);
                                    bpsProcessClient.retireProcess(pid);
                                }
                            } catch (RemoteException | ProcessManagementException e) {
                                //If exception throws at retiring one process, it will continue with
                                // other processes without terminating.
                                log.info("Failed to retire BPS process : " + pid);
                            }
                        }
                    }
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("BPS Artifacts Successfully removed for Workflow : " + workflow.getWorkflowName());
            }

        } catch (WorkflowException | PackageManagementException | RemoteException e) {
            throw new WorkflowImplException(
                    "Error while deleting the BPS Artifacts of the Workflow " + workflow.getWorkflowName(), e);
        }
        for (WorkflowImplServiceListener workflowListener : workflowListenerList) {
            if (workflowListener.isEnable()) {
                workflowListener.doPostRemoveBPSPackage(workflow);
            }
        }

    }

    /*
     *
     *
     * @param requestId Id of the deleting request
     * @param stub stub to call HumanTaskClientAPIAdmin
     * @param resultsList task list in the current human task engine
     * @param resultIndex index of the currently considering rask
     * @param taskElement currently considering task
     * @throws RemoteException
     */

    private void checkMatchingTaskAndDelete(String requestId, HumanTaskClientAPIAdminClient client,
            TTaskSimpleQueryResultRow[] resultsList, int resultIndex, OMElementImpl taskElement)
            throws RemoteException, IllegalStateFault, IllegalOperationFault, IllegalArgumentFault,
            IllegalAccessFault {

        if (taskElement.getLocalName().equals(WFImplConstant.HT_PARAMETER_LIST_ELEMENT)) {
            Iterator<OMElementImpl> parameters = taskElement.getChildElements();
            while (parameters.hasNext()) {
                OMElementImpl parameter = parameters.next();
                Iterator<OMAttribute> attributes = parameter.getAllAttributes();
                while (attributes.hasNext()) {
                    OMAttribute currentAttribute = attributes.next();
                    if (currentAttribute.getLocalName().equals(WFImplConstant.HT_ITEM_NAME_ATTRIBUTE)
                            && currentAttribute.getAttributeValue()
                                    .equals(WFImplConstant.HT_REQUEST_ID_ATTRIBUTE_VALUE)) {
                        Iterator<OMElementImpl> itemValues = parameter.getChildElements();
                        if (itemValues.hasNext()) {
                            String taskRequestId = itemValues.next().getText();
                            if (taskRequestId.contains(",")) {
                                taskRequestId = taskRequestId.replaceAll(",", "");
                            }
                            if (taskRequestId.equals(requestId)) {
                                client.skip(resultsList[resultIndex].getId());
                            }
                        }

                    }
                }
            }
        }

    }

}