Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.logspace.jvm.agent.shaded.quartz.core.QuartzScheduler Maven / Gradle / Ivy
/*
* Copyright 2001-2009 Terracotta, Inc.
*
* 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.
*
*/
package io.logspace.jvm.agent.shaded.quartz.core;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
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.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import io.logspace.jvm.agent.shaded.quartz.Calendar;
import io.logspace.jvm.agent.shaded.quartz.InterruptableJob;
import io.logspace.jvm.agent.shaded.quartz.Job;
import io.logspace.jvm.agent.shaded.quartz.JobDataMap;
import io.logspace.jvm.agent.shaded.quartz.JobDetail;
import io.logspace.jvm.agent.shaded.quartz.JobExecutionContext;
import io.logspace.jvm.agent.shaded.quartz.JobExecutionException;
import io.logspace.jvm.agent.shaded.quartz.JobKey;
import io.logspace.jvm.agent.shaded.quartz.JobListener;
import io.logspace.jvm.agent.shaded.quartz.ListenerManager;
import io.logspace.jvm.agent.shaded.quartz.Matcher;
import io.logspace.jvm.agent.shaded.quartz.ObjectAlreadyExistsException;
import io.logspace.jvm.agent.shaded.quartz.Scheduler;
import io.logspace.jvm.agent.shaded.quartz.SchedulerContext;
import io.logspace.jvm.agent.shaded.quartz.SchedulerException;
import io.logspace.jvm.agent.shaded.quartz.SchedulerListener;
import io.logspace.jvm.agent.shaded.quartz.SchedulerMetaData;
import io.logspace.jvm.agent.shaded.quartz.Trigger;
import static io.logspace.jvm.agent.shaded.quartz.TriggerBuilder.*;
import io.logspace.jvm.agent.shaded.quartz.TriggerKey;
import io.logspace.jvm.agent.shaded.quartz.TriggerListener;
import io.logspace.jvm.agent.shaded.quartz.UnableToInterruptJobException;
import io.logspace.jvm.agent.shaded.quartz.Trigger.CompletedExecutionInstruction;
import io.logspace.jvm.agent.shaded.quartz.Trigger.TriggerState;
import io.logspace.jvm.agent.shaded.quartz.core.jmx.QuartzSchedulerMBean;
import io.logspace.jvm.agent.shaded.quartz.impl.SchedulerRepository;
import io.logspace.jvm.agent.shaded.quartz.impl.StdSchedulerFactory;
import io.logspace.jvm.agent.shaded.quartz.impl.matchers.GroupMatcher;
import io.logspace.jvm.agent.shaded.quartz.listeners.SchedulerListenerSupport;
import io.logspace.jvm.agent.shaded.quartz.simpl.PropertySettingJobFactory;
import io.logspace.jvm.agent.shaded.quartz.spi.JobFactory;
import io.logspace.jvm.agent.shaded.quartz.spi.OperableTrigger;
import io.logspace.jvm.agent.shaded.quartz.spi.SchedulerPlugin;
import io.logspace.jvm.agent.shaded.quartz.spi.SchedulerSignaler;
import io.logspace.jvm.agent.shaded.quartz.spi.ThreadExecutor;
import io.logspace.jvm.agent.shaded.quartz.utils.UpdateChecker;
import io.logspace.jvm.agent.shaded.slf4j.Logger;
import io.logspace.jvm.agent.shaded.slf4j.LoggerFactory;
/**
*
* This is the heart of Quartz, an indirect implementation of the {@link io.logspace.jvm.agent.shaded.quartz.Scheduler}
* interface, containing methods to schedule {@link io.logspace.jvm.agent.shaded.quartz.Job}
s,
* register {@link io.logspace.jvm.agent.shaded.quartz.JobListener}
instances, etc.
*
*
* @see io.logspace.jvm.agent.shaded.quartz.Scheduler
* @see io.logspace.jvm.agent.shaded.quartz.core.QuartzSchedulerThread
* @see io.logspace.jvm.agent.shaded.quartz.spi.JobStore
* @see io.logspace.jvm.agent.shaded.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();
InputStream is = null;
try {
is = QuartzScheduler.class.getResourceAsStream("quartz-build.properties");
if(is != null) {
props.load(is);
String version = props.getProperty("version");
if (version != null) {
String[] versionComponents = version.split("\\.");
VERSION_MAJOR = versionComponents[0];
VERSION_MINOR = versionComponents[1];
if(versionComponents.length > 2)
VERSION_ITERATION = versionComponents[2];
else
VERSION_ITERATION = "0";
} else {
(LoggerFactory.getLogger(QuartzScheduler.class)).error(
"Can't parse Quartz version from quartz-build.properties");
}
}
} catch (Exception e) {
(LoggerFactory.getLogger(QuartzScheduler.class)).error(
"Error loading version info from quartz-build.properties.", e);
} finally {
if(is != null) {
try { is.close(); } catch(Exception ignore) {}
}
}
}
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Data members.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
private QuartzSchedulerResources resources;
private QuartzSchedulerThread schedThread;
private ThreadGroup threadGroup;
private SchedulerContext context = new SchedulerContext();
private ListenerManager listenerManager = new ListenerManagerImpl();
private HashMap internalJobListeners = new HashMap(10);
private HashMap internalTriggerListeners = new HashMap(10);
private ArrayList internalSchedulerListeners = new ArrayList(10);
private JobFactory jobFactory = new PropertySettingJobFactory();
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 volatile boolean closed = false;
private volatile boolean shuttingDown = false;
private boolean boundRemotely = false;
private QuartzSchedulerMBean jmxBean = null;
private Date initialStart = null;
/** Update timer that must be cancelled upon shutdown. */
private final Timer updateTimer;
private final Logger log = LoggerFactory.getLogger(getClass());
// private static final Map MGMT_SVR_BY_BIND = new
// HashMap();
// private String registeredManagementServerBind;
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Constructors.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/**
*
* Create a QuartzScheduler
with the given configuration
* properties.
*
*
* @see QuartzSchedulerResources
*/
public QuartzScheduler(QuartzSchedulerResources resources, long idleWaitTime, @Deprecated long dbRetryInterval)
throws SchedulerException {
this.resources = resources;
if (resources.getJobStore() instanceof JobListener) {
addInternalJobListener((JobListener)resources.getJobStore());
}
this.schedThread = new QuartzSchedulerThread(this, resources);
ThreadExecutor schedThreadExecutor = resources.getThreadExecutor();
schedThreadExecutor.execute(this.schedThread);
if (idleWaitTime > 0) {
this.schedThread.setIdleWaitTime(idleWaitTime);
}
jobMgr = new ExecutingJobsManager();
addInternalJobListener(jobMgr);
errLogger = new ErrorLogger();
addInternalSchedulerListener(errLogger);
signaler = new SchedulerSignalerImpl(this, this.schedThread);
if(shouldRunUpdateCheck())
updateTimer = scheduleUpdateCheck();
else
updateTimer = null;
getLog().info("Quartz Scheduler v." + getVersion() + " created.");
}
public void initialize() throws SchedulerException {
try {
bind();
} catch (Exception re) {
throw new SchedulerException(
"Unable to bind scheduler to RMI Registry.", re);
}
if (resources.getJMXExport()) {
try {
registerJMX();
} catch (Exception e) {
throw new SchedulerException(
"Unable to register scheduler with MBeanServer.", e);
}
}
// ManagementRESTServiceConfiguration managementRESTServiceConfiguration
// = resources.getManagementRESTServiceConfiguration();
//
// if (managementRESTServiceConfiguration != null &&
// managementRESTServiceConfiguration.isEnabled()) {
// try {
// /**
// * ManagementServer will only be instantiated and started if one
// * isn't already running on the configured port for this class
// * loader space.
// */
// synchronized (QuartzScheduler.class) {
// if
// (!MGMT_SVR_BY_BIND.containsKey(managementRESTServiceConfiguration.getBind()))
// {
// Class managementServerImplClass =
// Class.forName("io.logspace.jvm.agent.shaded.quartz.management.ManagementServerImpl");
// Class managementRESTServiceConfigurationClass[] = new Class[] {
// managementRESTServiceConfiguration.getClass() };
// Constructor managementRESTServiceConfigurationConstructor =
// managementServerImplClass
// .getConstructor(managementRESTServiceConfigurationClass);
// Object arglist[] = new Object[] { managementRESTServiceConfiguration
// };
// ManagementServer embeddedRESTServer = ((ManagementServer)
// managementRESTServiceConfigurationConstructor.newInstance(arglist));
// embeddedRESTServer.start();
// MGMT_SVR_BY_BIND.put(managementRESTServiceConfiguration.getBind(),
// embeddedRESTServer);
// }
// registeredManagementServerBind =
// managementRESTServiceConfiguration.getBind();
// ManagementServer embeddedRESTServer =
// MGMT_SVR_BY_BIND.get(registeredManagementServerBind);
// embeddedRESTServer.register(this);
// }
// } catch (Exception e) {
// throw new
// SchedulerException("Unable to start the scheduler management REST service",
// e);
// }
// }
getLog().info("Scheduler meta-data: " +
(new SchedulerMetaData(getSchedulerName(),
getSchedulerInstanceId(), getClass(), boundRemotely, runningSince() != null,
isInStandbyMode(), isShutdown(), runningSince(),
numJobsExecuted(), getJobStoreClass(),
supportsPersistence(), isClustered(), getThreadPoolClass(),
getThreadPoolSize(), getVersion())).toString());
}
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Interface.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
public String getVersion() {
return getVersionMajor() + "." + getVersionMinor() + "."
+ getVersionIteration();
}
public static String getVersionMajor() {
return VERSION_MAJOR;
}
private boolean shouldRunUpdateCheck() {
if(resources.isRunUpdateCheck() && !Boolean.getBoolean(StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK) &&
!Boolean.getBoolean("io.logspace.jvm.agent.shaded.terracotta.quartz.skipUpdateCheck")) {
return true;
}
return false;
}
public static String getVersionMinor() {
return VERSION_MINOR;
}
public static String getVersionIteration() {
return VERSION_ITERATION;
}
public SchedulerSignaler getSchedulerSignaler() {
return signaler;
}
public Logger getLog() {
return log;
}
/**
* Update checker scheduler - fires every week
*/
private Timer scheduleUpdateCheck() {
Timer rval = new Timer(true);
rval.scheduleAtFixedRate(new UpdateChecker(), 1000, 7 * 24 * 60 * 60 * 1000L);
return rval;
}
/**
* Register the scheduler in the local MBeanServer.
*/
private void registerJMX() throws Exception {
String jmxObjectName = resources.getJMXObjectName();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
jmxBean = new QuartzSchedulerMBeanImpl(this);
mbs.registerMBean(jmxBean, new ObjectName(jmxObjectName));
}
/**
* Unregister the scheduler from the local MBeanServer.
*/
private void unregisterJMX() throws Exception {
String jmxObjectName = resources.getJMXObjectName();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.unregisterMBean(new ObjectName(jmxObjectName));
jmxBean.setSampledStatisticsEnabled(false);
getLog().info("Scheduler unregistered from name '" + jmxObjectName + "' in the local MBeanServer.");
}
/**
*
* 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());
}
String bindName = resources.getRMIBindName();
registry.rebind(bindName, exportable);
boundRemotely = true;
getLog().info("Scheduler bound to RMI registry under name '" + bindName + "'");
}
/**
*
* 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());
String bindName = resources.getRMIBindName();
try {
registry.unbind(bindName);
UnicastRemoteObject.unexportObject(this, true);
} catch (java.rmi.NotBoundException nbe) {
}
getLog().info("Scheduler un-bound from name '" + bindName + "' in 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 thread group for Quartz's main threads.
*
*/
public ThreadGroup getSchedulerThreadGroup() {
if (threadGroup == null) {
threadGroup = new ThreadGroup("QuartzScheduler:"
+ getSchedulerName());
if (resources.getMakeSchedulerThreadDaemon()) {
threadGroup.setDaemon(true);
}
}
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;
}
///////////////////////////////////////////////////////////////////////////
///
/// Scheduler State Management Methods
///
///////////////////////////////////////////////////////////////////////////
/**
*
* Starts the QuartzScheduler
's threads that fire {@link io.logspace.jvm.agent.shaded.quartz.Trigger}s
.
*
*
*
* All {@link io.logspace.jvm.agent.shaded.quartz.Trigger}s
that have misfired will
* be passed to the appropriate TriggerListener(s).
*
*/
public void start() throws SchedulerException {
if (shuttingDown|| closed) {
throw new SchedulerException(
"The Scheduler cannot be restarted after shutdown() has been called.");
}
// QTZ-212 : calling new schedulerStarting() method on the listeners
// right after entering start()
notifySchedulerListenersStarting();
if (initialStart == null) {
initialStart = new Date();
this.resources.getJobStore().schedulerStarted();
startPlugins();
} else {
resources.getJobStore().schedulerResumed();
}
schedThread.togglePause(false);
getLog().info(
"Scheduler " + resources.getUniqueIdentifier() + " started.");
notifySchedulerListenersStarted();
}
public void startDelayed(final int seconds) throws SchedulerException
{
if (shuttingDown || closed) {
throw new SchedulerException(
"The Scheduler cannot be restarted after shutdown() has been called.");
}
Thread t = new Thread(new Runnable() {
public void run() {
try { Thread.sleep(seconds * 1000L); }
catch(InterruptedException ignore) {}
try { start(); }
catch(SchedulerException se) {
getLog().error("Unable to start secheduler after startup delay.", se);
}
}
});
t.start();
}
/**
*
* Temporarily halts the QuartzScheduler
's firing of {@link io.logspace.jvm.agent.shaded.quartz.Trigger}s
.
*
*
*
* The scheduler is not destroyed, and can be re-started at any time.
*
*/
public void standby() {
resources.getJobStore().schedulerPaused();
schedThread.togglePause(true);
getLog().info(
"Scheduler " + resources.getUniqueIdentifier() + " paused.");
notifySchedulerListenersInStandbyMode();
}
/**
*
* Reports whether the Scheduler
is paused.
*
*/
public boolean isInStandbyMode() {
return schedThread.isPaused();
}
public Date runningSince() {
if(initialStart == null)
return null;
return new Date(initialStart.getTime());
}
public int numJobsExecuted() {
return jobMgr.getNumJobsFired();
}
public Class getJobStoreClass() {
return resources.getJobStore().getClass();
}
public boolean supportsPersistence() {
return resources.getJobStore().supportsPersistence();
}
public boolean isClustered() {
return resources.getJobStore().isClustered();
}
public Class getThreadPoolClass() {
return resources.getThreadPool().getClass();
}
public int getThreadPoolSize() {
return resources.getThreadPool().getPoolSize();
}
/**
*
* Halts the QuartzScheduler
's firing of {@link io.logspace.jvm.agent.shaded.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 io.logspace.jvm.agent.shaded.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(shuttingDown || closed) {
return;
}
shuttingDown = true;
getLog().info(
"Scheduler " + resources.getUniqueIdentifier()
+ " shutting down.");
// boolean removeMgmtSvr = false;
// if (registeredManagementServerBind != null) {
// ManagementServer standaloneRestServer =
// MGMT_SVR_BY_BIND.get(registeredManagementServerBind);
//
// try {
// standaloneRestServer.unregister(this);
//
// if (!standaloneRestServer.hasRegistered()) {
// removeMgmtSvr = true;
// standaloneRestServer.stop();
// }
// } catch (Exception e) {
// getLog().warn("Failed to shutdown the ManagementRESTService", e);
// } finally {
// if (removeMgmtSvr) {
// MGMT_SVR_BY_BIND.remove(registeredManagementServerBind);
// }
//
// registeredManagementServerBind = null;
// }
// }
standby();
schedThread.halt(waitForJobsToComplete);
notifySchedulerListenersShuttingdown();
if( (resources.isInterruptJobsOnShutdown() && !waitForJobsToComplete) ||
(resources.isInterruptJobsOnShutdownWithWait() && waitForJobsToComplete)) {
List jobs = getCurrentlyExecutingJobs();
for(JobExecutionContext job: jobs) {
if(job.getJobInstance() instanceof InterruptableJob)
try {
((InterruptableJob)job.getJobInstance()).interrupt();
} catch (Throwable e) {
// do nothing, this was just a courtesy effort
getLog().warn("Encountered error when interrupting job {} during shutdown: {}", job.getJobDetail().getKey(), e);
}
}
}
resources.getThreadPool().shutdown(waitForJobsToComplete);
closed = true;
if (resources.getJMXExport()) {
try {
unregisterJMX();
} catch (Exception e) {
}
}
if(boundRemotely) {
try {
unBind();
} catch (RemoteException re) {
}
}
shutdownPlugins();
resources.getJobStore().shutdown();
notifySchedulerListenersShutdown();
SchedulerRepository.getInstance().remove(resources.getName());
holdToPreventGC.clear();
if(updateTimer != null)
updateTimer.cancel();
getLog().info(
"Scheduler " + resources.getUniqueIdentifier()
+ " shutdown complete.");
}
/**
*
* Reports whether the Scheduler
has been shutdown.
*
*/
public boolean isShutdown() {
return closed;
}
public boolean isShuttingDown() {
return shuttingDown;
}
public boolean isStarted() {
return !shuttingDown && !closed && !isInStandbyMode() && initialStart != null;
}
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 in this Scheduler instance.
*
*
*
* This method is not cluster aware. That is, it will only return Jobs
* currently executing in this Scheduler instance, not across the entire
* cluster.
*
*
*
* 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 io.logspace.jvm.agent.shaded.quartz.Job}
identified by the given
* {@link io.logspace.jvm.agent.shaded.quartz.JobDetail}
to the Scheduler, and
* associate the given {@link io.logspace.jvm.agent.shaded.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(JobDetail jobDetail,
Trigger trigger) throws SchedulerException {
validateState();
if (jobDetail == null) {
throw new SchedulerException("JobDetail cannot be null");
}
if (trigger == null) {
throw new SchedulerException("Trigger cannot be null");
}
if (jobDetail.getKey() == null) {
throw new SchedulerException("Job's key cannot be null");
}
if (jobDetail.getJobClass() == null) {
throw new SchedulerException("Job's class cannot be null");
}
OperableTrigger trig = (OperableTrigger)trigger;
if (trigger.getJobKey() == null) {
trig.setJobKey(jobDetail.getKey());
} else if (!trigger.getJobKey().equals(jobDetail.getKey())) {
throw new SchedulerException(
"Trigger does not reference given job!");
}
trig.validate();
Calendar cal = null;
if (trigger.getCalendarName() != null) {
cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
}
Date ft = trig.computeFirstFireTime(cal);
if (ft == null) {
throw new SchedulerException(
"Based on configured schedule, the given trigger '" + trigger.getKey() + "' will never fire.");
}
resources.getJobStore().storeJobAndTrigger(jobDetail, trig);
notifySchedulerListenersJobAdded(jobDetail);
notifySchedulerThread(trigger.getNextFireTime().getTime());
notifySchedulerListenersSchduled(trigger);
return ft;
}
/**
*
* Schedule the given {@link io.logspace.jvm.agent.shaded.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(Trigger trigger)
throws SchedulerException {
validateState();
if (trigger == null) {
throw new SchedulerException("Trigger cannot be null");
}
OperableTrigger trig = (OperableTrigger)trigger;
trig.validate();
Calendar cal = null;
if (trigger.getCalendarName() != null) {
cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
if(cal == null) {
throw new SchedulerException(
"Calendar not found: " + trigger.getCalendarName());
}
}
Date ft = trig.computeFirstFireTime(cal);
if (ft == null) {
throw new SchedulerException(
"Based on configured schedule, the given trigger '" + trigger.getKey() + "' will never fire.");
}
resources.getJobStore().storeTrigger(trig, false);
notifySchedulerThread(trigger.getNextFireTime().getTime());
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(JobDetail jobDetail, boolean replace) throws SchedulerException {
addJob(jobDetail, replace, false);
}
public void addJob(JobDetail jobDetail, boolean replace, boolean storeNonDurableWhileAwaitingScheduling) throws SchedulerException {
validateState();
if (!storeNonDurableWhileAwaitingScheduling && !jobDetail.isDurable()) {
throw new SchedulerException(
"Jobs added with no trigger must be durable.");
}
resources.getJobStore().storeJob(jobDetail, replace);
notifySchedulerThread(0L);
notifySchedulerListenersJobAdded(jobDetail);
}
/**
*
* 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(JobKey jobKey) throws SchedulerException {
validateState();
boolean result = false;
List triggers = getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
if (!unscheduleJob(trigger.getKey())) {
StringBuilder sb = new StringBuilder().append(
"Unable to unschedule trigger [").append(
trigger.getKey()).append("] while deleting job [")
.append(jobKey).append(
"]");
throw new SchedulerException(sb.toString());
}
result = true;
}
result = resources.getJobStore().removeJob(jobKey) || result;
if (result) {
notifySchedulerThread(0L);
notifySchedulerListenersJobDeleted(jobKey);
}
return result;
}
public boolean deleteJobs(List jobKeys) throws SchedulerException {
validateState();
boolean result = false;
result = resources.getJobStore().removeJobs(jobKeys);
notifySchedulerThread(0L);
for(JobKey key: jobKeys)
notifySchedulerListenersJobDeleted(key);
return result;
}
public void scheduleJobs(Map> triggersAndJobs, boolean replace) throws SchedulerException {
validateState();
// make sure all triggers refer to their associated job
for(Entry> e: triggersAndJobs.entrySet()) {
JobDetail job = e.getKey();
if(job == null) // there can be one of these (for adding a bulk set of triggers for pre-existing jobs)
continue;
Set triggers = e.getValue();
if(triggers == null) // this is possible because the job may be durable, and not yet be having triggers
continue;
for(Trigger trigger: triggers) {
OperableTrigger opt = (OperableTrigger)trigger;
opt.setJobKey(job.getKey());
opt.validate();
Calendar cal = null;
if (trigger.getCalendarName() != null) {
cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
if(cal == null) {
throw new SchedulerException(
"Calendar '" + trigger.getCalendarName() + "' not found for trigger: " + trigger.getKey());
}
}
Date ft = opt.computeFirstFireTime(cal);
if (ft == null) {
throw new SchedulerException(
"Based on configured schedule, the given trigger will never fire.");
}
}
}
resources.getJobStore().storeJobsAndTriggers(triggersAndJobs, replace);
notifySchedulerThread(0L);
for(JobDetail job: triggersAndJobs.keySet())
notifySchedulerListenersJobAdded(job);
}
public void scheduleJob(JobDetail jobDetail, Set triggersForJob,
boolean replace) throws SchedulerException {
Map> triggersAndJobs = new HashMap>();
triggersAndJobs.put(jobDetail, triggersForJob);
scheduleJobs(triggersAndJobs, replace);
}
public boolean unscheduleJobs(List triggerKeys) throws SchedulerException {
validateState();
boolean result = false;
result = resources.getJobStore().removeTriggers(triggerKeys);
notifySchedulerThread(0L);
for(TriggerKey key: triggerKeys)
notifySchedulerListenersUnscheduled(key);
return result;
}
/**
*
* Remove the indicated {@link io.logspace.jvm.agent.shaded.quartz.Trigger}
from the
* scheduler.
*
*/
public boolean unscheduleJob(TriggerKey triggerKey) throws SchedulerException {
validateState();
if (resources.getJobStore().removeTrigger(triggerKey)) {
notifySchedulerThread(0L);
notifySchedulerListenersUnscheduled(triggerKey);
} else {
return false;
}
return true;
}
/**
*
* Remove (delete) the {@link io.logspace.jvm.agent.shaded.quartz.Trigger}
with the
* given name, and store the new given one - which must be associated
* with the same job.
*
* @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(TriggerKey triggerKey,
Trigger newTrigger) throws SchedulerException {
validateState();
if (triggerKey == null) {
throw new IllegalArgumentException("triggerKey cannot be null");
}
if (newTrigger == null) {
throw new IllegalArgumentException("newTrigger cannot be null");
}
OperableTrigger trig = (OperableTrigger)newTrigger;
Trigger oldTrigger = getTrigger(triggerKey);
if (oldTrigger == null) {
return null;
} else {
trig.setJobKey(oldTrigger.getJobKey());
}
trig.validate();
Calendar cal = null;
if (newTrigger.getCalendarName() != null) {
cal = resources.getJobStore().retrieveCalendar(
newTrigger.getCalendarName());
}
Date ft = trig.computeFirstFireTime(cal);
if (ft == null) {
throw new SchedulerException(
"Based on configured schedule, the given trigger will never fire.");
}
if (resources.getJobStore().replaceTrigger(triggerKey, trig)) {
notifySchedulerThread(newTrigger.getNextFireTime().getTime());
notifySchedulerListenersUnscheduled(triggerKey);
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 io.logspace.jvm.agent.shaded.quartz.Job}
(execute it
* now) - with a non-volatile trigger.
*
*/
@SuppressWarnings("deprecation")
public void triggerJob(JobKey jobKey, JobDataMap data) throws SchedulerException {
validateState();
OperableTrigger trig = (OperableTrigger) newTrigger().withIdentity(newTriggerId(), Scheduler.DEFAULT_GROUP).forJob(jobKey).build();
trig.computeFirstFireTime(null);
if(data != null) {
trig.setJobDataMap(data);
}
boolean collision = true;
while (collision) {
try {
resources.getJobStore().storeTrigger(trig, false);
collision = false;
} catch (ObjectAlreadyExistsException oaee) {
trig.setKey(new TriggerKey(newTriggerId(), Scheduler.DEFAULT_GROUP));
}
}
notifySchedulerThread(trig.getNextFireTime().getTime());
notifySchedulerListenersSchduled(trig);
}
/**
*
* Store and schedule the identified {@link io.logspace.jvm.agent.shaded.quartz.spi.OperableTrigger}
*
*/
public void triggerJob(OperableTrigger trig) throws SchedulerException {
validateState();
trig.computeFirstFireTime(null);
boolean collision = true;
while (collision) {
try {
resources.getJobStore().storeTrigger(trig, false);
collision = false;
} catch (ObjectAlreadyExistsException oaee) {
trig.setKey(new TriggerKey(newTriggerId(), Scheduler.DEFAULT_GROUP));
}
}
notifySchedulerThread(trig.getNextFireTime().getTime());
notifySchedulerListenersSchduled(trig);
}
/**
*
* Pause the {@link Trigger}
with the given name.
*
*
*/
public void pauseTrigger(TriggerKey triggerKey) throws SchedulerException {
validateState();
resources.getJobStore().pauseTrigger(triggerKey);
notifySchedulerThread(0L);
notifySchedulerListenersPausedTrigger(triggerKey);
}
/**
*
* Pause all of the {@link Trigger}s
in the matching groups.
*
*
*/
public void pauseTriggers(GroupMatcher matcher)
throws SchedulerException {
validateState();
if(matcher == null) {
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
}
Collection pausedGroups = resources.getJobStore().pauseTriggers(matcher);
notifySchedulerThread(0L);
for (String pausedGroup : pausedGroups) {
notifySchedulerListenersPausedTriggers(pausedGroup);
}
}
/**
*
* Pause the {@link io.logspace.jvm.agent.shaded.quartz.JobDetail}
with the given
* name - by pausing all of its current Trigger
s.
*
*
*/
public void pauseJob(JobKey jobKey) throws SchedulerException {
validateState();
resources.getJobStore().pauseJob(jobKey);
notifySchedulerThread(0L);
notifySchedulerListenersPausedJob(jobKey);
}
/**
*
* Pause all of the {@link io.logspace.jvm.agent.shaded.quartz.JobDetail}s
in the
* matching groups - by pausing all of their Trigger
s.
*
*
*/
public void pauseJobs(GroupMatcher groupMatcher)
throws SchedulerException {
validateState();
if(groupMatcher == null) {
groupMatcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
}
Collection pausedGroups = resources.getJobStore().pauseJobs(groupMatcher);
notifySchedulerThread(0L);
for (String pausedGroup : pausedGroups) {
notifySchedulerListenersPausedJobs(pausedGroup);
}
}
/**
*
* 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(TriggerKey triggerKey) throws SchedulerException {
validateState();
resources.getJobStore().resumeTrigger(triggerKey);
notifySchedulerThread(0L);
notifySchedulerListenersResumedTrigger(triggerKey);
}
/**
*
* Resume (un-pause) all of the {@link Trigger}s
in the
* matching groups.
*
*
*
* If any Trigger
missed one or more fire-times, then the
* Trigger
's misfire instruction will be applied.
*
*
*/
public void resumeTriggers(GroupMatcher matcher)
throws SchedulerException {
validateState();
if(matcher == null) {
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
}
Collection pausedGroups = resources.getJobStore().resumeTriggers(matcher);
notifySchedulerThread(0L);
for (String pausedGroup : pausedGroups) {
notifySchedulerListenersResumedTriggers(pausedGroup);
}
}
public Set getPausedTriggerGroups() throws SchedulerException {
return resources.getJobStore().getPausedTriggerGroups();
}
/**
*
* Resume (un-pause) the {@link io.logspace.jvm.agent.shaded.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(JobKey jobKey) throws SchedulerException {
validateState();
resources.getJobStore().resumeJob(jobKey);
notifySchedulerThread(0L);
notifySchedulerListenersResumedJob(jobKey);
}
/**
*
* Resume (un-pause) all of the {@link io.logspace.jvm.agent.shaded.quartz.JobDetail}s
* in the matching groups.
*
*
*
* 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 resumeJobs(GroupMatcher matcher)
throws SchedulerException {
validateState();
if(matcher == null) {
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
}
Collection resumedGroups = resources.getJobStore().resumeJobs(matcher);
notifySchedulerThread(0L);
for (String pausedGroup : resumedGroups) {
notifySchedulerListenersResumedJobs(pausedGroup);
}
}
/**
*
* Pause all triggers - equivalent of calling pauseTriggers(GroupMatcher)
* with a matcher matching all known groups.
*
*
*
* When resumeAll()
is called (to un-pause), trigger misfire
* instructions WILL be applied.
*
*
* @see #resumeAll()
* @see #pauseTriggers(io.logspace.jvm.agent.shaded.quartz.impl.matchers.GroupMatcher)
* @see #standby()
*/
public void pauseAll() throws SchedulerException {
validateState();
resources.getJobStore().pauseAll();
notifySchedulerThread(0L);
notifySchedulerListenersPausedTriggers(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()
*/
public void resumeAll() throws SchedulerException {
validateState();
resources.getJobStore().resumeAll();
notifySchedulerThread(0L);
notifySchedulerListenersResumedTrigger(null);
}
/**
*
* Get the names of all known {@link io.logspace.jvm.agent.shaded.quartz.Job}
groups.
*
*/
public List getJobGroupNames()
throws SchedulerException {
validateState();
return resources.getJobStore().getJobGroupNames();
}
/**
*
* Get the names of all the {@link io.logspace.jvm.agent.shaded.quartz.Job}s
in the
* matching groups.
*
*/
public Set getJobKeys(GroupMatcher matcher)
throws SchedulerException {
validateState();
if(matcher == null) {
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
}
return resources.getJobStore().getJobKeys(matcher);
}
/**
*
* Get all {@link Trigger}
s that are associated with the
* identified {@link io.logspace.jvm.agent.shaded.quartz.JobDetail}
.
*
*/
public List getTriggersOfJob(JobKey jobKey) throws SchedulerException {
validateState();
return resources.getJobStore().getTriggersForJob(jobKey);
}
/**
*
* Get the names of all known {@link io.logspace.jvm.agent.shaded.quartz.Trigger}
* groups.
*
*/
public List getTriggerGroupNames()
throws SchedulerException {
validateState();
return resources.getJobStore().getTriggerGroupNames();
}
/**
*
* Get the names of all the {@link io.logspace.jvm.agent.shaded.quartz.Trigger}s
in
* the matching groups.
*
*/
public Set getTriggerKeys(GroupMatcher matcher)
throws SchedulerException {
validateState();
if(matcher == null) {
matcher = GroupMatcher.groupEquals(Scheduler.DEFAULT_GROUP);
}
return resources.getJobStore().getTriggerKeys(matcher);
}
/**
*
* Get the {@link JobDetail}
for the Job
* instance with the given name and group.
*
*/
public JobDetail getJobDetail(JobKey jobKey) throws SchedulerException {
validateState();
return resources.getJobStore().retrieveJob(jobKey);
}
/**
*
* Get the {@link Trigger}
instance with the given name and
* group.
*
*/
public Trigger getTrigger(TriggerKey triggerKey) throws SchedulerException {
validateState();
return resources.getJobStore().retrieveTrigger(triggerKey);
}
/**
* Determine whether a {@link Job} with the given identifier already
* exists within the scheduler.
*
* @param jobKey the identifier to check for
* @return true if a Job exists with the given identifier
* @throws SchedulerException
*/
public boolean checkExists(JobKey jobKey) throws SchedulerException {
validateState();
return resources.getJobStore().checkExists(jobKey);
}
/**
* Determine whether a {@link Trigger} with the given identifier already
* exists within the scheduler.
*
* @param triggerKey the identifier to check for
* @return true if a Trigger exists with the given identifier
* @throws SchedulerException
*/
public boolean checkExists(TriggerKey triggerKey) throws SchedulerException {
validateState();
return resources.getJobStore().checkExists(triggerKey);
}
/**
* Clears (deletes!) all scheduling data - all {@link Job}s, {@link Trigger}s
* {@link Calendar}s.
*
* @throws SchedulerException
*/
public void clear() throws SchedulerException {
validateState();
resources.getJobStore().clearAllSchedulingData();
notifySchedulerListenersUnscheduled(null);
}
/**
*
* Get the current state of the identified {@link Trigger}
.
*
J *
* @see TriggerState
*/
public TriggerState getTriggerState(TriggerKey triggerKey) throws SchedulerException {
validateState();
return resources.getJobStore().getTriggerState(triggerKey);
}
/**
*
* 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(String calName, Calendar calendar, boolean replace, boolean updateTriggers) throws SchedulerException {
validateState();
resources.getJobStore().storeCalendar(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(String calName)
throws SchedulerException {
validateState();
return resources.getJobStore().removeCalendar(calName);
}
/**
*
* Get the {@link Calendar}
instance with the given name.
*
*/
public Calendar getCalendar(String calName)
throws SchedulerException {
validateState();
return resources.getJobStore().retrieveCalendar(calName);
}
/**
*
* Get the names of all registered {@link Calendar}s
.
*
*/
public List getCalendarNames()
throws SchedulerException {
validateState();
return resources.getJobStore().getCalendarNames();
}
public ListenerManager getListenerManager() {
return listenerManager;
}
/**
*
* Add the given {@link io.logspace.jvm.agent.shaded.quartz.JobListener}
to the
* Scheduler
's internal list.
*
*/
public void addInternalJobListener(JobListener jobListener) {
if (jobListener.getName() == null
|| jobListener.getName().length() == 0) {
throw new IllegalArgumentException(
"JobListener name cannot be empty.");
}
synchronized (internalJobListeners) {
internalJobListeners.put(jobListener.getName(), jobListener);
}
}
/**
*
* Remove the identified {@link JobListener}
from the Scheduler
's
* list of internal listeners.
*
*
* @return true if the identified listener was found in the list, and
* removed.
*/
public boolean removeInternalJobListener(String name) {
synchronized (internalJobListeners) {
return (internalJobListeners.remove(name) != null);
}
}
/**
*
* Get a List containing all of the {@link io.logspace.jvm.agent.shaded.quartz.JobListener}
s
* in the Scheduler
's internal list.
*
*/
public List getInternalJobListeners() {
synchronized (internalJobListeners) {
return java.util.Collections.unmodifiableList(new LinkedList(internalJobListeners.values()));
}
}
/**
*
* Get the internal {@link io.logspace.jvm.agent.shaded.quartz.JobListener}
* that has the given name.
*
*/
public JobListener getInternalJobListener(String name) {
synchronized (internalJobListeners) {
return internalJobListeners.get(name);
}
}
/**
*
* Add the given {@link io.logspace.jvm.agent.shaded.quartz.TriggerListener}
to the
* Scheduler
's internal list.
*
*/
public void addInternalTriggerListener(TriggerListener triggerListener) {
if (triggerListener.getName() == null
|| triggerListener.getName().length() == 0) {
throw new IllegalArgumentException(
"TriggerListener name cannot be empty.");
}
synchronized (internalTriggerListeners) {
internalTriggerListeners.put(triggerListener.getName(), triggerListener);
}
}
/**
*
* Remove the identified {@link TriggerListener}
from the Scheduler
's
* list of internal listeners.
*
*
* @return true if the identified listener was found in the list, and
* removed.
*/
public boolean removeinternalTriggerListener(String name) {
synchronized (internalTriggerListeners) {
return (internalTriggerListeners.remove(name) != null);
}
}
/**
*
* Get a list containing all of the {@link io.logspace.jvm.agent.shaded.quartz.TriggerListener}
s
* in the Scheduler
's internal list.
*
*/
public List getInternalTriggerListeners() {
synchronized (internalTriggerListeners) {
return java.util.Collections.unmodifiableList(new LinkedList(internalTriggerListeners.values()));
}
}
/**
*
* Get the internal {@link TriggerListener}
that
* has the given name.
*
*/
public TriggerListener getInternalTriggerListener(String name) {
synchronized (internalTriggerListeners) {
return internalTriggerListeners.get(name);
}
}
/**
*
* Register the given {@link SchedulerListener}
with the
* Scheduler
's list of internal listeners.
*
*/
public void addInternalSchedulerListener(SchedulerListener schedulerListener) {
synchronized (internalSchedulerListeners) {
internalSchedulerListeners.add(schedulerListener);
}
}
/**
*
* Remove the given {@link SchedulerListener}
from the
* Scheduler
's list of internal listeners.
*
*
* @return true if the identified listener was found in the list, and
* removed.
*/
public boolean removeInternalSchedulerListener(SchedulerListener schedulerListener) {
synchronized (internalSchedulerListeners) {
return internalSchedulerListeners.remove(schedulerListener);
}
}
/**
*
* Get a List containing all of the internal {@link SchedulerListener}
s
* registered with the Scheduler
.
*
*/
public List getInternalSchedulerListeners() {
synchronized (internalSchedulerListeners) {
return java.util.Collections.unmodifiableList(new ArrayList(internalSchedulerListeners));
}
}
protected void notifyJobStoreJobComplete(OperableTrigger trigger, JobDetail detail, CompletedExecutionInstruction instCode) {
resources.getJobStore().triggeredJobComplete(trigger, detail, instCode);
}
protected void notifyJobStoreJobVetoed(OperableTrigger trigger, JobDetail detail, CompletedExecutionInstruction instCode) {
resources.getJobStore().triggeredJobComplete(trigger, detail, instCode);
}
protected void notifySchedulerThread(long candidateNewNextFireTime) {
if (isSignalOnSchedulingChange()) {
signaler.signalSchedulingChange(candidateNewNextFireTime);
}
}
private List buildTriggerListenerList()
throws SchedulerException {
List allListeners = new LinkedList();
allListeners.addAll(getListenerManager().getTriggerListeners());
allListeners.addAll(getInternalTriggerListeners());
return allListeners;
}
private List buildJobListenerList()
throws SchedulerException {
List allListeners = new LinkedList();
allListeners.addAll(getListenerManager().getJobListeners());
allListeners.addAll(getInternalJobListeners());
return allListeners;
}
private List buildSchedulerListenerList() {
List allListeners = new LinkedList();
allListeners.addAll(getListenerManager().getSchedulerListeners());
allListeners.addAll(getInternalSchedulerListeners());
return allListeners;
}
private boolean matchJobListener(JobListener listener, JobKey key) {
List> matchers = getListenerManager().getJobListenerMatchers(listener.getName());
if(matchers == null)
return true;
for(Matcher matcher: matchers) {
if(matcher.isMatch(key))
return true;
}
return false;
}
private boolean matchTriggerListener(TriggerListener listener, TriggerKey key) {
List> matchers = getListenerManager().getTriggerListenerMatchers(listener.getName());
if(matchers == null)
return true;
for(Matcher matcher: matchers) {
if(matcher.isMatch(key))
return true;
}
return false;
}
public boolean notifyTriggerListenersFired(JobExecutionContext jec)
throws SchedulerException {
boolean vetoedExecution = false;
// build a list of all trigger listeners that are to be notified...
List triggerListeners = buildTriggerListenerList();
// notify all trigger listeners in the list
for(TriggerListener tl: triggerListeners) {
try {
if(!matchTriggerListener(tl, jec.getTrigger().getKey()))
continue;
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);
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();
// notify all trigger listeners in the list
for(TriggerListener tl: triggerListeners) {
try {
if(!matchTriggerListener(tl, trigger.getKey()))
continue;
tl.triggerMisfired(trigger);
} catch (Exception e) {
SchedulerException se = new SchedulerException(
"TriggerListener '" + tl.getName()
+ "' threw exception: " + e.getMessage(), e);
throw se;
}
}
}
public void notifyTriggerListenersComplete(JobExecutionContext jec,
CompletedExecutionInstruction instCode) throws SchedulerException {
// build a list of all trigger listeners that are to be notified...
List triggerListeners = buildTriggerListenerList();
// notify all trigger listeners in the list
for(TriggerListener tl: triggerListeners) {
try {
if(!matchTriggerListener(tl, jec.getTrigger().getKey()))
continue;
tl.triggerComplete(jec.getTrigger(), jec, instCode);
} catch (Exception e) {
SchedulerException se = new SchedulerException(
"TriggerListener '" + tl.getName()
+ "' threw exception: " + e.getMessage(), e);
throw se;
}
}
}
public void notifyJobListenersToBeExecuted(JobExecutionContext jec)
throws SchedulerException {
// build a list of all job listeners that are to be notified...
List jobListeners = buildJobListenerList();
// notify all job listeners
for(JobListener jl: jobListeners) {
try {
if(!matchJobListener(jl, jec.getJobDetail().getKey()))
continue;
jl.jobToBeExecuted(jec);
} catch (Exception e) {
SchedulerException se = new SchedulerException(
"JobListener '" + jl.getName() + "' threw exception: "
+ e.getMessage(), e);
throw se;
}
}
}
public void notifyJobListenersWasVetoed(JobExecutionContext jec)
throws SchedulerException {
// build a list of all job listeners that are to be notified...
List jobListeners = buildJobListenerList();
// notify all job listeners
for(JobListener jl: jobListeners) {
try {
if(!matchJobListener(jl, jec.getJobDetail().getKey()))
continue;
jl.jobExecutionVetoed(jec);
} catch (Exception e) {
SchedulerException se = new SchedulerException(
"JobListener '" + jl.getName() + "' threw exception: "
+ e.getMessage(), e);
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();
// notify all job listeners
for(JobListener jl: jobListeners) {
try {
if(!matchJobListener(jl, jec.getJobDetail().getKey()))
continue;
jl.jobWasExecuted(jec, je);
} catch (Exception e) {
SchedulerException se = new SchedulerException(
"JobListener '" + jl.getName() + "' threw exception: "
+ e.getMessage(), e);
throw se;
}
}
}
public void notifySchedulerListenersError(String msg, SchedulerException se) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
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 = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobScheduled(trigger);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of scheduled job."
+ " Triger=" + trigger.getKey(), e);
}
}
}
public void notifySchedulerListenersUnscheduled(TriggerKey triggerKey) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
if(triggerKey == null)
sl.schedulingDataCleared();
else
sl.jobUnscheduled(triggerKey);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of unscheduled job."
+ " Triger=" + (triggerKey == null ? "ALL DATA" : triggerKey), e);
}
}
}
public void notifySchedulerListenersFinalized(Trigger trigger) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.triggerFinalized(trigger);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of finalized trigger."
+ " Triger=" + trigger.getKey(), e);
}
}
}
public void notifySchedulerListenersPausedTrigger(TriggerKey triggerKey) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.triggerPaused(triggerKey);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of paused trigger: "
+ triggerKey, e);
}
}
}
public void notifySchedulerListenersPausedTriggers(String group) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.triggersPaused(group);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of paused trigger group."
+ group, e);
}
}
}
public void notifySchedulerListenersResumedTrigger(TriggerKey key) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.triggerResumed(key);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of resumed trigger: "
+ key, e);
}
}
}
public void notifySchedulerListenersResumedTriggers(String group) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.triggersResumed(group);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of resumed group: "
+ group, e);
}
}
}
public void notifySchedulerListenersPausedJob(JobKey key) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobPaused(key);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of paused job: "
+ key, e);
}
}
}
public void notifySchedulerListenersPausedJobs(String group) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobsPaused(group);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of paused job group: "
+ group, e);
}
}
}
public void notifySchedulerListenersResumedJob(JobKey key) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobResumed(key);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of resumed job: "
+ key, e);
}
}
}
public void notifySchedulerListenersResumedJobs(String group) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobsResumed(group);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of resumed job group: "
+ group, e);
}
}
}
public void notifySchedulerListenersInStandbyMode() {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.schedulerInStandbyMode();
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of inStandByMode.",
e);
}
}
}
public void notifySchedulerListenersStarted() {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.schedulerStarted();
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of startup.",
e);
}
}
}
public void notifySchedulerListenersStarting() {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for (SchedulerListener sl : schedListeners) {
try {
sl.schedulerStarting();
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of startup.",
e);
}
}
}
public void notifySchedulerListenersShutdown() {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.schedulerShutdown();
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of shutdown.",
e);
}
}
}
public void notifySchedulerListenersShuttingdown() {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.schedulerShuttingdown();
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of shutdown.",
e);
}
}
}
public void notifySchedulerListenersJobAdded(JobDetail jobDetail) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobAdded(jobDetail);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of JobAdded.",
e);
}
}
}
public void notifySchedulerListenersJobDeleted(JobKey jobKey) {
// build a list of all scheduler listeners that are to be notified...
List schedListeners = buildSchedulerListenerList();
// notify all scheduler listeners
for(SchedulerListener sl: schedListeners) {
try {
sl.jobDeleted(jobKey);
} catch (Exception e) {
getLog().error(
"Error while notifying SchedulerListener of JobAdded.",
e);
}
}
}
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 executing in
* this Scheduler instance.
*
*
* This method is not cluster aware. That is, it will only interrupt
* instances of the identified InterruptableJob currently executing in this
* Scheduler instance, not across the entire cluster.
*
*
* @see io.logspace.jvm.agent.shaded.quartz.core.RemotableQuartzScheduler#interrupt(JobKey)
*/
public boolean interrupt(JobKey jobKey) throws UnableToInterruptJobException {
List jobs = getCurrentlyExecutingJobs();
JobDetail jobDetail = null;
Job job = null;
boolean interrupted = false;
for(JobExecutionContext jec : jobs) {
jobDetail = jec.getJobDetail();
if (jobKey.equals(jobDetail.getKey())) {
job = jec.getJobInstance();
if (job instanceof InterruptableJob) {
((InterruptableJob)job).interrupt();
interrupted = true;
} else {
throw new UnableToInterruptJobException(
"Job " + jobDetail.getKey() +
" can not be interrupted, since it does not implement " +
InterruptableJob.class.getName());
}
}
}
return interrupted;
}
/**
* Interrupt the identified InterruptableJob executing in this Scheduler instance.
*
*
* This method is not cluster aware. That is, it will only interrupt
* instances of the identified InterruptableJob currently executing in this
* Scheduler instance, not across the entire cluster.
*
*
* @see io.logspace.jvm.agent.shaded.quartz.core.RemotableQuartzScheduler#interrupt(JobKey)
*/
public boolean interrupt(String fireInstanceId) throws UnableToInterruptJobException {
List jobs = getCurrentlyExecutingJobs();
Job job = null;
for(JobExecutionContext jec : jobs) {
if (jec.getFireInstanceId().equals(fireInstanceId)) {
job = jec.getJobInstance();
if (job instanceof InterruptableJob) {
((InterruptableJob)job).interrupt();
return true;
} else {
throw new UnableToInterruptJobException(
"Job " + jec.getJobDetail().getKey() +
" can not be interrupted, since it does not implement " +
InterruptableJob.class.getName());
}
}
}
return false;
}
private void shutdownPlugins() {
java.util.Iterator itr = resources.getSchedulerPlugins().iterator();
while (itr.hasNext()) {
SchedulerPlugin plugin = itr.next();
plugin.shutdown();
}
}
private void startPlugins() {
java.util.Iterator itr = resources.getSchedulerPlugins().iterator();
while (itr.hasNext()) {
SchedulerPlugin plugin = itr.next();
plugin.start();
}
}
}
/////////////////////////////////////////////////////////////////////////////
//
// ErrorLogger - Scheduler Listener Class
//
/////////////////////////////////////////////////////////////////////////////
class ErrorLogger extends SchedulerListenerSupport {
ErrorLogger() {
}
@Override
public void schedulerError(String msg, SchedulerException cause) {
getLog().error(msg, cause);
}
}
/////////////////////////////////////////////////////////////////////////////
//
// ExecutingJobsManager - Job Listener Class
//
/////////////////////////////////////////////////////////////////////////////
class ExecutingJobsManager implements JobListener {
HashMap executingJobs = new HashMap();
AtomicInteger numJobsFired = new AtomicInteger(0);
ExecutingJobsManager() {
}
public String getName() {
return getClass().getName();
}
public int getNumJobsCurrentlyExecuting() {
synchronized (executingJobs) {
return executingJobs.size();
}
}
public void jobToBeExecuted(JobExecutionContext context) {
numJobsFired.incrementAndGet();
synchronized (executingJobs) {
executingJobs
.put(((OperableTrigger)context.getTrigger()).getFireInstanceId(), context);
}
}
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {
synchronized (executingJobs) {
executingJobs.remove(((OperableTrigger)context.getTrigger()).getFireInstanceId());
}
}
public int getNumJobsFired() {
return numJobsFired.get();
}
public List getExecutingJobs() {
synchronized (executingJobs) {
return java.util.Collections.unmodifiableList(new ArrayList(
executingJobs.values()));
}
}
public void jobExecutionVetoed(JobExecutionContext context) {
}
}