Home » quartz-1.6.0 » org » quartz » impl » [javadoc | source]

    1   /* 
    2    * Copyright 2004-2005 OpenSymphony 
    3    * 
    4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
    5    * use this file except in compliance with the License. You may obtain a copy 
    6    * of the License at 
    7    * 
    8    *   http://www.apache.org/licenses/LICENSE-2.0 
    9    *   
   10    * Unless required by applicable law or agreed to in writing, software 
   11    * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
   12    * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
   13    * License for the specific language governing permissions and limitations 
   14    * under the License.
   15    * 
   16    */
   17   
   18   /*
   19    * Previously Copyright (c) 2001-2004 James House
   20    */
   21   package org.quartz.impl;
   22   
   23   import java.beans.BeanInfo;
   24   import java.beans.IntrospectionException;
   25   import java.beans.Introspector;
   26   import java.beans.PropertyDescriptor;
   27   import java.io.BufferedInputStream;
   28   import java.io.File;
   29   import java.io.FileInputStream;
   30   import java.io.IOException;
   31   import java.io.InputStream;
   32   import java.lang.reflect.Method;
   33   import java.security.AccessControlException;
   34   import java.sql.SQLException;
   35   import java.util.Collection;
   36   import java.util.Iterator;
   37   import java.util.Locale;
   38   import java.util.Properties;
   39   
   40   import org.apache.commons.logging.Log;
   41   import org.apache.commons.logging.LogFactory;
   42   import org.quartz.JobListener;
   43   import org.quartz.Scheduler;
   44   import org.quartz.SchedulerConfigException;
   45   import org.quartz.SchedulerException;
   46   import org.quartz.SchedulerFactory;
   47   import org.quartz.TriggerListener;
   48   import org.quartz.core.JobRunShellFactory;
   49   import org.quartz.core.QuartzScheduler;
   50   import org.quartz.core.QuartzSchedulerResources;
   51   import org.quartz.core.SchedulingContext;
   52   import org.quartz.ee.jta.JTAJobRunShellFactory;
   53   import org.quartz.ee.jta.UserTransactionHelper;
   54   import org.quartz.impl.jdbcjobstore.JobStoreSupport;
   55   import org.quartz.impl.jdbcjobstore.Semaphore;
   56   import org.quartz.impl.jdbcjobstore.TablePrefixAware;
   57   import org.quartz.simpl.RAMJobStore;
   58   import org.quartz.simpl.SimpleThreadPool;
   59   import org.quartz.spi.ClassLoadHelper;
   60   import org.quartz.spi.InstanceIdGenerator;
   61   import org.quartz.spi.JobFactory;
   62   import org.quartz.spi.JobStore;
   63   import org.quartz.spi.SchedulerPlugin;
   64   import org.quartz.spi.ThreadPool;
   65   import org.quartz.utils.ConnectionProvider;
   66   import org.quartz.utils.DBConnectionManager;
   67   import org.quartz.utils.JNDIConnectionProvider;
   68   import org.quartz.utils.PoolingConnectionProvider;
   69   import org.quartz.utils.PropertiesParser;
   70   
   71   /**
   72    * <p>
   73    * An implementation of <code>{@link org.quartz.SchedulerFactory}</code> that
   74    * does all of its work of creating a <code>QuartzScheduler</code> instance
   75    * based on the contenents of a <code>Properties</code> file.
   76    * </p>
   77    * 
   78    * <p>
   79    * By default a properties file named "quartz.properties" is loaded from the
   80    * 'current working directory'. If that fails, then the "quartz.properties"
   81    * file located (as a resource) in the org/quartz package is loaded. If you
   82    * wish to use a file other than these defaults, you must define the system
   83    * property 'org.quartz.properties' to point to the file you want.
   84    * </p>
   85    * 
   86    * <p>
   87    * See the sample properties files that are distributed with Quartz for
   88    * information about the various settings available within the file.
   89    * </p>
   90    * 
   91    * <p>
   92    * Alternatively, you can explicitly initialize the factory by calling one of
   93    * the <code>initialize(xx)</code> methods before calling <code>getScheduler()</code>.
   94    * </p>
   95    * 
   96    * <p>
   97    * Instances of the specified <code>{@link org.quartz.spi.JobStore}</code>,
   98    * <code>{@link org.quartz.spi.ThreadPool}</code>, classes will be created
   99    * by name, and then any additional properties specified for them in the config
  100    * file will be set on the instance by calling an equivalent 'set' method. For
  101    * example if the properties file contains the property 
  102    * 'org.quartz.jobStore.myProp = 10' then after the JobStore class has been 
  103    * instantiated, the method 'setMyProp()' will be called on it. Type conversion 
  104    * to primitive Java types (int, long, float, double, boolean, and String) are 
  105    * performed before calling the property's setter method.
  106    * </p>
  107    * 
  108    * @author James House
  109    * @author Anthony Eden
  110    * @author Mohammad Rezaei
  111    */
  112   public class StdSchedulerFactory implements SchedulerFactory {
  113   
  114       /*
  115        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  116        * 
  117        * Constants.
  118        * 
  119        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  120        */
  121   
  122       public static final String PROPERTIES_FILE = "org.quartz.properties";
  123   
  124       public static final String PROP_SCHED_INSTANCE_NAME = "org.quartz.scheduler.instanceName";
  125   
  126       public static final String PROP_SCHED_INSTANCE_ID = "org.quartz.scheduler.instanceId";
  127   
  128       public static final String PROP_SCHED_INSTANCE_ID_GENERATOR_PREFIX = "org.quartz.scheduler.instanceIdGenerator";
  129       
  130       public static final String PROP_SCHED_INSTANCE_ID_GENERATOR_CLASS = 
  131           PROP_SCHED_INSTANCE_ID_GENERATOR_PREFIX + ".class";
  132       
  133       public static final String PROP_SCHED_THREAD_NAME = "org.quartz.scheduler.threadName";
  134   
  135       public static final String PROP_SCHED_JMX_EXPORT = "org.quartz.scheduler.jmx.export";
  136       
  137       public static final String PROP_SCHED_JMX_PROXY = "org.quartz.scheduler.jmx.proxy";
  138   
  139       public static final String PROP_SCHED_JMX_PROXY_CLASS = "org.quartz.scheduler.jmx.proxy.class";
  140   
  141       public static final String PROP_SCHED_JMX_OBJECT_NAME = "org.quartz.scheduler.jmx.objectName";
  142   
  143       public static final String PROP_SCHED_RMI_EXPORT = "org.quartz.scheduler.rmi.export";
  144   
  145       public static final String PROP_SCHED_RMI_PROXY = "org.quartz.scheduler.rmi.proxy";
  146   
  147       public static final String PROP_SCHED_RMI_HOST = "org.quartz.scheduler.rmi.registryHost";
  148   
  149       public static final String PROP_SCHED_RMI_PORT = "org.quartz.scheduler.rmi.registryPort";
  150   
  151       public static final String PROP_SCHED_RMI_SERVER_PORT = "org.quartz.scheduler.rmi.serverPort";
  152   
  153       public static final String PROP_SCHED_RMI_CREATE_REGISTRY = "org.quartz.scheduler.rmi.createRegistry";
  154   
  155       public static final String PROP_SCHED_RMI_BIND_NAME = "org.quartz.scheduler.rmi.bindName";
  156   
  157       public static final String PROP_SCHED_WRAP_JOB_IN_USER_TX = "org.quartz.scheduler.wrapJobExecutionInUserTransaction";
  158   
  159       public static final String PROP_SCHED_USER_TX_URL = "org.quartz.scheduler.userTransactionURL";
  160   
  161       public static final String PROP_SCHED_IDLE_WAIT_TIME = "org.quartz.scheduler.idleWaitTime";
  162   
  163       public static final String PROP_SCHED_DB_FAILURE_RETRY_INTERVAL = "org.quartz.scheduler.dbFailureRetryInterval";
  164   
  165       public static final String PROP_SCHED_MAKE_SCHEDULER_THREAD_DAEMON = "org.quartz.scheduler.makeSchedulerThreadDaemon";
  166   
  167       public static final String PROP_SCHED_CLASS_LOAD_HELPER_CLASS = "org.quartz.scheduler.classLoadHelper.class";
  168   
  169       public static final String PROP_SCHED_JOB_FACTORY_CLASS = "org.quartz.scheduler.jobFactory.class";
  170   
  171       public static final String PROP_SCHED_JOB_FACTORY_PREFIX = "org.quartz.scheduler.jobFactory";
  172   
  173       public static final String PROP_SCHED_CONTEXT_PREFIX = "org.quartz.context.key";
  174   
  175       public static final String PROP_THREAD_POOL_PREFIX = "org.quartz.threadPool";
  176   
  177       public static final String PROP_THREAD_POOL_CLASS = "org.quartz.threadPool.class";
  178   
  179       public static final String PROP_JOB_STORE_PREFIX = "org.quartz.jobStore";
  180   
  181       public static final String PROP_JOB_STORE_LOCK_HANDLER_PREFIX = PROP_JOB_STORE_PREFIX + ".lockHandler";
  182       
  183       public static final String PROP_JOB_STORE_LOCK_HANDLER_CLASS = PROP_JOB_STORE_LOCK_HANDLER_PREFIX + ".class";
  184   
  185       public static final String PROP_TABLE_PREFIX = "tablePrefix";
  186   
  187       public static final String PROP_JOB_STORE_CLASS = "org.quartz.jobStore.class";
  188   
  189       public static final String PROP_JOB_STORE_USE_PROP = "org.quartz.jobStore.useProperties";
  190   
  191       public static final String PROP_DATASOURCE_PREFIX = "org.quartz.dataSource";
  192   
  193       public static final String PROP_CONNECTION_PROVIDER_CLASS = "connectionProvider.class";
  194   
  195       public static final String PROP_DATASOURCE_DRIVER = "driver";
  196   
  197       public static final String PROP_DATASOURCE_URL = "URL";
  198   
  199       public static final String PROP_DATASOURCE_USER = "user";
  200   
  201       public static final String PROP_DATASOURCE_PASSWORD = "password";
  202   
  203       public static final String PROP_DATASOURCE_MAX_CONNECTIONS = "maxConnections";
  204   
  205       public static final String PROP_DATASOURCE_VALIDATION_QUERY = "validationQuery";
  206   
  207       public static final String PROP_DATASOURCE_JNDI_URL = "jndiURL";
  208   
  209       public static final String PROP_DATASOURCE_JNDI_ALWAYS_LOOKUP = "jndiAlwaysLookup";
  210   
  211       public static final String PROP_DATASOURCE_JNDI_INITIAL = "java.naming.factory.initial";
  212   
  213       public static final String PROP_DATASOURCE_JNDI_PROVDER = "java.naming.provider.url";
  214   
  215       public static final String PROP_DATASOURCE_JNDI_PRINCIPAL = "java.naming.security.principal";
  216   
  217       public static final String PROP_DATASOURCE_JNDI_CREDENTIALS = "java.naming.security.credentials";
  218   
  219       public static final String PROP_PLUGIN_PREFIX = "org.quartz.plugin";
  220   
  221       public static final String PROP_PLUGIN_CLASS = "class";
  222   
  223       public static final String PROP_JOB_LISTENER_PREFIX = "org.quartz.jobListener";
  224   
  225       public static final String PROP_TRIGGER_LISTENER_PREFIX = "org.quartz.triggerListener";
  226   
  227       public static final String PROP_LISTENER_CLASS = "class";
  228   
  229       public static final String DEFAULT_INSTANCE_ID = "NON_CLUSTERED";
  230   
  231       public static final String AUTO_GENERATE_INSTANCE_ID = "AUTO";
  232   
  233       /*
  234        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  235        * 
  236        * Data members.
  237        * 
  238        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  239        */
  240   
  241       private SchedulerException initException = null;
  242   
  243       private String propSrc = null;
  244   
  245       private PropertiesParser cfg;
  246   
  247       private final Log log = LogFactory.getLog(getClass());
  248   
  249       //  private Scheduler scheduler;
  250   
  251       /*
  252        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  253        * 
  254        * Constructors.
  255        * 
  256        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  257        */
  258   
  259       /**
  260        * Create an uninitialized StdSchedulerFactory.
  261        */
  262       public StdSchedulerFactory() {
  263       }
  264   
  265       /**
  266        * Create a StdSchedulerFactory that has been initialized via
  267        * <code>{@link #initialize(Properties)}</code>.
  268        * 
  269        * @see #initialize(Properties)
  270        */
  271       public StdSchedulerFactory(Properties props) throws SchedulerException {
  272           initialize(props);
  273       }
  274   
  275       /**
  276        * Create a StdSchedulerFactory that has been initialized via
  277        * <code>{@link #initialize(String)}</code>.
  278        * 
  279        * @see #initialize(String)
  280        */
  281       public StdSchedulerFactory(String fileName) throws SchedulerException {
  282           initialize(fileName);
  283       }
  284   
  285       /*
  286        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  287        * 
  288        * Interface.
  289        * 
  290        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  291        */
  292   
  293       public Log getLog() {
  294           return log;
  295       }
  296   
  297       /**
  298        * <p>
  299        * Initialize the <code>{@link org.quartz.SchedulerFactory}</code> with
  300        * the contents of a <code>Properties</code> file and overriding System 
  301        * properties.
  302        * </p>
  303        * 
  304        * <p>
  305        * By default a properties file named "quartz.properties" is loaded from
  306        * the 'current working directory'. If that fails, then the
  307        * "quartz.properties" file located (as a resource) in the org/quartz
  308        * package is loaded. If you wish to use a file other than these defaults,
  309        * you must define the system property 'org.quartz.properties' to point to
  310        * the file you want.
  311        * </p>
  312        * 
  313        * <p>
  314        * System properties (environment variables, and -D definitions on the
  315        * command-line when running the JVM) override any properties in the
  316        * loaded file.  For this reason, you may want to use a different initialize()
  317        * method if your application security policy prohibits access to 
  318        * <code>{@link java.lang.System#getProperties()}</code>.
  319        * </p>
  320        */
  321       public void initialize() throws SchedulerException {
  322           // short-circuit if already initialized
  323           if (cfg != null) {
  324               return;
  325           }
  326           if (initException != null) {
  327               throw initException;
  328           }
  329   
  330           String requestedFile = System.getProperty(PROPERTIES_FILE);
  331           String propFileName = requestedFile != null ? requestedFile
  332                   : "quartz.properties";
  333           File propFile = new File(propFileName);
  334   
  335           Properties props = new Properties();
  336   
  337           if (propFile.exists()) {
  338               try {
  339                   if (requestedFile != null) {
  340                       propSrc = "specified file: '" + requestedFile + "'";
  341                   } else {
  342                       propSrc = "default file in current working dir: 'quartz.properties'";
  343                   }
  344   
  345                   props.load(new BufferedInputStream(new FileInputStream(
  346                           propFileName)));
  347   
  348               } catch (IOException ioe) {
  349                   initException = new SchedulerException("Properties file: '"
  350                           + propFileName + "' could not be read.", ioe);
  351                   throw initException;
  352               }
  353           } else if (requestedFile != null) {
  354               InputStream in = 
  355                   Thread.currentThread().getContextClassLoader().getResourceAsStream(requestedFile);
  356   
  357               if(in == null) {
  358                   initException = new SchedulerException("Properties file: '"
  359                       + requestedFile + "' could not be found.");
  360                   throw initException;
  361               }
  362               
  363               propSrc = "specified file: '" + requestedFile + "' in the class resource path.";
  364               
  365               try {
  366                   props.load(new BufferedInputStream(in));
  367               } catch (IOException ioe) {
  368                   initException = new SchedulerException("Properties file: '"
  369                           + requestedFile + "' could not be read.", ioe);
  370                   throw initException;
  371               }
  372               
  373           } else {
  374               propSrc = "default resource file in Quartz package: 'quartz.properties'";
  375   
  376               InputStream in = getClass().getClassLoader().getResourceAsStream(
  377                       "quartz.properties");
  378   
  379               if (in == null) {
  380                   in = getClass().getClassLoader().getResourceAsStream(
  381                           "/quartz.properties");
  382               }
  383               if (in == null) {
  384                   in = getClass().getClassLoader().getResourceAsStream(
  385                           "org/quartz/quartz.properties");
  386               }
  387               if (in == null) {
  388                   initException = new SchedulerException(
  389                           "Default quartz.properties not found in class path");
  390                   throw initException;
  391               }
  392               try {
  393                   props.load(in);
  394               } catch (IOException ioe) {
  395                   initException = new SchedulerException(
  396                           "Resource properties file: 'org/quartz/quartz.properties' "
  397                                   + "could not be read from the classpath.", ioe);
  398                   throw initException;
  399               }
  400           }
  401           
  402           initialize(overrideWithSysProps(props));
  403       }
  404   
  405       /**
  406        * Add all System properties to the given <code>props</code>.  Will override
  407        * any properties that already exist in the given <code>props</code>.
  408        */
  409       private Properties overrideWithSysProps(Properties props) {
  410           Properties sysProps = null;
  411           try {
  412               sysProps = System.getProperties();
  413           } catch (AccessControlException e) {
  414               getLog().warn(
  415                   "Skipping overriding quartz properties with System properties " +
  416                   "during initialization because of an AccessControlException.  " +
  417                   "This is likely due to not having read/write access for " +
  418                   "java.util.PropertyPermission as required by java.lang.System.getProperties().  " +
  419                   "To resolve this warning, either add this permission to your policy file or " +
  420                   "use a non-default version of initialize().", 
  421                   e);
  422           }
  423           
  424           if (sysProps != null) {
  425               props.putAll(sysProps);
  426           }
  427   
  428           return props;
  429       }
  430   
  431       /**
  432        * <p>
  433        * Initialize the <code>{@link org.quartz.SchedulerFactory}</code> with
  434        * the contenents of the <code>Properties</code> file with the given
  435        * name.
  436        * </p>
  437        */
  438       public void initialize(String filename) throws SchedulerException {
  439           // short-circuit if already initialized
  440           if (cfg != null) {
  441               return;
  442           }
  443           
  444           if (initException != null) {
  445               throw initException;
  446           }
  447   
  448           InputStream is = null;
  449           Properties props = new Properties();
  450   
  451           is = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
  452            
  453           try {
  454               if(is != null) {
  455                   is = new BufferedInputStream(is);
  456                   propSrc = "the specified file : '" + filename + "' from the class resource path.";
  457               } else {
  458                   is = new BufferedInputStream(new FileInputStream(filename));
  459                   propSrc = "the specified file : '" + filename + "'";
  460               }
  461               props.load(is);
  462           } catch (IOException ioe) {
  463               initException = new SchedulerException("Properties file: '"
  464                       + filename + "' could not be read.", ioe);
  465               throw initException;
  466           }
  467   
  468           initialize(props);
  469       }
  470   
  471       /**
  472        * <p>
  473        * Initialize the <code>{@link org.quartz.SchedulerFactory}</code> with
  474        * the contenents of the <code>Properties</code> file opened with the
  475        * given <code>InputStream</code>.
  476        * </p>
  477        */
  478       public void initialize(InputStream propertiesStream)
  479           throws SchedulerException {
  480           // short-circuit if already initialized
  481           if (cfg != null) {
  482               return;
  483           }
  484           
  485           if (initException != null) {
  486               throw initException;
  487           }
  488   
  489           Properties props = new Properties();
  490   
  491           if (propertiesStream != null) {
  492               try {
  493                   props.load(propertiesStream);
  494                   propSrc = "an externally opened InputStream.";
  495               } catch (IOException e) {
  496                   initException = new SchedulerException(
  497                           "Error loading property data from InputStream", e);
  498                   throw initException;
  499               }
  500           } else {
  501               initException = new SchedulerException(
  502                       "Error loading property data from InputStream - InputStream is null.");
  503               throw initException;
  504           }
  505   
  506           initialize(props);
  507       }
  508   
  509       /**
  510        * <p>
  511        * Initialize the <code>{@link org.quartz.SchedulerFactory}</code> with
  512        * the contenents of the given <code>Properties</code> object.
  513        * </p>
  514        */
  515       public void initialize(Properties props) throws SchedulerException {
  516           if (propSrc == null) {
  517               propSrc = "an externally provided properties instance.";
  518           }
  519   
  520           this.cfg = new PropertiesParser(props);
  521       }
  522   
  523       private Scheduler instantiate() throws SchedulerException {
  524           if (cfg == null) {
  525               initialize();
  526           }
  527   
  528           if (initException != null) {
  529               throw initException;
  530           }
  531   
  532           JobStore js = null;
  533           ThreadPool tp = null;
  534           QuartzScheduler qs = null;
  535           SchedulingContext schedCtxt = null;
  536           DBConnectionManager dbMgr = null;
  537           String instanceIdGeneratorClass = null;
  538           Properties tProps = null;
  539           String userTXLocation = null;
  540           boolean wrapJobInTx = false;
  541           boolean autoId = false;
  542           long idleWaitTime = -1;
  543           long dbFailureRetry = -1;
  544           String classLoadHelperClass;
  545           String jobFactoryClass;
  546   
  547           SchedulerRepository schedRep = SchedulerRepository.getInstance();
  548   
  549           // Get Scheduler Properties
  550           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  551   
  552           String schedName = cfg.getStringProperty(PROP_SCHED_INSTANCE_NAME,
  553                   "QuartzScheduler");
  554   
  555           String threadName = cfg.getStringProperty(PROP_SCHED_THREAD_NAME,
  556                   schedName + "_QuartzSchedulerThread");
  557           
  558           String schedInstId = cfg.getStringProperty(PROP_SCHED_INSTANCE_ID,
  559                   DEFAULT_INSTANCE_ID);
  560   
  561           if (schedInstId.equals(AUTO_GENERATE_INSTANCE_ID)) {
  562               autoId = true;
  563               instanceIdGeneratorClass = cfg.getStringProperty(
  564                       PROP_SCHED_INSTANCE_ID_GENERATOR_CLASS,
  565                       "org.quartz.simpl.SimpleInstanceIdGenerator");
  566           }
  567           
  568           userTXLocation = cfg.getStringProperty(PROP_SCHED_USER_TX_URL,
  569                   userTXLocation);
  570           if (userTXLocation != null && userTXLocation.trim().length() == 0) {
  571               userTXLocation = null;
  572           }
  573   
  574           classLoadHelperClass = cfg.getStringProperty(
  575                   PROP_SCHED_CLASS_LOAD_HELPER_CLASS,
  576                   "org.quartz.simpl.CascadingClassLoadHelper");
  577           wrapJobInTx = cfg.getBooleanProperty(PROP_SCHED_WRAP_JOB_IN_USER_TX,
  578                   wrapJobInTx);
  579   
  580           jobFactoryClass = cfg.getStringProperty(
  581                   PROP_SCHED_JOB_FACTORY_CLASS, null);
  582   
  583           idleWaitTime = cfg.getLongProperty(PROP_SCHED_IDLE_WAIT_TIME,
  584                   idleWaitTime);
  585           dbFailureRetry = cfg.getLongProperty(
  586                   PROP_SCHED_DB_FAILURE_RETRY_INTERVAL, dbFailureRetry);
  587   
  588           boolean makeSchedulerThreadDaemon = 
  589               cfg.getBooleanProperty(PROP_SCHED_MAKE_SCHEDULER_THREAD_DAEMON);
  590           
  591           boolean jmxExport = cfg.getBooleanProperty(PROP_SCHED_JMX_EXPORT);
  592           boolean jmxProxy = cfg.getBooleanProperty(PROP_SCHED_JMX_PROXY);
  593           String jmxProxyClass = cfg.getStringProperty(PROP_SCHED_JMX_PROXY_CLASS);
  594           String jmxObjectName = cfg.getStringProperty(PROP_SCHED_JMX_OBJECT_NAME);
  595           
  596           boolean rmiExport = cfg.getBooleanProperty(PROP_SCHED_RMI_EXPORT, false);
  597           boolean rmiProxy = cfg.getBooleanProperty(PROP_SCHED_RMI_PROXY, false);
  598           String rmiHost = cfg.getStringProperty(PROP_SCHED_RMI_HOST, "localhost");
  599           int rmiPort = cfg.getIntProperty(PROP_SCHED_RMI_PORT, 1099);
  600           int rmiServerPort = cfg.getIntProperty(PROP_SCHED_RMI_SERVER_PORT, -1);
  601           String rmiCreateRegistry = cfg.getStringProperty(
  602                   PROP_SCHED_RMI_CREATE_REGISTRY,
  603                   QuartzSchedulerResources.CREATE_REGISTRY_NEVER);
  604           String rmiBindName = cfg.getStringProperty(PROP_SCHED_RMI_BIND_NAME);
  605   
  606           if (jmxProxy && rmiProxy) {
  607               throw new SchedulerConfigException("Cannot proxy both RMI and JMX.");
  608           }
  609           
  610           Properties schedCtxtProps = cfg.getPropertyGroup(PROP_SCHED_CONTEXT_PREFIX, true);
  611   
  612           // If Proxying to remote scheduler, short-circuit here...
  613           // ~~~~~~~~~~~~~~~~~~
  614           if (rmiProxy) {
  615   
  616               if (autoId) {  
  617                   schedInstId = DEFAULT_INSTANCE_ID;
  618               }
  619                   
  620               schedCtxt = new SchedulingContext();
  621               schedCtxt.setInstanceId(schedInstId);
  622   
  623               String uid = (rmiBindName == null) ? QuartzSchedulerResources.getUniqueIdentifier(
  624                       schedName, schedInstId) : rmiBindName;
  625   
  626               RemoteScheduler remoteScheduler = new RemoteScheduler(schedCtxt,
  627                       uid, rmiHost, rmiPort);
  628   
  629               schedRep.bind(remoteScheduler);
  630   
  631               return remoteScheduler;
  632           }
  633   
  634           
  635           // Create class load helper
  636           ClassLoadHelper loadHelper = null;
  637           try {
  638               loadHelper = (ClassLoadHelper) loadClass(classLoadHelperClass)
  639                       .newInstance();
  640           } catch (Exception e) {
  641               throw new SchedulerConfigException(
  642                       "Unable to instantiate class load helper class: "
  643                               + e.getMessage(), e);
  644           }
  645           loadHelper.initialize();
  646           
  647           // If Proxying to remote JMX scheduler, short-circuit here...
  648           // ~~~~~~~~~~~~~~~~~~
  649           if (jmxProxy) {
  650               if (autoId) {  
  651                   schedInstId = DEFAULT_INSTANCE_ID;
  652               }
  653   
  654               if (jmxProxyClass == null) {
  655                   throw new SchedulerConfigException("No JMX Proxy Scheduler class provided");
  656               }
  657   
  658               RemoteMBeanScheduler jmxScheduler = null;
  659               try {
  660                   jmxScheduler = (RemoteMBeanScheduler)loadHelper.loadClass(jmxProxyClass)
  661                           .newInstance();
  662               } catch (Exception e) {
  663                   throw new SchedulerConfigException(
  664                           "Unable to instantiate RemoteMBeanScheduler class.", e);
  665               }
  666               
  667               schedCtxt = new SchedulingContext();
  668               schedCtxt.setInstanceId(schedInstId);
  669               
  670               if (jmxObjectName == null) {
  671                   jmxObjectName = QuartzSchedulerResources.generateJMXObjectName(schedName, schedInstId);
  672               }
  673               
  674               jmxScheduler.setSchedulingContext(schedCtxt);
  675               jmxScheduler.setSchedulerObjectName(jmxObjectName);
  676                           
  677               tProps = cfg.getPropertyGroup(PROP_SCHED_JMX_PROXY, true);
  678               try {
  679                   setBeanProps(jmxScheduler, tProps);
  680               } catch (Exception e) {
  681                   initException = new SchedulerException("RemoteMBeanScheduler class '"
  682                           + jmxProxyClass + "' props could not be configured.", e);
  683                   initException.setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  684                   throw initException;
  685               }
  686               
  687               jmxScheduler.initialize();
  688               
  689               schedRep.bind(jmxScheduler);
  690   
  691               return jmxScheduler;
  692           }
  693           
  694           JobFactory jobFactory = null;
  695           if(jobFactoryClass != null) {
  696               try {
  697                   jobFactory = (JobFactory) loadHelper.loadClass(jobFactoryClass)
  698                           .newInstance();
  699               } catch (Exception e) {
  700                   throw new SchedulerConfigException(
  701                           "Unable to instantiate JobFactory class: "
  702                                   + e.getMessage(), e);
  703               }
  704   
  705               tProps = cfg.getPropertyGroup(PROP_SCHED_JOB_FACTORY_PREFIX, true);
  706               try {
  707                   setBeanProps(jobFactory, tProps);
  708               } catch (Exception e) {
  709                   initException = new SchedulerException("JobFactory class '"
  710                           + jobFactoryClass + "' props could not be configured.", e);
  711                   initException
  712                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  713                   throw initException;
  714               }
  715           }        
  716           
  717           InstanceIdGenerator instanceIdGenerator = null;
  718           if(instanceIdGeneratorClass != null) {
  719               try {
  720                   instanceIdGenerator = (InstanceIdGenerator) loadHelper.loadClass(instanceIdGeneratorClass)
  721                       .newInstance();
  722               } catch (Exception e) {
  723                   throw new SchedulerConfigException(
  724                           "Unable to instantiate InstanceIdGenerator class: "
  725                           + e.getMessage(), e);
  726               }
  727               
  728               tProps = cfg.getPropertyGroup(PROP_SCHED_INSTANCE_ID_GENERATOR_PREFIX, true);
  729               try {
  730                   setBeanProps(instanceIdGenerator, tProps);
  731               } catch (Exception e) {
  732                   initException = new SchedulerException("InstanceIdGenerator class '"
  733                           + instanceIdGeneratorClass + "' props could not be configured.", e);
  734                   initException
  735                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  736                   throw initException;
  737               }           
  738           }
  739           
  740           // Get ThreadPool Properties
  741           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  742   
  743           String tpClass = cfg.getStringProperty(PROP_THREAD_POOL_CLASS, null);
  744   
  745           if (tpClass == null) {
  746               initException = new SchedulerException(
  747                       "ThreadPool class not specified. ",
  748                       SchedulerException.ERR_BAD_CONFIGURATION);
  749               throw initException;
  750           }
  751   
  752           try {
  753               tp = (ThreadPool) loadHelper.loadClass(tpClass).newInstance();
  754           } catch (Exception e) {
  755               initException = new SchedulerException("ThreadPool class '"
  756                       + tpClass + "' could not be instantiated.", e);
  757               initException
  758                       .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  759               throw initException;
  760           }
  761           tProps = cfg.getPropertyGroup(PROP_THREAD_POOL_PREFIX, true);
  762           try {
  763               setBeanProps(tp, tProps);
  764           } catch (Exception e) {
  765               initException = new SchedulerException("ThreadPool class '"
  766                       + tpClass + "' props could not be configured.", e);
  767               initException
  768                       .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  769               throw initException;
  770           }
  771   
  772           // Get JobStore Properties
  773           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  774   
  775           String jsClass = cfg.getStringProperty(PROP_JOB_STORE_CLASS,
  776                   RAMJobStore.class.getName());
  777   
  778           if (jsClass == null) {
  779               initException = new SchedulerException(
  780                       "JobStore class not specified. ",
  781                       SchedulerException.ERR_BAD_CONFIGURATION);
  782               throw initException;
  783           }
  784   
  785           try {
  786               js = (JobStore) loadHelper.loadClass(jsClass).newInstance();
  787           } catch (Exception e) {
  788               initException = new SchedulerException("JobStore class '" + jsClass
  789                       + "' could not be instantiated.", e);
  790               initException
  791                       .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  792               throw initException;
  793           }
  794           tProps = cfg.getPropertyGroup(PROP_JOB_STORE_PREFIX, true, new String[] {PROP_JOB_STORE_LOCK_HANDLER_PREFIX});
  795           try {
  796               setBeanProps(js, tProps);
  797           } catch (Exception e) {
  798               initException = new SchedulerException("JobStore class '" + jsClass
  799                       + "' props could not be configured.", e);
  800               initException
  801                       .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  802               throw initException;
  803           }
  804   
  805           if (js instanceof JobStoreSupport) {
  806               ((JobStoreSupport)js).setInstanceId(schedInstId);
  807               ((JobStoreSupport)js).setInstanceName(schedName);
  808               
  809               // Install custom lock handler (Semaphore)
  810               String lockHandlerClass = cfg.getStringProperty(PROP_JOB_STORE_LOCK_HANDLER_CLASS);
  811               if (lockHandlerClass != null) {
  812                   try {
  813                       Semaphore lockHandler = (Semaphore)loadHelper.loadClass(lockHandlerClass).newInstance();
  814                       
  815                       tProps = cfg.getPropertyGroup(PROP_JOB_STORE_LOCK_HANDLER_PREFIX, true);
  816   
  817                       // If this lock handler requires the table prefix, add it to its properties.
  818                       if (lockHandler instanceof TablePrefixAware) {
  819                           tProps.setProperty(
  820                               PROP_TABLE_PREFIX, ((JobStoreSupport)js).getTablePrefix());
  821                       }
  822                       
  823                       try {
  824                           setBeanProps(lockHandler, tProps);
  825                       } catch (Exception e) {
  826                           initException = new SchedulerException("JobStore LockHandler class '" + lockHandlerClass
  827                                   + "' props could not be configured.", e);
  828                           initException.setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  829                           throw initException;
  830                       }
  831                       
  832                       ((JobStoreSupport)js).setLockHandler(lockHandler);
  833                       getLog().info("Using custom data access locking (synchronization): " + lockHandlerClass);
  834                   } catch (Exception e) {
  835                       initException = new SchedulerException("JobStore LockHandler class '" + lockHandlerClass
  836                               + "' could not be instantiated.", e);
  837                       initException.setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  838                       throw initException;
  839                   }
  840               }
  841           }
  842           
  843           // Set up any DataSources
  844           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  845   
  846           String[] dsNames = cfg.getPropertyGroups(PROP_DATASOURCE_PREFIX);
  847           for (int i = 0; i < dsNames.length; i++) {
  848               PropertiesParser pp = new PropertiesParser(cfg.getPropertyGroup(
  849                       PROP_DATASOURCE_PREFIX + "." + dsNames[i], true));
  850   
  851               String cpClass = pp.getStringProperty(PROP_CONNECTION_PROVIDER_CLASS, null);
  852   
  853               // custom connectionProvider...
  854               if(cpClass != null) {
  855                   ConnectionProvider cp = null;
  856                   try {
  857                       cp = (ConnectionProvider) loadHelper.loadClass(cpClass).newInstance();
  858                   } catch (Exception e) {
  859                       initException = new SchedulerException("ConnectionProvider class '" + cpClass
  860                               + "' could not be instantiated.", e);
  861                       initException
  862                               .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  863                       throw initException;
  864                   }
  865   
  866                   try {
  867                       // remove the class name, so it isn't attempted to be set
  868                       pp.getUnderlyingProperties().remove(
  869                               PROP_CONNECTION_PROVIDER_CLASS);
  870                       
  871                       setBeanProps(cp, pp.getUnderlyingProperties());
  872                   } catch (Exception e) {
  873                       initException = new SchedulerException("ConnectionProvider class '" + cpClass
  874                               + "' props could not be configured.", e);
  875                       initException
  876                               .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  877                       throw initException;
  878                   }
  879   
  880                   dbMgr = DBConnectionManager.getInstance();
  881                   dbMgr.addConnectionProvider(dsNames[i], cp);
  882               } else {
  883                   String dsJndi = pp.getStringProperty(PROP_DATASOURCE_JNDI_URL, null);
  884           
  885                   if (dsJndi != null) {
  886                       boolean dsAlwaysLookup = pp.getBooleanProperty(
  887                               PROP_DATASOURCE_JNDI_ALWAYS_LOOKUP);
  888                       String dsJndiInitial = pp.getStringProperty(
  889                               PROP_DATASOURCE_JNDI_INITIAL);
  890                       String dsJndiProvider = pp.getStringProperty(
  891                               PROP_DATASOURCE_JNDI_PROVDER);
  892                       String dsJndiPrincipal = pp.getStringProperty(
  893                               PROP_DATASOURCE_JNDI_PRINCIPAL);
  894                       String dsJndiCredentials = pp.getStringProperty(
  895                               PROP_DATASOURCE_JNDI_CREDENTIALS);
  896                       Properties props = null;
  897                       if (null != dsJndiInitial || null != dsJndiProvider
  898                               || null != dsJndiPrincipal || null != dsJndiCredentials) {
  899                           props = new Properties();
  900                           if (dsJndiInitial != null) {
  901                               props.put(PROP_DATASOURCE_JNDI_INITIAL,
  902                                       dsJndiInitial);
  903                           }
  904                           if (dsJndiProvider != null) {
  905                               props.put(PROP_DATASOURCE_JNDI_PROVDER,
  906                                       dsJndiProvider);
  907                           }
  908                           if (dsJndiPrincipal != null) {
  909                               props.put(PROP_DATASOURCE_JNDI_PRINCIPAL,
  910                                       dsJndiPrincipal);
  911                           }
  912                           if (dsJndiCredentials != null) {
  913                               props.put(PROP_DATASOURCE_JNDI_CREDENTIALS,
  914                                       dsJndiCredentials);
  915                           }
  916                       }
  917                       JNDIConnectionProvider cp = new JNDIConnectionProvider(dsJndi,
  918                               props, dsAlwaysLookup);
  919                       dbMgr = DBConnectionManager.getInstance();
  920                       dbMgr.addConnectionProvider(dsNames[i], cp);
  921                   } else {
  922                       String dsDriver = pp.getStringProperty(PROP_DATASOURCE_DRIVER);
  923                       String dsURL = pp.getStringProperty(PROP_DATASOURCE_URL);
  924                       String dsUser = pp.getStringProperty(PROP_DATASOURCE_USER, "");
  925                       String dsPass = pp.getStringProperty(PROP_DATASOURCE_PASSWORD, "");
  926                       int dsCnt = pp.getIntProperty(PROP_DATASOURCE_MAX_CONNECTIONS, 10);
  927                       String dsValidation = pp.getStringProperty(PROP_DATASOURCE_VALIDATION_QUERY);
  928                       
  929                       if (dsDriver == null) {
  930                           initException = new SchedulerException(
  931                                   "Driver not specified for DataSource: "
  932                                           + dsNames[i]);
  933                           throw initException;
  934                       }
  935                       if (dsURL == null) {
  936                           initException = new SchedulerException(
  937                                   "DB URL not specified for DataSource: "
  938                                           + dsNames[i]);
  939                           throw initException;
  940                       }
  941                       try {
  942                           PoolingConnectionProvider cp = new PoolingConnectionProvider(
  943                                   dsDriver, dsURL, dsUser, dsPass, dsCnt,
  944                                   dsValidation);
  945                           dbMgr = DBConnectionManager.getInstance();
  946                           dbMgr.addConnectionProvider(dsNames[i], cp);
  947                       } catch (SQLException sqle) {
  948                           initException = new SchedulerException(
  949                                   "Could not initialize DataSource: " + dsNames[i],
  950                                   sqle);
  951                           throw initException;
  952                       }
  953                   }
  954                   
  955               }
  956               
  957           }
  958   
  959           // Set up any SchedulerPlugins
  960           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  961   
  962           String[] pluginNames = cfg.getPropertyGroups(PROP_PLUGIN_PREFIX);
  963           SchedulerPlugin[] plugins = new SchedulerPlugin[pluginNames.length];
  964           for (int i = 0; i < pluginNames.length; i++) {
  965               Properties pp = cfg.getPropertyGroup(PROP_PLUGIN_PREFIX + "."
  966                       + pluginNames[i], true);
  967   
  968               String plugInClass = pp.getProperty(PROP_PLUGIN_CLASS, null);
  969   
  970               if (plugInClass == null) {
  971                   initException = new SchedulerException(
  972                           "SchedulerPlugin class not specified for plugin '"
  973                                   + pluginNames[i] + "'",
  974                           SchedulerException.ERR_BAD_CONFIGURATION);
  975                   throw initException;
  976               }
  977               SchedulerPlugin plugin = null;
  978               try {
  979                   plugin = (SchedulerPlugin)
  980                           loadHelper.loadClass(plugInClass).newInstance();
  981               } catch (Exception e) {
  982                   initException = new SchedulerException(
  983                           "SchedulerPlugin class '" + plugInClass
  984                                   + "' could not be instantiated.", e);
  985                   initException
  986                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  987                   throw initException;
  988               }
  989               try {
  990                   setBeanProps(plugin, pp);
  991               } catch (Exception e) {
  992                   initException = new SchedulerException(
  993                           "JobStore SchedulerPlugin '" + plugInClass
  994                                   + "' props could not be configured.", e);
  995                   initException
  996                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
  997                   throw initException;
  998               }
  999               
 1000               plugins[i] = plugin;
 1001           }
 1002   
 1003           // Set up any JobListeners
 1004           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1005   
 1006           Class[] strArg = new Class[] { String.class };
 1007           String[] jobListenerNames = cfg.getPropertyGroups(PROP_JOB_LISTENER_PREFIX);
 1008           JobListener[] jobListeners = new JobListener[jobListenerNames.length];
 1009           for (int i = 0; i < jobListenerNames.length; i++) {
 1010               Properties lp = cfg.getPropertyGroup(PROP_JOB_LISTENER_PREFIX + "."
 1011                       + jobListenerNames[i], true);
 1012               
 1013               String listenerClass = lp.getProperty(PROP_LISTENER_CLASS, null);
 1014   
 1015               if (listenerClass == null) {
 1016                   initException = new SchedulerException(
 1017                           "JobListener class not specified for listener '"
 1018                                   + jobListenerNames[i] + "'",
 1019                           SchedulerException.ERR_BAD_CONFIGURATION);
 1020                   throw initException;
 1021               }
 1022               JobListener listener = null;
 1023               try {
 1024                   listener = (JobListener)
 1025                          loadHelper.loadClass(listenerClass).newInstance();
 1026               } catch (Exception e) {
 1027                   initException = new SchedulerException(
 1028                           "JobListener class '" + listenerClass
 1029                                   + "' could not be instantiated.", e);
 1030                   initException
 1031                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
 1032                   throw initException;
 1033               }
 1034               try {
 1035                   Method nameSetter = listener.getClass().getMethod("setName", strArg);
 1036                   if(nameSetter != null) {
 1037                       nameSetter.invoke(listener, new Object[] {jobListenerNames[i] } );
 1038                   }
 1039                   setBeanProps(listener, lp);
 1040               } catch (Exception e) {
 1041                   initException = new SchedulerException(
 1042                           "JobListener '" + listenerClass
 1043                                   + "' props could not be configured.", e);
 1044                   initException
 1045                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
 1046                   throw initException;
 1047               }
 1048               jobListeners[i] = listener;
 1049           }
 1050                  
 1051           // Set up any TriggerListeners
 1052           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1053   
 1054           String[] triggerListenerNames = cfg.getPropertyGroups(PROP_TRIGGER_LISTENER_PREFIX);
 1055           TriggerListener[] triggerListeners = new TriggerListener[triggerListenerNames.length];
 1056           for (int i = 0; i < triggerListenerNames.length; i++) {
 1057               Properties lp = cfg.getPropertyGroup(PROP_TRIGGER_LISTENER_PREFIX + "."
 1058                       + triggerListenerNames[i], true);
 1059               
 1060               String listenerClass = lp.getProperty(PROP_LISTENER_CLASS, null);
 1061   
 1062               if (listenerClass == null) {
 1063                   initException = new SchedulerException(
 1064                           "TriggerListener class not specified for listener '"
 1065                                   + triggerListenerNames[i] + "'",
 1066                           SchedulerException.ERR_BAD_CONFIGURATION);
 1067                   throw initException;
 1068               }
 1069               TriggerListener listener = null;
 1070               try {
 1071                   listener = (TriggerListener)
 1072                          loadHelper.loadClass(listenerClass).newInstance();
 1073               } catch (Exception e) {
 1074                   initException = new SchedulerException(
 1075                           "TriggerListener class '" + listenerClass
 1076                                   + "' could not be instantiated.", e);
 1077                   initException
 1078                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
 1079                   throw initException;
 1080               }
 1081               try {
 1082                   Method nameSetter = listener.getClass().getMethod("setName", strArg);
 1083                   if(nameSetter != null) {
 1084                       nameSetter.invoke(listener, new Object[] {triggerListenerNames[i] } );
 1085                   }
 1086                   setBeanProps(listener, lp);
 1087               } catch (Exception e) {
 1088                   initException = new SchedulerException(
 1089                           "TriggerListener '" + listenerClass
 1090                                   + "' props could not be configured.", e);
 1091                   initException
 1092                           .setErrorCode(SchedulerException.ERR_BAD_CONFIGURATION);
 1093                   throw initException;
 1094               }
 1095               triggerListeners[i] = listener;
 1096           }
 1097                   
 1098           
 1099           // Fire everything up
 1100           // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1101   
 1102           JobRunShellFactory jrsf = null; // Create correct run-shell factory...
 1103   
 1104           UserTransactionHelper.setUserTxLocation(userTXLocation);
 1105   
 1106           if (wrapJobInTx) {
 1107               jrsf = new JTAJobRunShellFactory();
 1108           } else {
 1109               jrsf = new StdJobRunShellFactory();
 1110           }
 1111   
 1112           if (autoId) {
 1113               try {
 1114                   schedInstId = DEFAULT_INSTANCE_ID;
 1115                   if (js instanceof JobStoreSupport) {
 1116                       if(((JobStoreSupport)js).isClustered()) {
 1117                           schedInstId = instanceIdGenerator.generateInstanceId();                    
 1118                       }
 1119                   }
 1120               } catch (Exception e) {
 1121                   getLog().error("Couldn't generate instance Id!", e);
 1122                   throw new IllegalStateException(
 1123                           "Cannot run without an instance id.");
 1124               }
 1125           }
 1126   
 1127           if (js instanceof JobStoreSupport) {
 1128               JobStoreSupport jjs = (JobStoreSupport)js;
 1129               jjs.setInstanceId(schedInstId);
 1130               jjs.setDbRetryInterval(dbFailureRetry);
 1131           }
 1132           
 1133           QuartzSchedulerResources rsrcs = new QuartzSchedulerResources();
 1134           rsrcs.setName(schedName);
 1135           rsrcs.setThreadName(threadName);        
 1136           rsrcs.setInstanceId(schedInstId);
 1137           rsrcs.setJobRunShellFactory(jrsf);
 1138           rsrcs.setMakeSchedulerThreadDaemon(makeSchedulerThreadDaemon);
 1139           rsrcs.setJMXExport(jmxExport);
 1140           rsrcs.setJMXObjectName(jmxObjectName);
 1141   
 1142           if (rmiExport) {
 1143               rsrcs.setRMIRegistryHost(rmiHost);
 1144               rsrcs.setRMIRegistryPort(rmiPort);
 1145               rsrcs.setRMIServerPort(rmiServerPort);
 1146               rsrcs.setRMICreateRegistryStrategy(rmiCreateRegistry);
 1147               rsrcs.setRMIBindName(rmiBindName);
 1148           }
 1149   
 1150           rsrcs.setThreadPool(tp);
 1151           if(tp instanceof SimpleThreadPool) {
 1152               ((SimpleThreadPool)tp).setThreadNamePrefix(schedName + "_Worker");
 1153           }
 1154           tp.initialize();
 1155           
 1156           rsrcs.setJobStore(js);
 1157   
 1158           // add plugins
 1159           for (int i = 0; i < plugins.length; i++) {
 1160               rsrcs.addSchedulerPlugin(plugins[i]);
 1161           }
 1162   
 1163           schedCtxt = new SchedulingContext();
 1164           schedCtxt.setInstanceId(rsrcs.getInstanceId());
 1165   
 1166           qs = new QuartzScheduler(rsrcs, schedCtxt, idleWaitTime, dbFailureRetry);
 1167   
 1168           //    if(usingJSCMT)
 1169           //      qs.setSignalOnSchedulingChange(false); // TODO: fixed? (don't need
 1170           // this any more?)
 1171   
 1172           // Create Scheduler ref...
 1173           Scheduler scheduler = instantiate(rsrcs, qs);
 1174           
 1175           // set job factory if specified
 1176           if(jobFactory != null) {
 1177               qs.setJobFactory(jobFactory);
 1178           }
 1179   
 1180           // Initialize plugins now that we have a Scheduler instance.
 1181           for (int i = 0; i < plugins.length; i++) {
 1182               plugins[i].initialize(pluginNames[i], scheduler);
 1183           }
 1184           
 1185           // add listeners
 1186           for (int i = 0; i < jobListeners.length; i++) {
 1187               qs.addGlobalJobListener(jobListeners[i]);
 1188           }
 1189           for (int i = 0; i < triggerListeners.length; i++) {
 1190               qs.addGlobalTriggerListener(triggerListeners[i]);
 1191           }
 1192           
 1193           // set scheduler context data...
 1194           Iterator itr = schedCtxtProps.keySet().iterator();
 1195           while(itr.hasNext()) {
 1196               String key = (String) itr.next();
 1197               String val = schedCtxtProps.getProperty(key);
 1198               
 1199               scheduler.getContext().put(key, val);
 1200           }
 1201           
 1202           // fire up job store, and runshell factory
 1203   
 1204           js.initialize(loadHelper, qs.getSchedulerSignaler());
 1205   
 1206           jrsf.initialize(scheduler, schedCtxt);
 1207   
 1208           getLog().info(
 1209                   "Quartz scheduler '" + scheduler.getSchedulerName()
 1210                           + "' initialized from " + propSrc);
 1211   
 1212           getLog().info("Quartz scheduler version: " + qs.getVersion());
 1213   
 1214           // prevents the repository from being garbage collected
 1215           qs.addNoGCObject(schedRep);
 1216           // prevents the db manager from being garbage collected
 1217           if (dbMgr != null) {
 1218               qs.addNoGCObject(dbMgr);
 1219           }
 1220   
 1221           schedRep.bind(scheduler);
 1222   
 1223           return scheduler;
 1224       }
 1225   
 1226       protected Scheduler instantiate(QuartzSchedulerResources rsrcs, QuartzScheduler qs) {
 1227           SchedulingContext schedCtxt = new SchedulingContext();
 1228           schedCtxt.setInstanceId(rsrcs.getInstanceId());
 1229           
 1230           Scheduler scheduler = new StdScheduler(qs, schedCtxt);
 1231           return scheduler;
 1232       }
 1233       
 1234   
 1235       private void setBeanProps(Object obj, Properties props)
 1236           throws NoSuchMethodException, IllegalAccessException,
 1237               java.lang.reflect.InvocationTargetException,
 1238               IntrospectionException, SchedulerConfigException {
 1239           props.remove("class");
 1240   
 1241           BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
 1242           PropertyDescriptor[] propDescs = bi.getPropertyDescriptors();
 1243           PropertiesParser pp = new PropertiesParser(props);
 1244   
 1245           java.util.Enumeration keys = props.keys();
 1246           while (keys.hasMoreElements()) {
 1247               String name = (String) keys.nextElement();
 1248               String c = name.substring(0, 1).toUpperCase(Locale.US);
 1249               String methName = "set" + c + name.substring(1);
 1250   
 1251               java.lang.reflect.Method setMeth = getSetMethod(methName, propDescs);
 1252   
 1253               try {
 1254                   if (setMeth == null) {
 1255                       throw new NoSuchMethodException(
 1256                               "No setter for property '" + name + "'");
 1257                   }
 1258   
 1259                   Class[] params = setMeth.getParameterTypes();
 1260                   if (params.length != 1) {
 1261                       throw new NoSuchMethodException(
 1262                           "No 1-argument setter for property '" + name + "'");
 1263                   }
 1264                   if (params[0].equals(int.class)) {
 1265                       setMeth.invoke(obj, new Object[]{new Integer(pp
 1266                               .getIntProperty(name))});
 1267                   } else if (params[0].equals(long.class)) {
 1268                       setMeth.invoke(obj, new Object[]{new Long(pp
 1269                               .getLongProperty(name))});
 1270                   } else if (params[0].equals(float.class)) {
 1271                       setMeth.invoke(obj, new Object[]{new Float(pp
 1272                               .getFloatProperty(name))});
 1273                   } else if (params[0].equals(double.class)) {
 1274                       setMeth.invoke(obj, new Object[]{new Double(pp
 1275                               .getDoubleProperty(name))});
 1276                   } else if (params[0].equals(boolean.class)) {
 1277                       setMeth.invoke(obj, new Object[]{new Boolean(pp
 1278                               .getBooleanProperty(name))});
 1279                   } else if (params[0].equals(String.class)) {
 1280                       setMeth.invoke(obj,
 1281                               new Object[]{pp.getStringProperty(name)});
 1282                   } else {
 1283                       throw new NoSuchMethodException(
 1284                               "No primitive-type setter for property '" + name
 1285                                       + "'");
 1286                   }
 1287               } catch (NumberFormatException nfe) {
 1288                   throw new SchedulerConfigException("Could not parse property '"
 1289                           + name + "' into correct data type: " + nfe.toString());
 1290               }
 1291           }
 1292       }
 1293   
 1294       private java.lang.reflect.Method getSetMethod(String name,
 1295               PropertyDescriptor[] props) {
 1296           for (int i = 0; i < props.length; i++) {
 1297               java.lang.reflect.Method wMeth = props[i].getWriteMethod();
 1298   
 1299               if (wMeth != null && wMeth.getName().equals(name)) {
 1300                   return wMeth;
 1301               }
 1302           }
 1303   
 1304           return null;
 1305       }
 1306   
 1307       private Class loadClass(String className) throws ClassNotFoundException {
 1308   
 1309           try {
 1310               return Thread.currentThread().getContextClassLoader().loadClass(
 1311                       className);
 1312           } catch (ClassNotFoundException e) {
 1313               return getClass().getClassLoader().loadClass(className);
 1314           }
 1315       }
 1316       
 1317       private String getSchedulerName() {
 1318           return cfg.getStringProperty(PROP_SCHED_INSTANCE_NAME,
 1319                   "QuartzScheduler");
 1320       }
 1321   
 1322       private String getSchedulerInstId() {
 1323           return cfg.getStringProperty(PROP_SCHED_INSTANCE_ID,
 1324                   DEFAULT_INSTANCE_ID);
 1325       }
 1326   
 1327       /**
 1328        * <p>
 1329        * Returns a handle to the Scheduler produced by this factory.
 1330        * </p>
 1331        * 
 1332        * <p>
 1333        * If one of the <code>initialize</code> methods has not be previously
 1334        * called, then the default (no-arg) <code>initialize()</code> method
 1335        * will be called by this method.
 1336        * </p>
 1337        */
 1338       public Scheduler getScheduler() throws SchedulerException {
 1339           if (cfg == null) {
 1340               initialize();
 1341           }
 1342   
 1343           SchedulerRepository schedRep = SchedulerRepository.getInstance();
 1344   
 1345           Scheduler sched = schedRep.lookup(getSchedulerName());
 1346   
 1347           if (sched != null) {
 1348               if (sched.isShutdown()) {
 1349                   schedRep.remove(getSchedulerName());
 1350               } else {
 1351                   return sched;
 1352               }
 1353           }
 1354   
 1355           sched = instantiate();
 1356   
 1357           return sched;
 1358       }
 1359   
 1360       /**
 1361        * <p>
 1362        * Returns a handle to the default Scheduler, creating it if it does not
 1363        * yet exist.
 1364        * </p>
 1365        * 
 1366        * @see #initialize()
 1367        */
 1368       public static Scheduler getDefaultScheduler() throws SchedulerException {
 1369           StdSchedulerFactory fact = new StdSchedulerFactory();
 1370   
 1371           return fact.getScheduler();
 1372       }
 1373   
 1374       /**
 1375        * <p>
 1376        * Returns a handle to the Scheduler with the given name, if it exists (if
 1377        * it has already been instantiated).
 1378        * </p>
 1379        */
 1380       public Scheduler getScheduler(String schedName) throws SchedulerException {
 1381           return SchedulerRepository.getInstance().lookup(schedName);
 1382       }
 1383   
 1384       /**
 1385        * <p>
 1386        * Returns a handle to all known Schedulers (made by any
 1387        * StdSchedulerFactory instance.).
 1388        * </p>
 1389        */
 1390       public Collection getAllSchedulers() throws SchedulerException {
 1391           return SchedulerRepository.getInstance().lookupAll();
 1392       }
 1393   }

Home » quartz-1.6.0 » org » quartz » impl » [javadoc | source]