All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.workflow.event.EventPublishUtil Maven / Gradle / Ivy

/*
 * Copyright 1997-2008 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.workflow.event;

import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.Workflow;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.job.AbsoluteTimeoutHandler;
import com.day.cq.workflow.job.ExternalProcessJob;
import com.day.cq.workflow.job.TimeoutJob;
import com.day.cq.workflow.job.WorkflowJob;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.event.EventAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import javax.jcr.RepositoryException;

import static com.day.cq.workflow.event.WorkflowEvent.DELEGATEE;
import static com.day.cq.workflow.event.WorkflowEvent.EVENT_TYPE;
import static com.day.cq.workflow.event.WorkflowEvent.FROM_NODE_NAME;
import static com.day.cq.workflow.event.WorkflowEvent.JOB_FAILED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.MODEL_DELETED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.MODEL_DEPLOYED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.NODE_TRANSITION_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.PROCESS_TIMEOUT_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.RESOURCE_COLLECTION_MODIFIED;
import static com.day.cq.workflow.event.WorkflowEvent.TIME_STAMP;
import static com.day.cq.workflow.event.WorkflowEvent.TO_NODE_NAME;
import static com.day.cq.workflow.event.WorkflowEvent.USER;
import static com.day.cq.workflow.event.WorkflowEvent.VARIABLE_NAME;
import static com.day.cq.workflow.event.WorkflowEvent.VARIABLE_UPDATE_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.VARIABLE_VALUE;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_ABORTED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_COMPLETED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_INSTANCE_ID;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_NAME;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_NODE;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_RESUMED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_STARTED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_SUSPENDED_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.WORKFLOW_VERSION;
import static com.day.cq.workflow.event.WorkflowEvent.WORKITEM_DELEGATION_EVENT;
import static com.day.cq.workflow.event.WorkflowEvent.WORK_DATA;
import static com.day.cq.workflow.event.WorkflowEvent.WORK_ITEM;

/**
 * The EventsPublisher provides a utility for publishing workflow
 * related events.
 */
public class EventPublishUtil {
    /**
     * Logger instance for this class.
     */
    private static final Logger log = LoggerFactory.getLogger(EventPublishUtil.class);

    /**
     * The OSGI event admin used for sending events
     */
    private EventAdmin eventAdmin;

    public EventPublishUtil(EventAdmin eventAdmin) {
        this.eventAdmin = eventAdmin;
    }

    /**
     * Notifies all registered listeners about an event.
     *
     * @param props event properties
     */
    private void sendEvent(Dictionary props) {
        log.debug("Sending workflow event of type " + props.get(EVENT_TYPE)
                + ((props.get(WORKFLOW_INSTANCE_ID) != null) ? " for " + props.get(WORKFLOW_INSTANCE_ID) : ""));
        eventAdmin.sendEvent(new WorkflowEvent(props));
    }

    public void publishModelDeployedEvent(String id, String version, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, MODEL_DEPLOYED_EVENT);
        properties.put(WORKFLOW_NAME, id);
        if (version != null) {
            properties.put(WORKFLOW_VERSION, version);
        } else {
            log.warn("No version specified"); // TODO: make sure that version
            // is specified...
        }
        sendEvent(properties);
    }

    public void publishModelDeletedEvent(String id, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, MODEL_DELETED_EVENT);
        properties.put(WORKFLOW_NAME, id);
        sendEvent(properties);
    }

    public void publishWorkflowStartedEvent(Workflow instance, Workflow parentWorkflow, String user, WorkflowData data) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, WORKFLOW_STARTED_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());
        // properties.put(PARENT_WORKFLOW_ID, parentWorkflow.getId());
        properties.put(WORK_DATA, data);

        sendEvent(properties);
    }

    public void publishWorkflowAbortedEvent(Workflow instance, String userId) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, userId);
        properties.put(EVENT_TYPE, WORKFLOW_ABORTED_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());

        sendEvent(properties);
    }

    public void publishWorkflowSuspendedEvent(Workflow instance, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, WORKFLOW_SUSPENDED_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());

        sendEvent(properties);
    }

    public void publishWorkflowResumedEvent(Workflow instance, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, WORKFLOW_RESUMED_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());

        sendEvent(properties);
    }

    public void publishWorkflowCompletedEvent(Workflow instance, String user) throws WorkflowException {

        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, WORKFLOW_COMPLETED_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());

        sendEvent(properties);
    }

    public void publishNodeTransitionEvent(Workflow instance, String fromNodeName, String toNodeName,
                                           WorkItem workitem, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, NODE_TRANSITION_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());
        properties.put(FROM_NODE_NAME, fromNodeName);
        properties.put(TO_NODE_NAME, toNodeName);
        properties.put(WORK_ITEM, workitem);

        sendEvent(properties);
    }

    public void publishVariableUpdatedEvent(Workflow instance, String variableName, Object variableValue, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, VARIABLE_UPDATE_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());
        properties.put(VARIABLE_NAME, variableName);
        properties.put(VARIABLE_VALUE, variableValue);

        sendEvent(properties);
    }

    public void publishProcessTimeoutEvent(Workflow instance, String processName) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(EVENT_TYPE, PROCESS_TIMEOUT_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());

        sendEvent(properties);
    }

    public void publishJobEvent(Map workItemMap, Integer retryCount, int numOfParallelProcs, String jobId) {
        WorkflowJob job = new WorkflowJob(workItemMap);
        eventAdmin.postEvent(job.createJobEvent(retryCount, numOfParallelProcs, jobId));
    }

    public void publishExternalProcessJobEvent(Map workItemMap, Integer retryCount, String jobId) {
        ExternalProcessJob job = new ExternalProcessJob(workItemMap);
        eventAdmin.postEvent(job.createJobEvent(retryCount, jobId));
    }

    public void publishJobFailedEvent(WorkItem item, String message) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(EVENT_TYPE, JOB_FAILED_EVENT);
        properties.put(WORKFLOW_NODE, item.getNode().getId());
        properties.put(WORKFLOW_NAME, item.getWorkflow().getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, item.getWorkflow().getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, item.getWorkflow().getId());

        sendEvent(properties);
    }

    public void publishTimeoutEvent(WorkItem item, WorkflowSession session) {
        log.debug("entering publishTimeoutEvent..");
        String handler = null;
        Long timeout = null;
        boolean addOffset = true;

        Iterator keys = item.getNode().getMetaDataMap().keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            if (key.equals("timeoutHandler")) {
                handler = item.getNode().getMetaDataMap().get("timeoutHandler", String.class);
            } else if (key.equals("timeoutMillis")) {
                timeout = item.getNode().getMetaDataMap().get("timeoutMillis", Long.class);
            }
        }

        // check for absolute timeout handler
        AbsoluteTimeoutHandler handlerImpl = handler != null ? getHandler(handler, session) : null;
        if (handlerImpl != null) {
            timeout = handlerImpl.getTimeoutDate(item);
            if (timeout > 0) {
                timeout = timeout / 1000; // convert into seconds
                addOffset = false;
                log.debug("publishTimeoutEvent: Using AbsoluteTimeoutHandler. Timeout is: " + timeout + "s");
            } else {
                log.debug("publishTimeoutEvent: no time set");
                timeout = null;
            }
        }

        if ((handler != null) && (timeout != null)) {
            TimeoutJob job = new TimeoutJob(item, handler);
            eventAdmin.postEvent(job.createEvent(true, timeout, addOffset));
        }
    }

    public void publishResetTimeoutEvent(WorkItem item) {
        String handler = null;
        Iterator iter = item.getNode().getMetaDataMap().keySet().iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            if (key.equals("timeoutHandler")) {
                handler = item.getNode().getMetaDataMap().get("timeoutHandler", String.class);
            }
        }
        if (handler != null) {
            TimeoutJob job = new TimeoutJob(item, handler);
            eventAdmin.postEvent(job.cancelEvent(true));
        }
    }

    public void publishDelegationEvent(Workflow instance, Authorizable participant, WorkItem item, String user) {
        final Dictionary properties = new Hashtable();
        properties.put(TIME_STAMP, new Date());
        properties.put(USER, user);
        properties.put(EVENT_TYPE, WORKITEM_DELEGATION_EVENT);
        properties.put(WORKFLOW_NAME, instance.getWorkflowModel().getTitle());
        properties.put(WORKFLOW_VERSION, instance.getWorkflowModel().getVersion());
        properties.put(WORKFLOW_INSTANCE_ID, instance.getId());
        try {
            properties.put(DELEGATEE, participant.getID());
        } catch (RepositoryException e) {
            log.error("Unable to get ID for Authorizable.", e);
        }
        properties.put(WORK_ITEM, item);

        sendEvent(properties);
    }

    public void publishResourceCollectionModificationEvent(String path) {
        Dictionary properties = new Hashtable();
        properties.put("Path", path);
        properties.put(EVENT_TYPE, RESOURCE_COLLECTION_MODIFIED);
        sendEvent(properties);
    }

    // ------------< helper >---------------------------------------------------
    private AbsoluteTimeoutHandler getHandler(String handler, WorkflowSession session) {
        ComponentContext context = (ComponentContext) session.getWorkflowService().getConfig().get("componentContext");
        if (context != null && context.getBundleContext() != null) {
            try {
                ServiceReference refs[] = context.getBundleContext().getAllServiceReferences(
                        AbsoluteTimeoutHandler.class.getName(), null);
                ServiceReference ref = getServiceRef(refs, handler);
                if (ref != null) {
                    Object service = context.getBundleContext().getService(ref);
                    if (service instanceof AbsoluteTimeoutHandler) {
                        return (AbsoluteTimeoutHandler) service;
                    }
                }
            } catch (InvalidSyntaxException e) {
                // TODO
            }
        }
        return null;
    }

    private ServiceReference getServiceRef(ServiceReference[] refs, String handler) {
        for (ServiceReference ref : refs) {
            String componentName = (String) ref.getProperty("component.name");
            if (componentName.equals(handler)) {
                return ref;
            }
        }
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy