📄 quartzscheduler.java
字号:
/*
* 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.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import org.apache.commons.logging.Log;
import 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.listeners.SchedulerListenerSupport;
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;
/**
* <p>
* This is the heart of Quartz, an indirect implementation of the <code>{@link org.quartz.Scheduler}</code>
* interface, containing methods to schedule <code>{@link org.quartz.Job}</code>s,
* register <code>{@link org.quartz.JobListener}</code> instances, etc.
* </p>// 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();
InputStream is = null;
try {
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) {
(LogFactory.getLog(QuartzScheduler.class)).error(
"Error loading version info from 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 HashMap jobListeners = new HashMap(10);
private HashMap globalJobListeners = new HashMap(10);
private HashMap triggerListeners = new HashMap(10);
private HashMap globalTriggerListeners = new HashMap(10);
private ArrayList schedulerListeners = 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 boolean shuttingDown = false;
private Date initialStart = null;
private final Log log = LogFactory.getLog(getClass());
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Constructors.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/**
* <p>
* Create a <code>QuartzScheduler</code> with the given configuration
* properties.
* </p>
*
* @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);
}
if (resources.getJMXExport()) {
try {
registerJMX();
} catch (Exception e) {
throw new SchedulerException(
"Unable to register scheduler with MBeanServer.", e);
}
}
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, this.schedThread);
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 Log getLog() {
return log;
}
/**
* Register the scheduler in the local MBeanServer.
*/
private void registerJMX() throws Exception {
org.apache.commons.modeler.Registry registry =
org.apache.commons.modeler.Registry.getRegistry(null, null);
String jmxObjectName = resources.getJMXObjectName();
registry.registerComponent(this, jmxObjectName, null);
getLog().info("Scheduler registered with local MBeanServer under name '" + jmxObjectName + "'");
}
/**
* Unregister the scheduler from the local MBeanServer.
*/
private void unregisterJMX() throws Exception {
org.apache.commons.modeler.Registry registry =
org.apache.commons.modeler.Registry.getRegistry(null, null);
String jmxObjectName = resources.getJMXObjectName();
registry.unregisterComponent(jmxObjectName);
getLog().info("Scheduler unregistered from name '" + jmxObjectName + "' in the local MBeanServer.");
}
/**
* <p>
* Bind the scheduler to an RMI registry.
* </p>
*/
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);
getLog().info("Scheduler bound to RMI registry under name '" + bindName + "'");
}
/**
* <p>
* Un-bind the scheduler from an RMI registry.
* </p>
*/
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");
}
/**
* <p>
* Returns the name of the <code>QuartzScheduler</code>.
* </p>
*/
public String getSchedulerName() {
return resources.getName();
}
/**
* <p>
* Returns the instance Id of the <code>QuartzScheduler</code>.
* </p>
*/
public String getSchedulerInstanceId() {
return resources.getInstanceId();
}
/**
* <p>
* Returns the name of the <code>QuartzScheduler</code>.
* </p>
*/
public ThreadGroup getSchedulerThreadGroup() {
if (threadGroup == null) {
threadGroup = new ThreadGroup("QuartzScheduler:"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -