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

org.quartz.core.QuartzScheduler Maven / Gradle / Ivy

Go to download

SDK for dev_appserver (local development) with some of the dependencies shaded (repackaged)

There is a newer version: 2.0.31
Show newest version

/* 
 * Copyright 2004-2005 OpenSymphony 
 * 
 * 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.
 * 
 */

/*
 * Previously Copyright (c) 2001-2004 James House
 */
package org.quartz.core;

import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.Set;

import com.google.appengine.repackaged.org.apache.commons.logging.Log;
import com.google.appengine.repackaged.org.apache.commons.logging.LogFactory;
import org.quartz.Calendar;
import org.quartz.InterruptableJob;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.quartz.JobPersistenceException;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.Scheduler;
import org.quartz.SchedulerContext;
import org.quartz.SchedulerException;
import org.quartz.SchedulerListener;
import org.quartz.Trigger;
import org.quartz.TriggerListener;
import org.quartz.UnableToInterruptJobException;
import org.quartz.impl.SchedulerRepository;
import org.quartz.simpl.SimpleJobFactory;
import org.quartz.spi.JobFactory;
import org.quartz.spi.SchedulerPlugin;
import org.quartz.spi.SchedulerSignaler;

/**
 * 

* This is the heart of Quartz, an indirect implementation of the {@link org.quartz.Scheduler} * interface, containing methods to schedule {@link org.quartz.Job}s, * register {@link org.quartz.JobListener} instances, etc. *

// TODO: more docs... * * @see org.quartz.Scheduler * @see org.quartz.core.QuartzSchedulerThread * @see org.quartz.spi.JobStore * @see org.quartz.spi.ThreadPool * * @author James House */ public class QuartzScheduler implements RemotableQuartzScheduler { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constants. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private static String VERSION_MAJOR = "UNKNOWN"; private static String VERSION_MINOR = "UNKNOWN"; private static String VERSION_ITERATION = "UNKNOWN"; static { Properties props = new Properties(); try { InputStream is = QuartzScheduler.class.getResourceAsStream("/build.properties"); if(is != null) { props.load(is); VERSION_MAJOR = props.getProperty("version.major"); VERSION_MINOR = props.getProperty("version.minor"); VERSION_ITERATION = props.getProperty("version.iter"); } } catch (IOException e) { getLog().error("Error loading version info from build.properties.", e); } } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private QuartzSchedulerResources resources; private QuartzSchedulerThread schedThread; private ThreadGroup threadGroup; private SchedulerContext context = new SchedulerContext(); private HashMap jobListeners = new HashMap(10); private ArrayList globalJobListeners = new ArrayList(10); private HashMap triggerListeners = new HashMap(10); private ArrayList globalTriggerListeners = new ArrayList(10); private ArrayList schedulerListeners = new ArrayList(10); private ArrayList schedulerPlugins = new ArrayList(10); private JobFactory jobFactory = new SimpleJobFactory(); ExecutingJobsManager jobMgr = null; ErrorLogger errLogger = null; private SchedulerSignaler signaler; private Random random = new Random(); private ArrayList holdToPreventGC = new ArrayList(5); private boolean signalOnSchedulingChange = true; private boolean closed = false; private Date initialStart = null; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** *

* Create a QuartzScheduler with the given configuration * properties. *

* * @see QuartzSchedulerResources */ public QuartzScheduler(QuartzSchedulerResources resources, SchedulingContext ctxt, long idleWaitTime, long dbRetryInterval) throws SchedulerException { this.resources = resources; try { bind(); } catch (Exception re) { throw new SchedulerException( "Unable to bind scheduler to RMI Registry.", re); } this.schedThread = new QuartzSchedulerThread(this, resources, ctxt); if (idleWaitTime > 0) this.schedThread.setIdleWaitTime(idleWaitTime); if (dbRetryInterval > 0) this.schedThread.setDbFailureRetryInterval(dbRetryInterval); jobMgr = new ExecutingJobsManager(); addGlobalJobListener(jobMgr); errLogger = new ErrorLogger(); addSchedulerListener(errLogger); signaler = new SchedulerSignalerImpl(this); getLog().info("Quartz Scheduler v." + getVersion() + " created."); } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public String getVersion() { return getVersionMajor() + "." + getVersionMinor() + "." + getVersionIteration(); } public static String getVersionMajor() { return VERSION_MAJOR; } public static String getVersionMinor() { return VERSION_MINOR; } public static String getVersionIteration() { return VERSION_ITERATION; } public SchedulerSignaler getSchedulerSignaler() { return signaler; } public static Log getLog() { return LogFactory.getLog(QuartzScheduler.class); } /** *

* Bind the scheduler to an RMI registry. *

*/ private void bind() throws RemoteException { String host = resources.getRMIRegistryHost(); // don't export if we're not configured to do so... if (host == null || host.length() == 0) return; RemotableQuartzScheduler exportable = null; if(resources.getRMIServerPort() > 0) exportable = (RemotableQuartzScheduler) UnicastRemoteObject .exportObject(this, resources.getRMIServerPort()); else exportable = (RemotableQuartzScheduler) UnicastRemoteObject .exportObject(this); Registry registry = null; if (resources.getRMICreateRegistryStrategy().equals( QuartzSchedulerResources.CREATE_REGISTRY_AS_NEEDED)) { try { // First try to get an existing one, instead of creating it, // since if // we're in a web-app being 'hot' re-depoloyed, then the JVM // still // has the registry that we created above the first time... registry = LocateRegistry.getRegistry(resources .getRMIRegistryPort()); registry.list(); } catch (Exception e) { registry = LocateRegistry.createRegistry(resources .getRMIRegistryPort()); } } else if (resources.getRMICreateRegistryStrategy().equals( QuartzSchedulerResources.CREATE_REGISTRY_ALWAYS)) { try { registry = LocateRegistry.createRegistry(resources .getRMIRegistryPort()); } catch (Exception e) { // Fall back to an existing one, instead of creating it, since // if // we're in a web-app being 'hot' re-depoloyed, then the JVM // still // has the registry that we created above the first time... registry = LocateRegistry.getRegistry(resources .getRMIRegistryPort()); } } else { registry = LocateRegistry.getRegistry(resources .getRMIRegistryHost(), resources.getRMIRegistryPort()); } registry.rebind(resources.getUniqueIdentifier(), exportable); getLog().info("Scheduler bound to RMI registry."); } /** *

* Un-bind the scheduler from an RMI registry. *

*/ private void unBind() throws RemoteException { String host = resources.getRMIRegistryHost(); // don't un-export if we're not configured to do so... if (host == null || host.length() == 0) return; Registry registry = LocateRegistry.getRegistry(resources .getRMIRegistryHost(), resources.getRMIRegistryPort()); try { registry.unbind(resources.getUniqueIdentifier()); UnicastRemoteObject.unexportObject(this, true); } catch (java.rmi.NotBoundException nbe) { } getLog().info("Scheduler un-bound from RMI registry."); } /** *

* Returns the name of the QuartzScheduler. *

*/ public String getSchedulerName() { return resources.getName(); } /** *

* Returns the instance Id of the QuartzScheduler. *

*/ public String getSchedulerInstanceId() { return resources.getInstanceId(); } /** *

* Returns the name of the QuartzScheduler. *

*/ public ThreadGroup getSchedulerThreadGroup() { if (threadGroup == null) { threadGroup = new ThreadGroup("QuartzScheduler:" + getSchedulerName()); } return threadGroup; } public void addNoGCObject(Object obj) { holdToPreventGC.add(obj); } public boolean removeNoGCObject(Object obj) { return holdToPreventGC.remove(obj); } /** *

* Returns the SchedulerContext of the Scheduler. *

*/ public SchedulerContext getSchedulerContext() throws SchedulerException { return context; } public boolean isSignalOnSchedulingChange() { return signalOnSchedulingChange; } public void setSignalOnSchedulingChange(boolean signalOnSchedulingChange) { this.signalOnSchedulingChange = signalOnSchedulingChange; } /////////////////////////////////////////////////////////////////////////// /// /// Schedululer State Management Methods /// /////////////////////////////////////////////////////////////////////////// /** *

* Starts the QuartzScheduler's threads that fire {@link org.quartz.Trigger}s. *

* *

* All {@link org.quartz.Trigger}s that have misfired will * be passed to the appropriate TriggerListener(s). *

*/ public void start() throws SchedulerException { if (closed) throw new SchedulerException( "The Scheduler cannot be restarted after shutdown() has been called."); schedThread.togglePause(false); if (initialStart == null) { initialStart = new Date(); this.resources.getJobStore().schedulerStarted(); startPlugins(); } getLog().info( "Scheduler " + resources.getUniqueIdentifier() + " started."); } /** *

* Temporarily halts the QuartzScheduler's firing of {@link org.quartz.Trigger}s. *

* *

* The scheduler is not destroyed, and can be re-started at any time. *

*/ public void standby() { schedThread.togglePause(true); getLog().info( "Scheduler " + resources.getUniqueIdentifier() + " paused."); } /** *

* Reports whether the Scheduler is paused. *

*/ public boolean isInStandbyMode() { return schedThread.isPaused(); } public Date runningSince() { return initialStart; } public int numJobsExecuted() { return jobMgr.getNumJobsFired(); } public Class getJobStoreClass() { return resources.getJobStore().getClass(); } public boolean supportsPersistence() { return resources.getJobStore().supportsPersistence(); } public Class getThreadPoolClass() { return resources.getThreadPool().getClass(); } public int getThreadPoolSize() { return resources.getThreadPool().getPoolSize(); } /** *

* Halts the QuartzScheduler's firing of {@link org.quartz.Trigger}s, * and cleans up all resources associated with the QuartzScheduler. * Equivalent to shutdown(false). *

* *

* The scheduler cannot be re-started. *

*/ public void shutdown() { shutdown(false); } /** *

* Halts the QuartzScheduler's firing of {@link org.quartz.Trigger}s, * and cleans up all resources associated with the QuartzScheduler. *

* *

* The scheduler cannot be re-started. *

* * @param waitForJobsToComplete * if true the scheduler will not allow this method * to return until all currently executing jobs have completed. */ public void shutdown(boolean waitForJobsToComplete) { if(closed == true) return; getLog().info( "Scheduler " + resources.getUniqueIdentifier() + " shutting down."); standby(); closed = true; schedThread.halt(); resources.getThreadPool().shutdown(waitForJobsToComplete); if (waitForJobsToComplete) { while (jobMgr.getNumJobsCurrentlyExecuting() > 0) try { Thread.sleep(100); } catch (Exception ignore) { } } resources.getJobStore().shutdown(); notifySchedulerListenersShutdown(); shutdownPlugins(); SchedulerRepository.getInstance().remove(resources.getName()); holdToPreventGC.clear(); try { unBind(); } catch (RemoteException re) { } getLog().info( "Scheduler " + resources.getUniqueIdentifier() + " shutdown complete."); } /** *

* Reports whether the Scheduler has been shutdown. *

*/ public boolean isShutdown() { return closed; } public void validateState() throws SchedulerException { if (isShutdown()) throw new SchedulerException("The Scheduler has been shutdown."); // other conditions to check (?) } /** *

* Return a list of JobExecutionContext objects that * represent all currently executing Jobs. *

* *

* Note that the list returned is an 'instantaneous' snap-shot, and that as * soon as it's returned, the true list of executing jobs may be different. *

*/ public List getCurrentlyExecutingJobs() { return jobMgr.getExecutingJobs(); } /////////////////////////////////////////////////////////////////////////// /// /// Scheduling-related Methods /// /////////////////////////////////////////////////////////////////////////// /** *

* Add the {@link org.quartz.Job} identified by the given * {@link org.quartz.JobDetail} to the Scheduler, and * associate the given {@link org.quartz.Trigger} with it. *

* *

* If the given Trigger does not reference any Job, then it * will be set to reference the Job passed with it into this method. *

* * @throws SchedulerException * if the Job or Trigger cannot be added to the Scheduler, or * there is an internal Scheduler error. */ public Date scheduleJob(SchedulingContext ctxt, JobDetail jobDetail, Trigger trigger) throws SchedulerException { validateState(); jobDetail.validate(); if (trigger.getJobName() == null) { trigger.setJobName(jobDetail.getName()); trigger.setJobGroup(jobDetail.getGroup()); } else if (trigger.getJobName() != null && !trigger.getJobName().equals(jobDetail.getName())) { throw new SchedulerException( "Trigger does not reference given job!", SchedulerException.ERR_CLIENT_ERROR); } else if (trigger.getJobGroup() != null && !trigger.getJobGroup().equals(jobDetail.getGroup())) { throw new SchedulerException( "Trigger does not reference given job!", SchedulerException.ERR_CLIENT_ERROR); } trigger.validate(); Calendar cal = null; if (trigger.getCalendarName() != null) { cal = resources.getJobStore().retrieveCalendar(ctxt, trigger.getCalendarName()); } Date ft = trigger.computeFirstFireTime(cal); if (ft == null) throw new SchedulerException( "Based on configured schedule, the given trigger will never fire.", SchedulerException.ERR_CLIENT_ERROR); resources.getJobStore().storeJobAndTrigger(ctxt, jobDetail, trigger); notifySchedulerThread(); notifySchedulerListenersSchduled(trigger); return ft; } /** *

* Schedule the given {@link org.quartz.Trigger} with the * Job identified by the Trigger's settings. *

* * @throws SchedulerException * if the indicated Job does not exist, or the Trigger cannot be * added to the Scheduler, or there is an internal Scheduler * error. */ public Date scheduleJob(SchedulingContext ctxt, Trigger trigger) throws SchedulerException { validateState(); trigger.validate(); Calendar cal = null; if (trigger.getCalendarName() != null) { cal = resources.getJobStore().retrieveCalendar(ctxt, trigger.getCalendarName()); if(cal == null) throw new SchedulerException( "Calendar not found: " + trigger.getCalendarName(), SchedulerException.ERR_PERSISTENCE_CALENDAR_DOES_NOT_EXIST); } Date ft = trigger.computeFirstFireTime(cal); if (ft == null) throw new SchedulerException( "Based on configured schedule, the given trigger will never fire.", SchedulerException.ERR_CLIENT_ERROR); resources.getJobStore().storeTrigger(ctxt, trigger, false); notifySchedulerThread(); notifySchedulerListenersSchduled(trigger); return ft; } /** *

* Add the given Job to the Scheduler - with no associated * Trigger. The Job will be 'dormant' until * it is scheduled with a Trigger, or Scheduler.triggerJob() * is called for it. *

* *

* The Job must by definition be 'durable', if it is not, * SchedulerException will be thrown. *

* * @throws SchedulerException * if there is an internal Scheduler error, or if the Job is not * durable, or a Job with the same name already exists, and * replace is false. */ public void addJob(SchedulingContext ctxt, JobDetail jobDetail, boolean replace) throws SchedulerException { validateState(); if (!jobDetail.isDurable() && !replace) throw new SchedulerException( "Jobs added with no trigger must be durable.", SchedulerException.ERR_CLIENT_ERROR); resources.getJobStore().storeJob(ctxt, jobDetail, replace); } /** *

* Delete the identified Job from the Scheduler - and any * associated Triggers. *

* * @return true if the Job was found and deleted. * @throws SchedulerException * if there is an internal Scheduler error. */ public boolean deleteJob(SchedulingContext ctxt, String jobName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; return resources.getJobStore().removeJob(ctxt, jobName, groupName); } /** *

* Remove the indicated {@link org.quartz.Trigger} from the * scheduler. *

*/ public boolean unscheduleJob(SchedulingContext ctxt, String triggerName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; if (resources.getJobStore().removeTrigger(ctxt, triggerName, groupName)) { notifySchedulerThread(); notifySchedulerListenersUnschduled(triggerName, groupName); } else return false; return true; } /** *

* Remove (delete) the {@link org.quartz.Trigger} with the * given name, and store the new given one - which must be associated * with the same job. *

* * @param triggerName * The name of the Trigger to be removed. * @param groupName * The group name of the Trigger to be removed. * @param newTrigger * The new Trigger to be stored. * @return null if a Trigger with the given * name & group was not found and removed from the store, otherwise * the first fire time of the newly scheduled trigger. */ public Date rescheduleJob(SchedulingContext ctxt, String triggerName, String groupName, Trigger newTrigger) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; newTrigger.validate(); Calendar cal = null; if (newTrigger.getCalendarName() != null) { cal = resources.getJobStore().retrieveCalendar(ctxt, newTrigger.getCalendarName()); } Date ft = newTrigger.computeFirstFireTime(cal); if (ft == null) throw new SchedulerException( "Based on configured schedule, the given trigger will never fire.", SchedulerException.ERR_CLIENT_ERROR); if (resources.getJobStore().replaceTrigger(ctxt, triggerName, groupName, newTrigger)) { notifySchedulerThread(); notifySchedulerListenersUnschduled(triggerName, groupName); notifySchedulerListenersSchduled(newTrigger); } else return null; return ft; } private String newTriggerId() { long r = random.nextLong(); if (r < 0) r = -r; return "MT_" + Long.toString(r, 30 + (int) (System.currentTimeMillis() % 7)); } /** *

* Trigger the identified {@link org.quartz.Job} (execute it * now) - with a non-volatile trigger. *

*/ public void triggerJob(SchedulingContext ctxt, String jobName, String groupName, JobDataMap data) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; Trigger trig = new org.quartz.SimpleTrigger(newTriggerId(), Scheduler.DEFAULT_MANUAL_TRIGGERS, jobName, groupName, new Date(), null, 0, 0); trig.setVolatility(false); trig.computeFirstFireTime(null); if(data != null) trig.setJobDataMap(data); boolean collision = true; while (collision) { try { resources.getJobStore().storeTrigger(ctxt, trig, false); collision = false; } catch (ObjectAlreadyExistsException oaee) { trig.setName(newTriggerId()); } } notifySchedulerThread(); notifySchedulerListenersSchduled(trig); } /** *

* Trigger the identified {@link org.quartz.Job} (execute it * now) - with a volatile trigger. *

*/ public void triggerJobWithVolatileTrigger(SchedulingContext ctxt, String jobName, String groupName, JobDataMap data) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; Trigger trig = new org.quartz.SimpleTrigger(newTriggerId(), Scheduler.DEFAULT_MANUAL_TRIGGERS, jobName, groupName, new Date(), null, 0, 0); trig.setVolatility(true); trig.computeFirstFireTime(null); if(data != null) trig.setJobDataMap(data); boolean collision = true; while (collision) { try { resources.getJobStore().storeTrigger(ctxt, trig, false); collision = false; } catch (ObjectAlreadyExistsException oaee) { trig.setName(newTriggerId()); } } notifySchedulerThread(); notifySchedulerListenersSchduled(trig); } /** *

* Pause the {@link Trigger} with the given name. *

* */ public void pauseTrigger(SchedulingContext ctxt, String triggerName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().pauseTrigger(ctxt, triggerName, groupName); notifySchedulerThread(); notifySchedulerListenersPausedTrigger(triggerName, groupName); } /** *

* Pause all of the {@link Trigger}s in the given group. *

* */ public void pauseTriggerGroup(SchedulingContext ctxt, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().pauseTriggerGroup(ctxt, groupName); notifySchedulerThread(); notifySchedulerListenersPausedTrigger(null, groupName); } /** *

* Pause the {@link org.quartz.JobDetail} with the given * name - by pausing all of its current Triggers. *

* */ public void pauseJob(SchedulingContext ctxt, String jobName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().pauseJob(ctxt, jobName, groupName); notifySchedulerThread(); notifySchedulerListenersPausedJob(jobName, groupName); } /** *

* Pause all of the {@link org.quartz.JobDetail}s in the * given group - by pausing all of their Triggers. *

* */ public void pauseJobGroup(SchedulingContext ctxt, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().pauseJobGroup(ctxt, groupName); notifySchedulerThread(); notifySchedulerListenersPausedJob(null, groupName); } /** *

* Resume (un-pause) the {@link Trigger} with the given * name. *

* *

* If the Trigger missed one or more fire-times, then the * Trigger's misfire instruction will be applied. *

* */ public void resumeTrigger(SchedulingContext ctxt, String triggerName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().resumeTrigger(ctxt, triggerName, groupName); notifySchedulerThread(); notifySchedulerListenersResumedTrigger(triggerName, groupName); } /** *

* Resume (un-pause) all of the {@link Trigger}s in the * given group. *

* *

* If any Trigger missed one or more fire-times, then the * Trigger's misfire instruction will be applied. *

* */ public void resumeTriggerGroup(SchedulingContext ctxt, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().resumeTriggerGroup(ctxt, groupName); notifySchedulerThread(); notifySchedulerListenersResumedTrigger(null, groupName); } public Set getPausedTriggerGroups(SchedulingContext ctxt) throws SchedulerException { return resources.getJobStore().getPausedTriggerGroups(ctxt); } /** *

* Resume (un-pause) the {@link org.quartz.JobDetail} with * the given name. *

* *

* If any of the Job'sTrigger s missed one * or more fire-times, then the Trigger's misfire * instruction will be applied. *

* */ public void resumeJob(SchedulingContext ctxt, String jobName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().resumeJob(ctxt, jobName, groupName); notifySchedulerThread(); notifySchedulerListenersResumedJob(jobName, groupName); } /** *

* Resume (un-pause) all of the {@link org.quartz.JobDetail}s * in the given group. *

* *

* If any of the Job s had Trigger s that * missed one or more fire-times, then the Trigger's * misfire instruction will be applied. *

* */ public void resumeJobGroup(SchedulingContext ctxt, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; resources.getJobStore().resumeJobGroup(ctxt, groupName); notifySchedulerThread(); notifySchedulerListenersResumedJob(null, groupName); } /** *

* Pause all triggers - equivalent of calling pauseTriggerGroup(group) * on every group. *

* *

* When resumeAll() is called (to un-pause), trigger misfire * instructions WILL be applied. *

* * @see #resumeAll(SchedulingContext) * @see #pauseTriggerGroup(SchedulingContext, String) * @see #pause() */ public void pauseAll(SchedulingContext ctxt) throws SchedulerException { validateState(); resources.getJobStore().pauseAll(ctxt); notifySchedulerThread(); notifySchedulerListenersPausedTrigger(null, null); } /** *

* Resume (un-pause) all triggers - equivalent of calling resumeTriggerGroup(group) * on every group. *

* *

* If any Trigger missed one or more fire-times, then the * Trigger's misfire instruction will be applied. *

* * @see #pauseAll(SchedulingContext) */ public void resumeAll(SchedulingContext ctxt) throws SchedulerException { validateState(); resources.getJobStore().resumeAll(ctxt); notifySchedulerThread(); notifySchedulerListenersResumedTrigger(null, null); } /** *

* Get the names of all known {@link org.quartz.Job} groups. *

*/ public String[] getJobGroupNames(SchedulingContext ctxt) throws SchedulerException { validateState(); return resources.getJobStore().getJobGroupNames(ctxt); } /** *

* Get the names of all the {@link org.quartz.Job}s in the * given group. *

*/ public String[] getJobNames(SchedulingContext ctxt, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; return resources.getJobStore().getJobNames(ctxt, groupName); } /** *

* Get all {@link Trigger} s that are associated with the * identified {@link org.quartz.JobDetail}. *

*/ public Trigger[] getTriggersOfJob(SchedulingContext ctxt, String jobName, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; return resources.getJobStore().getTriggersForJob(ctxt, jobName, groupName); } /** *

* Get the names of all known {@link org.quartz.Trigger} * groups. *

*/ public String[] getTriggerGroupNames(SchedulingContext ctxt) throws SchedulerException { validateState(); return resources.getJobStore().getTriggerGroupNames(ctxt); } /** *

* Get the names of all the {@link org.quartz.Trigger}s in * the given group. *

*/ public String[] getTriggerNames(SchedulingContext ctxt, String groupName) throws SchedulerException { validateState(); if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; return resources.getJobStore().getTriggerNames(ctxt, groupName); } /** *

* Get the {@link JobDetail} for the Job * instance with the given name and group. *

*/ public JobDetail getJobDetail(SchedulingContext ctxt, String jobName, String jobGroup) throws SchedulerException { validateState(); if(jobGroup == null) jobGroup = Scheduler.DEFAULT_GROUP; return resources.getJobStore().retrieveJob(ctxt, jobName, jobGroup); } /** *

* Get the {@link Trigger} instance with the given name and * group. *

*/ public Trigger getTrigger(SchedulingContext ctxt, String triggerName, String triggerGroup) throws SchedulerException { validateState(); if(triggerGroup == null) triggerGroup = Scheduler.DEFAULT_GROUP; return resources.getJobStore().retrieveTrigger(ctxt, triggerName, triggerGroup); } /** *

* Get the current state of the identified {@link Trigger}. *

* * @see Trigger#STATE_NORMAL * @see Trigger#STATE_PAUSED * @see Trigger#STATE_COMPLETE * @see Trigger#STATE_ERROR */ public int getTriggerState(SchedulingContext ctxt, String triggerName, String triggerGroup) throws SchedulerException { validateState(); if(triggerGroup == null) triggerGroup = Scheduler.DEFAULT_GROUP; return resources.getJobStore().getTriggerState(ctxt, triggerName, triggerGroup); } /** *

* Add (register) the given Calendar to the Scheduler. *

* * @throws SchedulerException * if there is an internal Scheduler error, or a Calendar with * the same name already exists, and replace is * false. */ public void addCalendar(SchedulingContext ctxt, String calName, Calendar calendar, boolean replace, boolean updateTriggers) throws SchedulerException { validateState(); resources.getJobStore().storeCalendar(ctxt, calName, calendar, replace, updateTriggers); } /** *

* Delete the identified Calendar from the Scheduler. *

* * @return true if the Calendar was found and deleted. * @throws SchedulerException * if there is an internal Scheduler error. */ public boolean deleteCalendar(SchedulingContext ctxt, String calName) throws SchedulerException { validateState(); return resources.getJobStore().removeCalendar(ctxt, calName); } /** *

* Get the {@link Calendar} instance with the given name. *

*/ public Calendar getCalendar(SchedulingContext ctxt, String calName) throws SchedulerException { validateState(); return resources.getJobStore().retrieveCalendar(ctxt, calName); } /** *

* Get the names of all registered {@link Calendar}s. *

*/ public String[] getCalendarNames(SchedulingContext ctxt) throws SchedulerException { validateState(); return resources.getJobStore().getCalendarNames(ctxt); } /** *

* Add the given {@link org.quartz.JobListener} to the * Scheduler'sglobal list. *

* *

* Listeners in the 'global' list receive notification of execution events * for ALL {@link org.quartz.Job}s. *

*/ public void addGlobalJobListener(JobListener jobListener) { if (jobListener.getName() == null || jobListener.getName().length() == 0) throw new IllegalArgumentException( "JobListener name cannot be empty."); globalJobListeners.add(jobListener); } /** *

* Add the given {@link org.quartz.JobListener} to the * Scheduler's list, of registered JobListeners. */ public void addJobListener(JobListener jobListener) { if (jobListener.getName() == null || jobListener.getName().length() == 0) throw new IllegalArgumentException( "JobListener name cannot be empty."); jobListeners.put(jobListener.getName(), jobListener); } /** *

* Remove the given {@link org.quartz.JobListener} from the * Scheduler's list of global listeners. *

* * @return true if the identifed listener was found in the list, and * removed. */ public boolean removeGlobalJobListener(JobListener jobListener) { return globalJobListeners.remove(jobListener); } /** *

* Remove the identifed {@link org.quartz.JobListener} from * the Scheduler's list of registered listeners. *

* * @return true if the identifed listener was found in the list, and * removed. */ public boolean removeJobListener(String name) { Object o = jobListeners.remove(name); if (o != null) return true; return false; } /** *

* Get a List containing all of the {@link org.quartz.JobListener} * s in the Scheduler'sglobal list. *

*/ public List getGlobalJobListeners() { return new LinkedList(globalJobListeners); } /** *

* Get a Set containing the names of all the non-global{@link org.quartz.JobListener} * s registered with the Scheduler. *

*/ public Set getJobListenerNames() { return Collections.unmodifiableSet(jobListeners.keySet()); } /** *

* Get the non-global{@link org.quartz.JobListener} * that has the given name. *

*/ public JobListener getJobListener(String name) { return (JobListener) jobListeners.get(name); } /** *

* Add the given {@link org.quartz.TriggerListener} to the * Scheduler'sglobal list. *

* *

* Listeners in the 'global' list receive notification of execution events * for ALL {@link org.quartz.Trigger}s. *

*/ public void addGlobalTriggerListener(TriggerListener triggerListener) { if (triggerListener.getName() == null || triggerListener.getName().length() == 0) throw new IllegalArgumentException( "TriggerListener name cannot be empty."); globalTriggerListeners.add(triggerListener); } /** *

* Add the given {@link org.quartz.TriggerListener} to the * Scheduler's list, of registered TriggerListeners. */ public void addTriggerListener(TriggerListener triggerListener) { if (triggerListener.getName() == null || triggerListener.getName().length() == 0) throw new IllegalArgumentException( "TriggerListener name cannot be empty."); triggerListeners.put(triggerListener.getName(), triggerListener); } /** *

* Remove the given {@link org.quartz.TriggerListener} from * the Scheduler's list of global listeners. *

* * @return true if the identifed listener was found in the list, and * removed. */ public boolean removeGlobalTriggerListener(TriggerListener triggerListener) { return globalTriggerListeners.remove(triggerListener); } /** *

* Remove the identifed {@link org.quartz.TriggerListener} * from the Scheduler's list of registered listeners. *

* * @return true if the identifed listener was found in the list, and * removed. */ public boolean removeTriggerListener(String name) { Object o = triggerListeners.remove(name); if (o != null) return true; return false; } /** *

* Get a list containing all of the {@link org.quartz.TriggerListener} * s in the Scheduler'sglobal list. *

*/ public List getGlobalTriggerListeners() { return new LinkedList(globalTriggerListeners); } /** *

* Get a Set containing the names of all the non-global{@link org.quartz.TriggerListener} * s registered with the Scheduler. *

*/ public Set getTriggerListenerNames() { return Collections.unmodifiableSet(triggerListeners.keySet()); } /** *

* Get the non-global{@link org.quartz.TriggerListener} * that has the given name. *

*/ public TriggerListener getTriggerListener(String name) { return (TriggerListener) triggerListeners.get(name); } /** *

* Register the given {@link SchedulerListener} with the * Scheduler. *

*/ public void addSchedulerListener(SchedulerListener schedulerListener) { schedulerListeners.add(schedulerListener); } /** *

* Remove the given {@link SchedulerListener} from the * Scheduler. *

* * @return true if the identifed listener was found in the list, and * removed. */ public boolean removeSchedulerListener(SchedulerListener schedulerListener) { return schedulerListeners.remove(schedulerListener); } /** *

* Get a List containing all of the {@link SchedulerListener} * s registered with the Scheduler. *

*/ public List getSchedulerListeners() { return (List) schedulerListeners.clone(); } protected void notifyJobStoreJobComplete(SchedulingContext ctxt, Trigger trigger, JobDetail detail, int instCode) throws JobPersistenceException { resources.getJobStore().triggeredJobComplete(ctxt, trigger, detail, instCode); } protected void notifySchedulerThread() { if (isSignalOnSchedulingChange()) schedThread.signalSchedulingChange(); } private List buildTriggerListenerList(String[] additionalLstnrs) throws SchedulerException { List triggerListeners = getGlobalTriggerListeners(); for (int i = 0; i < additionalLstnrs.length; i++) { TriggerListener tl = getTriggerListener(additionalLstnrs[i]); if (tl != null) triggerListeners.add(tl); else throw new SchedulerException("TriggerListener '" + additionalLstnrs[i] + "' not found.", SchedulerException.ERR_TRIGGER_LISTENER_NOT_FOUND); } return triggerListeners; } private List buildJobListenerList(String[] additionalLstnrs) throws SchedulerException { List jobListeners = getGlobalJobListeners(); for (int i = 0; i < additionalLstnrs.length; i++) { JobListener jl = getJobListener(additionalLstnrs[i]); if (jl != null) jobListeners.add(jl); else throw new SchedulerException("JobListener '" + additionalLstnrs[i] + "' not found.", SchedulerException.ERR_JOB_LISTENER_NOT_FOUND); } return jobListeners; } public boolean notifyTriggerListenersFired(JobExecutionContext jec) throws SchedulerException { // build a list of all trigger listeners that are to be notified... List triggerListeners = buildTriggerListenerList(jec.getTrigger() .getTriggerListenerNames()); boolean vetoedExecution = false; // notify all trigger listeners in the list java.util.Iterator itr = triggerListeners.iterator(); while (itr.hasNext()) { TriggerListener tl = (TriggerListener) itr.next(); try { tl.triggerFired(jec.getTrigger(), jec); if(tl.vetoJobExecution(jec.getTrigger(), jec)) vetoedExecution = true; } catch (Exception e) { SchedulerException se = new SchedulerException( "TriggerListener '" + tl.getName() + "' threw exception: " + e.getMessage(), e); se.setErrorCode(SchedulerException.ERR_TRIGGER_LISTENER); throw se; } } return vetoedExecution; } public void notifyTriggerListenersMisfired(Trigger trigger) throws SchedulerException { // build a list of all trigger listeners that are to be notified... List triggerListeners = buildTriggerListenerList(trigger .getTriggerListenerNames()); // notify all trigger listeners in the list java.util.Iterator itr = triggerListeners.iterator(); while (itr.hasNext()) { TriggerListener tl = (TriggerListener) itr.next(); try { tl.triggerMisfired(trigger); } catch (Exception e) { SchedulerException se = new SchedulerException( "TriggerListener '" + tl.getName() + "' threw exception: " + e.getMessage(), e); se.setErrorCode(SchedulerException.ERR_TRIGGER_LISTENER); throw se; } } } public void notifyTriggerListenersComplete(JobExecutionContext jec, int instCode) throws SchedulerException { // build a list of all trigger listeners that are to be notified... List triggerListeners = buildTriggerListenerList(jec.getTrigger() .getTriggerListenerNames()); // notify all trigger listeners in the list java.util.Iterator itr = triggerListeners.iterator(); while (itr.hasNext()) { TriggerListener tl = (TriggerListener) itr.next(); try { tl.triggerComplete(jec.getTrigger(), jec, instCode); } catch (Exception e) { SchedulerException se = new SchedulerException( "TriggerListener '" + tl.getName() + "' threw exception: " + e.getMessage(), e); se.setErrorCode(SchedulerException.ERR_TRIGGER_LISTENER); throw se; } } } public void notifyJobListenersToBeExecuted(JobExecutionContext jec) throws SchedulerException { // build a list of all job listeners that are to be notified... List jobListeners = buildJobListenerList(jec.getJobDetail() .getJobListenerNames()); // notify all job listeners java.util.Iterator itr = jobListeners.iterator(); while (itr.hasNext()) { JobListener jl = (JobListener) itr.next(); try { jl.jobToBeExecuted(jec); } catch (Exception e) { SchedulerException se = new SchedulerException( "JobListener '" + jl.getName() + "' threw exception: " + e.getMessage(), e); se.setErrorCode(SchedulerException.ERR_JOB_LISTENER); throw se; } } } public void notifyJobListenersWasVetoed(JobExecutionContext jec) throws SchedulerException { // build a list of all job listeners that are to be notified... List jobListeners = buildJobListenerList(jec.getJobDetail() .getJobListenerNames()); // notify all job listeners java.util.Iterator itr = jobListeners.iterator(); while (itr.hasNext()) { JobListener jl = (JobListener) itr.next(); try { jl.jobExecutionVetoed(jec); } catch (Exception e) { SchedulerException se = new SchedulerException( "JobListener '" + jl.getName() + "' threw exception: " + e.getMessage(), e); se.setErrorCode(SchedulerException.ERR_JOB_LISTENER); throw se; } } } public void notifyJobListenersWasExecuted(JobExecutionContext jec, JobExecutionException je) throws SchedulerException { // build a list of all job listeners that are to be notified... List jobListeners = buildJobListenerList(jec.getJobDetail() .getJobListenerNames()); // notify all job listeners java.util.Iterator itr = jobListeners.iterator(); while (itr.hasNext()) { JobListener jl = (JobListener) itr.next(); try { jl.jobWasExecuted(jec, je); } catch (Exception e) { SchedulerException se = new SchedulerException( "JobListener '" + jl.getName() + "' threw exception: " + e.getMessage(), e); se.setErrorCode(SchedulerException.ERR_JOB_LISTENER); throw se; } } } public void notifySchedulerListenersError(String msg, SchedulerException se) { // build a list of all scheduler listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.schedulerError(msg, se); } catch (Exception e) { getLog() .error( "Error while notifying SchedulerListener of error: ", e); getLog().error( " Original error (for notification) was: " + msg, se); } } } public void notifySchedulerListenersSchduled(Trigger trigger) { // build a list of all scheduler listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.jobScheduled(trigger); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of scheduled job." + " Triger=" + trigger.getFullName(), e); } } } public void notifySchedulerListenersUnschduled(String triggerName, String triggerGroup) { // build a list of all scheduler listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.jobUnscheduled(triggerName, triggerGroup); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of unscheduled job." + " Triger=" + triggerGroup + "." + triggerName, e); } } } public void notifySchedulerListenersFinalized(Trigger trigger) { // build a list of all scheduler listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.triggerFinalized(trigger); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of finalized trigger." + " Triger=" + trigger.getFullName(), e); } } } public void notifySchedulerListenersPausedTrigger(String name, String group) { // build a list of all job listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.triggersPaused(name, group); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of paused trigger/group." + " Triger=" + group + "." + name, e); } } } public void notifySchedulerListenersResumedTrigger(String name, String group) { // build a list of all job listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.triggersResumed(name, group); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of resumed trigger/group." + " Triger=" + group + "." + name, e); } } } public void notifySchedulerListenersPausedJob(String name, String group) { // build a list of all job listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.jobsPaused(name, group); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of paused job/group." + " Job=" + group + "." + name, e); } } } public void notifySchedulerListenersResumedJob(String name, String group) { // build a list of all job listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.jobsResumed(name, group); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of resumed job/group." + " Job=" + group + "." + name, e); } } } public void notifySchedulerListenersShutdown() { // build a list of all job listeners that are to be notified... List schedListeners = getSchedulerListeners(); // notify all scheduler listeners java.util.Iterator itr = schedListeners.iterator(); while (itr.hasNext()) { SchedulerListener sl = (SchedulerListener) itr.next(); try { sl.schedulerShutdown(); } catch (Exception e) { getLog().error( "Error while notifying SchedulerListener of shutdown.", e); } } } /** *

* Add the given {@link org.quartz.spi.SchedulerPlugin} to * the Scheduler. This method expects the plugin's * "initialize" method to be invoked externally (either before or after * this method is called). */ public void addSchedulerPlugin(SchedulerPlugin plugin) { schedulerPlugins.add(plugin); } public void setJobFactory(JobFactory factory) throws SchedulerException { if(factory == null) throw new IllegalArgumentException("JobFactory cannot be set to null!"); getLog().info("JobFactory set to: " + factory); this.jobFactory = factory; } public JobFactory getJobFactory() { return jobFactory; } /** * Interrupt all instances of the identified InterruptableJob. * * @see org.quartz.core.RemotableQuartzScheduler#interrupt(java.lang.String, java.lang.String) */ public boolean interrupt(SchedulingContext ctxt, String jobName, String groupName) throws UnableToInterruptJobException { if(groupName == null) groupName = Scheduler.DEFAULT_GROUP; List jobs = getCurrentlyExecutingJobs(); java.util.Iterator it = jobs.iterator(); JobExecutionContext jec = null; JobDetail jobDetail = null; Job job = null; boolean interrupted = false; while (it.hasNext()) { jec = (JobExecutionContext)it.next(); jobDetail = jec.getJobDetail(); if (jobName.equals(jobDetail.getName()) && groupName.equals(jobDetail.getGroup())){ job = jec.getJobInstance(); if (job instanceof InterruptableJob) { ((InterruptableJob)job).interrupt(); interrupted = true; } else { throw new UnableToInterruptJobException( "Job '" + jobName + "' of group '" + groupName + "' can not be interrupted, since it does not implement " + InterruptableJob.class.getName()); } } } return interrupted; } private void shutdownPlugins() { java.util.Iterator itr = schedulerPlugins.iterator(); while (itr.hasNext()) { SchedulerPlugin plugin = (SchedulerPlugin) itr.next(); plugin.shutdown(); } } private void startPlugins() { java.util.Iterator itr = schedulerPlugins.iterator(); while (itr.hasNext()) { SchedulerPlugin plugin = (SchedulerPlugin) itr.next(); plugin.start(); } } } ///////////////////////////////////////////////////////////////////////////// // // ErrorLogger - Scheduler Listener Class // ///////////////////////////////////////////////////////////////////////////// class ErrorLogger implements SchedulerListener { public static Log getLog() { return LogFactory.getLog(ErrorLogger.class); } ErrorLogger() { } public void jobScheduled(Trigger trigger) { // do nothing... } public void jobUnscheduled(String triggerName, String triggerGroup) { // do nothing... } public void triggerFinalized(Trigger trigger) { // do nothing... } /** *

* Called by the {@link Scheduler} when a {@link Trigger} * or group of {@link Trigger}s has been paused. *

* *

* If a group was paused, then the triggerName parameter * will be null. *

*/ public void triggersPaused(String triggerName, String triggerGroup) { // do nothing... } /** *

* Called by the {@link Scheduler} when a {@link Trigger} * or group of {@link Trigger}s has been un-paused. *

* *

* If a group was resumed, then the triggerName parameter * will be null. *

*/ public void triggersResumed(String triggerName, String triggerGroup) { // do nothing... } /** *

* Called by the {@link Scheduler} when a {@link org.quartz.JobDetail} * or group of {@link org.quartz.JobDetail}s has been * paused. *

* *

* If a group was paused, then the jobName parameter will be * null. *

*/ public void jobsPaused(String jobName, String jobGroup) { // do nothing... } /** *

* Called by the {@link Scheduler} when a {@link org.quartz.JobDetail} * or group of {@link org.quartz.JobDetail}s has been * un-paused. *

* *

* If a group was paused, then the jobName parameter will be * null. *

*/ public void jobsResumed(String jobName, String jobGroup) { // do nothing... } public void schedulerError(String msg, SchedulerException cause) { getLog().error(msg, cause); } public void schedulerShutdown() { // do nothing... } } ///////////////////////////////////////////////////////////////////////////// // // ExecutingJobsManager - Job Listener Class // ///////////////////////////////////////////////////////////////////////////// class ExecutingJobsManager implements JobListener { HashMap executingJobs = new HashMap(); int numJobsFired = 0; ExecutingJobsManager() { } public String getName() { return getClass().getName(); } public int getNumJobsCurrentlyExecuting() { synchronized (executingJobs) { return executingJobs.size(); } } public void jobToBeExecuted(JobExecutionContext context) { numJobsFired++; synchronized (executingJobs) { executingJobs .put(context.getTrigger().getFireInstanceId(), context); } } public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { synchronized (executingJobs) { executingJobs.remove(context.getTrigger().getFireInstanceId()); } } public int getNumJobsFired() { return numJobsFired; } public List getExecutingJobs() { synchronized (executingJobs) { return java.util.Collections.unmodifiableList(new ArrayList( executingJobs.values())); } } public void jobExecutionVetoed(JobExecutionContext context) { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy