org.quartz.core.QuartzScheduler Maven / Gradle / Ivy
/*
* 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 Trigger
s.
*
*
* @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 Trigger
s.
*
*
*/
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 Trigger
s.
*
*
*/
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 JobListener
s.
*/
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 TriggerListener
s.
*/
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) {
}
}