org.fireflow.engine.modules.schedule.impl.SchedulerSpringQuartzImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.fireflow.engine.modules.schedule.impl.SchedulerSpringQuartzImpl.java

Source

/**
 * Copyright 2007-2010 ?
 * All rights reserved. 
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses. *
 */
package org.fireflow.engine.modules.schedule.impl;

import java.text.ParseException;
import java.util.Date;

import org.fireflow.engine.WorkflowSession;
import org.fireflow.engine.WorkflowSessionFactory;
import org.fireflow.engine.WorkflowStatement;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.entity.runtime.ActivityInstanceState;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.entity.runtime.ScheduleJob;
import org.fireflow.engine.entity.runtime.ScheduleJobState;
import org.fireflow.engine.entity.runtime.impl.ScheduleJobImpl;
import org.fireflow.engine.exception.InvalidOperationException;
import org.fireflow.engine.exception.WorkflowProcessNotFoundException;
import org.fireflow.engine.impl.WorkflowSessionLocalImpl;
import org.fireflow.engine.modules.calendar.CalendarService;
import org.fireflow.engine.modules.instancemanager.ActivityInstanceManager;
import org.fireflow.engine.modules.ousystem.impl.FireWorkflowSystem;
import org.fireflow.engine.modules.persistence.PersistenceService;
import org.fireflow.engine.modules.persistence.ScheduleJobPersister;
import org.fireflow.engine.modules.persistence.TokenPersister;
import org.fireflow.engine.modules.schedule.ScheduleJobBean;
import org.fireflow.model.InvalidModelException;
import org.fireflow.pvm.kernel.BookMark;
import org.fireflow.pvm.kernel.ExecutionEntrance;
import org.fireflow.pvm.kernel.KernelManager;
import org.fireflow.pvm.kernel.Token;
import org.fireflow.pvm.kernel.TokenState;
import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * 
 * 
 * @author ?
 * @version 2.0
 */
public class SchedulerSpringQuartzImpl extends AbsScheduler {
    private Scheduler quartzScheduler;
    private TransactionTemplate transactionTemplate = null;

    /* (non-Javadoc)
     * @see org.fireflow.engine.service.timmer.AbsTimerHandlerManager#schedule(org.fireflow.engine.entity.runtime.TimerHandler)
     */
    public void schedule(ScheduleJob timerHandler, RuntimeContext runtimeContext) {
        try {
            String triggerType = timerHandler.getTriggerType();
            String triggerExpression = timerHandler.getTriggerExpression();
            Trigger trigger = null;
            if (triggerType.equals(ScheduleJob.CRON)) {
                trigger = new CronTrigger(
                        (new StringBuilder()).append(timerHandler.getId()).append("_trigger").toString(),
                        JOB_GROUP_NAME, timerHandler.getId(), JOB_GROUP_NAME, triggerExpression);
            } else if (triggerType.equals(ScheduleJob.STARTTIME_REPEATCOUNT_INTERVAL)) {

                int index = triggerExpression.indexOf("|");
                String timeStr = triggerExpression.substring(0, index);
                triggerExpression = triggerExpression.substring(index + 1);

                index = triggerExpression.indexOf("|");
                String repeatCountStr = triggerExpression.substring(0, index);
                triggerExpression = triggerExpression.substring(index + 1);

                String intervalStr = triggerExpression;

                Date time = new Date(Long.parseLong(timeStr));
                Integer repeatCount = Integer.parseInt(repeatCountStr);
                Integer interval = Integer.parseInt(intervalStr);

                if (time == null) {
                    throw new NullPointerException("The start time is null");
                }
                if (repeatCount == null) {
                    throw new NullPointerException("The repeat count is null");
                }
                if (interval == null) {
                    throw new NullPointerException("The interval is null");
                }

                trigger = new SimpleTrigger(
                        (new StringBuilder()).append(timerHandler.getId()).append("_trigger").toString(),
                        JOB_GROUP_NAME, timerHandler.getId(), JOB_GROUP_NAME, time, null, repeatCount, interval);

            } else if (triggerType.equals(ScheduleJob.STARTTIME_ENDTIME_INTERVAL)) {
                int index = triggerExpression.indexOf("|");
                String timeStr = triggerExpression.substring(0, index);
                triggerExpression = triggerExpression.substring(index + 1);

                index = triggerExpression.indexOf("|");
                String endTimeStr = triggerExpression.substring(0, index);
                triggerExpression = triggerExpression.substring(index + 1);

                String intervalStr = triggerExpression;

                Date time = new Date(Long.parseLong(timeStr));
                Date endTime = null;
                if (endTimeStr == null || endTimeStr.trim().equals("") || endTimeStr.equalsIgnoreCase("null")) {
                    endTime = null;
                } else {
                    endTime = new Date(Integer.parseInt(endTimeStr));
                }
                Integer interval = Integer.parseInt(intervalStr);

                if (time == null) {
                    throw new NullPointerException("The start time is null");
                }

                if (interval == null) {
                    throw new NullPointerException("The interval is null");
                }

                trigger = new SimpleTrigger(
                        (new StringBuilder()).append(timerHandler.getId()).append("_trigger").toString(),
                        JOB_GROUP_NAME, timerHandler.getId(), JOB_GROUP_NAME, time, endTime, 0, interval);
            }

            if (trigger == null) {
                //timerHandler???
                ((ScheduleJobImpl) timerHandler).setState(ScheduleJobState.OUT_OF_DATE);
                ((ScheduleJobImpl) timerHandler).setNote("Unsupported trigger type!");
                PersistenceService persistenceService = runtimeContext.getEngineModule(PersistenceService.class,
                        timerHandler.getProcessType());
                ScheduleJobPersister persister = persistenceService.getScheduleJobPersister();
                persister.saveOrUpdate(timerHandler);
            }
            //TODO trigger???

            JobDetail jobDetail = new JobDetail(timerHandler.getId(), JOB_GROUP_NAME, ScheduleJobBean.class);
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put(ScheduleJob.class.getName(), timerHandler);
            jobDataMap.put(RuntimeContext.class.getName(), runtimeContext);
            jobDetail.setJobDataMap(jobDataMap);
            quartzScheduler.addJob(jobDetail, true);

            quartzScheduler.scheduleJob(trigger);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (SchedulerException ex) {
            ex.printStackTrace();
        }
    }

    public void unSchedule(ScheduleJob scheduleJob, RuntimeContext runtimeContext) {
        try {
            quartzScheduler.deleteJob(scheduleJob.getId(), JOB_GROUP_NAME);
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public boolean ifJobCanBeFiredAgain(ScheduleJob job, RuntimeContext runtimeContext) {
        try {
            Trigger trigger = quartzScheduler.getTrigger(job.getId() + "_trigger", JOB_GROUP_NAME);
            return trigger.mayFireAgain();
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return false;
    }

    /**
     * @return the quartzScheduler
     */
    public Scheduler getQuartzScheduler() {
        return quartzScheduler;
    }

    /**
     * @param quartzScheduler the quartzScheduler to set
     */
    public void setQuartzScheduler(Scheduler quartzScheduler) {
        this.quartzScheduler = quartzScheduler;
    }

    /**
     * @return the transactionTemplate
     */
    public TransactionTemplate getTransactionTemplate() {
        return transactionTemplate;
    }

    /**
     * @param transactionTemplate the transactionTemplate to set
     */
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    /**
     * ??
     */
    public void onTimerTriggered(final ScheduleJob scheduleJob, final RuntimeContext runtimeContext) {
        PersistenceService persistenceService = runtimeContext.getEngineModule(PersistenceService.class,
                scheduleJob.getProcessType());
        final ScheduleJobPersister persister = persistenceService.getScheduleJobPersister();
        final TokenPersister tokenPersister = persistenceService.getTokenPersister();
        final CalendarService calendarService = runtimeContext.getEngineModule(CalendarService.class,
                scheduleJob.getProcessType());

        final WorkflowSession session = WorkflowSessionFactory.createWorkflowSession(runtimeContext,
                FireWorkflowSystem.getInstance());
        final WorkflowStatement statement = session.createWorkflowStatement(scheduleJob.getProcessType());
        if (scheduleJob.isCreateNewProcessInstance()) {
            transactionTemplate.execute(new TransactionCallback() {

                public Object doInTransaction(TransactionStatus arg0) {
                    try {
                        statement.startProcess(scheduleJob.getProcessId(), scheduleJob.getVersion(), null, null);
                        ((ScheduleJobImpl) scheduleJob).setTriggeredTimes(scheduleJob.getTriggeredTimes() + 1);
                        ((ScheduleJobImpl) scheduleJob).setLatestTriggeredTime(calendarService.getSysDate());

                        persister.saveOrUpdate(scheduleJob);

                    } catch (InvalidModelException e) {
                        ((ScheduleJobImpl) scheduleJob).setState(ScheduleJobState.FAULTED);
                        ((ScheduleJobImpl) scheduleJob).setEndTime(calendarService.getSysDate());
                        ((ScheduleJobImpl) scheduleJob).setNote(e.getMessage());
                        persister.saveOrUpdate(scheduleJob);
                        unSchedule(scheduleJob, runtimeContext);
                        e.printStackTrace();
                    } catch (WorkflowProcessNotFoundException e) {
                        // TODO Auto-generated catch block
                        ((ScheduleJobImpl) scheduleJob).setState(ScheduleJobState.FAULTED);
                        ((ScheduleJobImpl) scheduleJob).setEndTime(calendarService.getSysDate());
                        ((ScheduleJobImpl) scheduleJob).setNote(e.getMessage());
                        persister.saveOrUpdate(scheduleJob);
                        unSchedule(scheduleJob, runtimeContext);
                        e.printStackTrace();
                    } catch (InvalidOperationException e) {
                        // TODO Auto-generated catch block
                        ((ScheduleJobImpl) scheduleJob).setState(ScheduleJobState.FAULTED);
                        ((ScheduleJobImpl) scheduleJob).setEndTime(calendarService.getSysDate());
                        ((ScheduleJobImpl) scheduleJob).setNote(e.getMessage());
                        persister.saveOrUpdate(scheduleJob);
                        unSchedule(scheduleJob, runtimeContext);
                        e.printStackTrace();
                    }
                    return null;
                }

            });

        } else {
            transactionTemplate.execute(new TransactionCallback() {

                public Object doInTransaction(TransactionStatus arg0) {
                    ActivityInstance activityInstance = scheduleJob.getActivityInstance();

                    if (activityInstance == null || activityInstance.getState()
                            .getValue() > ActivityInstanceState.DELIMITER.getValue()) {
                        ((ScheduleJobImpl) scheduleJob).setState(ScheduleJobState.FAULTED);
                        ((ScheduleJobImpl) scheduleJob).setEndTime(calendarService.getSysDate());
                        if (activityInstance == null) {
                            ((ScheduleJobImpl) scheduleJob).setNote("The activity instance is null.");
                        } else {
                            ((ScheduleJobImpl) scheduleJob).setNote("The state of the activity instance is dead.");
                        }
                        persister.saveOrUpdate(scheduleJob);
                        unSchedule(scheduleJob, runtimeContext);
                        return null;
                    }

                    //??
                    ((ScheduleJobImpl) scheduleJob).setLatestTriggeredTime(calendarService.getSysDate());
                    ((ScheduleJobImpl) scheduleJob).setTriggeredTimes(scheduleJob.getTriggeredTimes() + 1);
                    persister.saveOrUpdate(scheduleJob);

                    ProcessInstance processInstance = activityInstance.getProcessInstance(session);
                    ((WorkflowSessionLocalImpl) session).setCurrentActivityInstance(activityInstance);
                    ((WorkflowSessionLocalImpl) session).setCurrentProcessInstance(processInstance);

                    RuntimeContext ctx = ((WorkflowSessionLocalImpl) session).getRuntimeContext();
                    ActivityInstanceManager activityInstanceMgr = ctx.getEngineModule(ActivityInstanceManager.class,
                            activityInstance.getProcessType());

                    activityInstanceMgr.onServiceCompleted(session, activityInstance);

                    //?activity
                    if (scheduleJob.isCancelAttachedToActivity()) {
                        Token thisToken = tokenPersister.find(Token.class, activityInstance.getTokenId());
                        Token attachedToToken = tokenPersister.find(Token.class,
                                thisToken.getAttachedToToken() == null ? "" : thisToken.getAttachedToToken());
                        if (attachedToToken != null
                                && attachedToToken.getState().getValue() < TokenState.DELIMITER.getValue()) {
                            KernelManager kernelManager = ctx.getEngineModule(KernelManager.class,
                                    attachedToToken.getProcessType());

                            BookMark bookMark = new BookMark();
                            bookMark.setToken(attachedToToken);
                            bookMark.setExecutionEntrance(ExecutionEntrance.HANDLE_CANCELLATION);
                            bookMark.setExtraArg(BookMark.SOURCE_TOKEN, thisToken);

                            kernelManager.addBookMark(bookMark);

                            kernelManager.execute(session);
                        }
                    }
                    return null;
                }

            });

        }
    }

    public boolean hasJobInSchedule(RuntimeContext runtimeContext) {
        try {
            String[] triggerNames = this.quartzScheduler.getTriggerNames(JOB_GROUP_NAME);
            if (triggerNames == null || triggerNames.length == 0) {
                return false;
            } else
                return true;
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
    }
}