Example #1
0
        /// <summary>  </summary>
        private IScheduler Instantiate()
        {
            if (cfg == null)
            {
                Initialize();
            }

            if (initException != null)
            {
                throw initException;
            }

            ISchedulerExporter   exporter = null;
            IJobStore            js;
            IThreadPool          tp;
            QuartzScheduler      qs      = null;
            IDbConnectionManager dbMgr   = null;
            Type instanceIdGeneratorType = null;
            NameValueCollection tProps;
            bool            autoId         = false;
            TimeSpan        idleWaitTime   = TimeSpan.Zero;
            TimeSpan        dbFailureRetry = TimeSpan.FromSeconds(15);
            IThreadExecutor threadExecutor;

            SchedulerRepository schedRep = SchedulerRepository.Instance;

            // Get Scheduler Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string schedName   = cfg.GetStringProperty(PropertySchedulerInstanceName, "QuartzScheduler");
            string threadName  = cfg.GetStringProperty(PropertySchedulerThreadName, "{0}_QuartzSchedulerThread".FormatInvariant(schedName));
            string schedInstId = cfg.GetStringProperty(PropertySchedulerInstanceId, DefaultInstanceId);

            if (schedInstId.Equals(AutoGenerateInstanceId))
            {
                autoId = true;
                instanceIdGeneratorType = LoadType(cfg.GetStringProperty(PropertySchedulerInstanceIdGeneratorType)) ?? typeof(SimpleInstanceIdGenerator);
            }
            else if (schedInstId.Equals(SystemPropertyAsInstanceId))
            {
                autoId = true;
                instanceIdGeneratorType = typeof(SystemPropertyInstanceIdGenerator);
            }

            Type typeLoadHelperType = LoadType(cfg.GetStringProperty(PropertySchedulerTypeLoadHelperType));
            Type jobFactoryType     = LoadType(cfg.GetStringProperty(PropertySchedulerJobFactoryType, null));

            idleWaitTime = cfg.GetTimeSpanProperty(PropertySchedulerIdleWaitTime, idleWaitTime);
            if (idleWaitTime > TimeSpan.Zero && idleWaitTime < TimeSpan.FromMilliseconds(1000))
            {
                throw new SchedulerException("quartz.scheduler.idleWaitTime of less than 1000ms is not legal.");
            }

            dbFailureRetry = cfg.GetTimeSpanProperty(PropertySchedulerDbFailureRetryInterval, dbFailureRetry);
            if (dbFailureRetry < TimeSpan.Zero)
            {
                throw new SchedulerException(PropertySchedulerDbFailureRetryInterval + " of less than 0 ms is not legal.");
            }

            bool makeSchedulerThreadDaemon = cfg.GetBooleanProperty(PropertySchedulerMakeSchedulerThreadDaemon);
            long batchTimeWindow           = cfg.GetLongProperty(PropertySchedulerBatchTimeWindow, 0L);
            int  maxBatchSize = cfg.GetIntProperty(PropertySchedulerMaxBatchSize, 1);

            bool interruptJobsOnShutdown         = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdown, false);
            bool interruptJobsOnShutdownWithWait = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdownWithWait, false);

            NameValueCollection schedCtxtProps = cfg.GetPropertyGroup(PropertySchedulerContextPrefix, true);

            bool proxyScheduler = cfg.GetBooleanProperty(PropertySchedulerProxy, false);


            // Create type load helper
            ITypeLoadHelper loadHelper;

            try
            {
                loadHelper = ObjectUtils.InstantiateType <ITypeLoadHelper>(typeLoadHelperType ?? typeof(SimpleTypeLoadHelper));
            }
            catch (Exception e)
            {
                throw new SchedulerConfigException("Unable to instantiate type load helper: {0}".FormatInvariant(e.Message), e);
            }
            loadHelper.Initialize();


            // If Proxying to remote scheduler, short-circuit here...
            // ~~~~~~~~~~~~~~~~~~
            if (proxyScheduler)
            {
                if (autoId)
                {
                    schedInstId = DefaultInstanceId;
                }

                Type proxyType = loadHelper.LoadType(cfg.GetStringProperty(PropertySchedulerProxyType)) ?? typeof(RemotingSchedulerProxyFactory);
                IRemotableSchedulerProxyFactory factory;
                try
                {
                    factory = ObjectUtils.InstantiateType <IRemotableSchedulerProxyFactory>(proxyType);
                    ObjectUtils.SetObjectProperties(factory, cfg.GetPropertyGroup(PropertySchedulerProxy, true));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Remotable proxy factory '{0}' could not be instantiated.".FormatInvariant(proxyType), e);
                    throw initException;
                }

                string uid = QuartzSchedulerResources.GetUniqueIdentifier(schedName, schedInstId);

                RemoteScheduler remoteScheduler = new RemoteScheduler(uid, factory);

                schedRep.Bind(remoteScheduler);

                return(remoteScheduler);
            }


            IJobFactory jobFactory = null;

            if (jobFactoryType != null)
            {
                try
                {
                    jobFactory = ObjectUtils.InstantiateType <IJobFactory>(jobFactoryType);
                }
                catch (Exception e)
                {
                    throw new SchedulerConfigException("Unable to Instantiate JobFactory: {0}".FormatInvariant(e.Message), e);
                }

                tProps = cfg.GetPropertyGroup(PropertySchedulerJobFactoryPrefix, true);
                try
                {
                    ObjectUtils.SetObjectProperties(jobFactory, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobFactory of type '{0}' props could not be configured.".FormatInvariant(jobFactoryType), e);
                    throw initException;
                }
            }

            IInstanceIdGenerator instanceIdGenerator = null;

            if (instanceIdGeneratorType != null)
            {
                try
                {
                    instanceIdGenerator = ObjectUtils.InstantiateType <IInstanceIdGenerator>(instanceIdGeneratorType);
                }
                catch (Exception e)
                {
                    throw new SchedulerConfigException("Unable to Instantiate InstanceIdGenerator: {0}".FormatInvariant(e.Message), e);
                }
                tProps = cfg.GetPropertyGroup(PropertySchedulerInstanceIdGeneratorPrefix, true);
                try
                {
                    ObjectUtils.SetObjectProperties(instanceIdGenerator, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("InstanceIdGenerator of type '{0}' props could not be configured.".FormatInvariant(instanceIdGeneratorType), e);
                    throw initException;
                }
            }

            // Get ThreadPool Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            Type tpType = loadHelper.LoadType(cfg.GetStringProperty(PropertyThreadPoolType)) ?? typeof(SimpleThreadPool);

            try
            {
                tp = ObjectUtils.InstantiateType <IThreadPool>(tpType);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e);
                throw initException;
            }
            tProps = cfg.GetPropertyGroup(PropertyThreadPoolPrefix, true);
            try
            {
                ObjectUtils.SetObjectProperties(tp, tProps);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("ThreadPool type '{0}' props could not be configured.".FormatInvariant(tpType), e);
                throw initException;
            }

            // Set up any DataSources
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            IList <string> dsNames = cfg.GetPropertyGroups(PropertyDataSourcePrefix);

            foreach (string dataSourceName in dsNames)
            {
                string datasourceKey = "{0}.{1}".FormatInvariant(PropertyDataSourcePrefix, dataSourceName);
                NameValueCollection propertyGroup = cfg.GetPropertyGroup(datasourceKey, true);
                PropertiesParser    pp            = new PropertiesParser(propertyGroup);

                Type cpType = loadHelper.LoadType(pp.GetStringProperty(PropertyDbProviderType, null));

                // custom connectionProvider...
                if (cpType != null)
                {
                    IDbProvider cp;
                    try
                    {
                        cp = ObjectUtils.InstantiateType <IDbProvider>(cpType);
                    }
                    catch (Exception e)
                    {
                        initException = new SchedulerException("ConnectionProvider of type '{0}' could not be instantiated.".FormatInvariant(cpType), e);
                        throw initException;
                    }

                    try
                    {
                        // remove the type name, so it isn't attempted to be set
                        pp.UnderlyingProperties.Remove(PropertyDbProviderType);

                        ObjectUtils.SetObjectProperties(cp, pp.UnderlyingProperties);
                        cp.Initialize();
                    }
                    catch (Exception e)
                    {
                        initException = new SchedulerException("ConnectionProvider type '{0}' props could not be configured.".FormatInvariant(cpType), e);
                        throw initException;
                    }

                    dbMgr = DBConnectionManager.Instance;
                    dbMgr.AddConnectionProvider(dataSourceName, cp);
                }
                else
                {
                    string dsProvider             = pp.GetStringProperty(PropertyDataSourceProvider, null);
                    string dsConnectionString     = pp.GetStringProperty(PropertyDataSourceConnectionString, null);
                    string dsConnectionStringName = pp.GetStringProperty(PropertyDataSourceConnectionStringName, null);

                    if (dsConnectionString == null && !String.IsNullOrEmpty(dsConnectionStringName))
                    {
                        ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[dsConnectionStringName];
                        if (connectionStringSettings == null)
                        {
                            initException = new SchedulerException("Named connection string '{0}' not found for DataSource: {1}".FormatInvariant(dsConnectionStringName, dataSourceName));
                            throw initException;
                        }
                        dsConnectionString = connectionStringSettings.ConnectionString;
                    }

                    if (dsProvider == null)
                    {
                        initException = new SchedulerException("Provider not specified for DataSource: {0}".FormatInvariant(dataSourceName));
                        throw initException;
                    }
                    if (dsConnectionString == null)
                    {
                        initException = new SchedulerException("Connection string not specified for DataSource: {0}".FormatInvariant(dataSourceName));
                        throw initException;
                    }
                    try
                    {
                        DbProvider dbp = new DbProvider(dsProvider, dsConnectionString);
                        dbp.Initialize();

                        dbMgr = DBConnectionManager.Instance;
                        dbMgr.AddConnectionProvider(dataSourceName, dbp);
                    }
                    catch (Exception exception)
                    {
                        initException = new SchedulerException("Could not Initialize DataSource: {0}".FormatInvariant(dataSourceName), exception);
                        throw initException;
                    }
                }
            }

            // Get object serializer properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            IObjectSerializer objectSerializer;
            string            objectSerializerType = cfg.GetStringProperty("quartz.serializer.type");

            if (objectSerializerType != null)
            {
                tProps = cfg.GetPropertyGroup(PropertyObjectSerializer, true);
                try
                {
                    objectSerializer = ObjectUtils.InstantiateType <IObjectSerializer>(loadHelper.LoadType(objectSerializerType));
                    log.Info("Using custom implementation for object serializer: " + objectSerializerType);

                    ObjectUtils.SetObjectProperties(objectSerializer, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Object serializer type '" + objectSerializerType + "' could not be instantiated.", e);
                    throw initException;
                }
            }
            else
            {
                log.Info("Using default implementation for object serializer");
                objectSerializer = new DefaultObjectSerializer();
            }

            // Get JobStore Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            Type jsType = loadHelper.LoadType(cfg.GetStringProperty(PropertyJobStoreType));

            try
            {
                js = ObjectUtils.InstantiateType <IJobStore>(jsType ?? typeof(RAMJobStore));
            }
            catch (Exception e)
            {
                initException = new SchedulerException("JobStore of type '{0}' could not be instantiated.".FormatInvariant(jsType), e);
                throw initException;
            }


            SchedulerDetailsSetter.SetDetails(js, schedName, schedInstId);

            tProps = cfg.GetPropertyGroup(PropertyJobStorePrefix, true, new string[] { PropertyJobStoreLockHandlerPrefix });

            try
            {
                ObjectUtils.SetObjectProperties(js, tProps);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("JobStore type '{0}' props could not be configured.".FormatInvariant(jsType), e);
                throw initException;
            }

            JobStoreSupport jobStoreSupport = js as JobStoreSupport;

            if (jobStoreSupport != null)
            {
                // Install custom lock handler (Semaphore)
                Type lockHandlerType = loadHelper.LoadType(cfg.GetStringProperty(PropertyJobStoreLockHandlerType));
                if (lockHandlerType != null)
                {
                    try
                    {
                        ISemaphore      lockHandler;
                        ConstructorInfo cWithDbProvider = lockHandlerType.GetConstructor(new Type[] { typeof(DbProvider) });

                        if (cWithDbProvider != null)
                        {
                            // takes db provider
                            IDbProvider dbProvider = DBConnectionManager.Instance.GetDbProvider(jobStoreSupport.DataSource);
                            lockHandler = (ISemaphore)cWithDbProvider.Invoke(new object[] { dbProvider });
                        }
                        else
                        {
                            lockHandler = ObjectUtils.InstantiateType <ISemaphore>(lockHandlerType);
                        }

                        tProps = cfg.GetPropertyGroup(PropertyJobStoreLockHandlerPrefix, true);

                        // If this lock handler requires the table prefix, add it to its properties.
                        if (lockHandler is ITablePrefixAware)
                        {
                            tProps[PropertyTablePrefix]   = jobStoreSupport.TablePrefix;
                            tProps[PropertySchedulerName] = schedName;
                        }

                        try
                        {
                            ObjectUtils.SetObjectProperties(lockHandler, tProps);
                        }
                        catch (Exception e)
                        {
                            initException = new SchedulerException("JobStore LockHandler type '{0}' props could not be configured.".FormatInvariant(lockHandlerType), e);
                            throw initException;
                        }

                        jobStoreSupport.LockHandler = lockHandler;
                        Log.Info("Using custom data access locking (synchronization): " + lockHandlerType);
                    }
                    catch (Exception e)
                    {
                        initException = new SchedulerException("JobStore LockHandler type '{0}' could not be instantiated.".FormatInvariant(lockHandlerType), e);
                        throw initException;
                    }
                }
            }

            // Set up any SchedulerPlugins
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            IList <string> pluginNames = cfg.GetPropertyGroups(PropertyPluginPrefix);

            ISchedulerPlugin[] plugins = new ISchedulerPlugin[pluginNames.Count];
            for (int i = 0; i < pluginNames.Count; i++)
            {
                NameValueCollection pp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyPluginPrefix, pluginNames[i]), true);

                string plugInType = pp[PropertyPluginType];

                if (plugInType == null)
                {
                    initException = new SchedulerException("SchedulerPlugin type not specified for plugin '{0}'".FormatInvariant(pluginNames[i]));
                    throw initException;
                }
                ISchedulerPlugin plugin;
                try
                {
                    plugin = ObjectUtils.InstantiateType <ISchedulerPlugin>(LoadType(plugInType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("SchedulerPlugin of type '{0}' could not be instantiated.".FormatInvariant(plugInType), e);
                    throw initException;
                }
                try
                {
                    ObjectUtils.SetObjectProperties(plugin, pp);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobStore SchedulerPlugin '{0}' props could not be configured.".FormatInvariant(plugInType), e);
                    throw initException;
                }
                plugins[i] = plugin;
            }

            // Set up any JobListeners
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            IList <string> jobListenerNames = cfg.GetPropertyGroups(PropertyJobListenerPrefix);

            IJobListener[] jobListeners = new IJobListener[jobListenerNames.Count];
            for (int i = 0; i < jobListenerNames.Count; i++)
            {
                NameValueCollection lp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyJobListenerPrefix, jobListenerNames[i]), true);

                string listenerType = lp[PropertyListenerType];

                if (listenerType == null)
                {
                    initException = new SchedulerException("JobListener type not specified for listener '{0}'".FormatInvariant(jobListenerNames[i]));
                    throw initException;
                }
                IJobListener listener;
                try
                {
                    listener = ObjectUtils.InstantiateType <IJobListener>(loadHelper.LoadType(listenerType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobListener of type '{0}' could not be instantiated.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                try
                {
                    PropertyInfo nameProperty = listener.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
                    if (nameProperty != null && nameProperty.CanWrite)
                    {
                        nameProperty.GetSetMethod().Invoke(listener, new object[] { jobListenerNames[i] });
                    }
                    ObjectUtils.SetObjectProperties(listener, lp);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobListener '{0}' props could not be configured.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                jobListeners[i] = listener;
            }

            // Set up any TriggerListeners
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            IList <string> triggerListenerNames = cfg.GetPropertyGroups(PropertyTriggerListenerPrefix);

            ITriggerListener[] triggerListeners = new ITriggerListener[triggerListenerNames.Count];
            for (int i = 0; i < triggerListenerNames.Count; i++)
            {
                NameValueCollection lp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyTriggerListenerPrefix, triggerListenerNames[i]), true);

                string listenerType = lp[PropertyListenerType];

                if (listenerType == null)
                {
                    initException = new SchedulerException("TriggerListener type not specified for listener '{0}'".FormatInvariant(triggerListenerNames[i]));
                    throw initException;
                }
                ITriggerListener listener;
                try
                {
                    listener = ObjectUtils.InstantiateType <ITriggerListener>(loadHelper.LoadType(listenerType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("TriggerListener of type '{0}' could not be instantiated.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                try
                {
                    PropertyInfo nameProperty = listener.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
                    if (nameProperty != null && nameProperty.CanWrite)
                    {
                        nameProperty.GetSetMethod().Invoke(listener, new object[] { triggerListenerNames[i] });
                    }
                    ObjectUtils.SetObjectProperties(listener, lp);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("TriggerListener '{0}' props could not be configured.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                triggerListeners[i] = listener;
            }

            // Get exporter
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string exporterType = cfg.GetStringProperty(PropertySchedulerExporterType, null);

            if (exporterType != null)
            {
                try
                {
                    exporter = ObjectUtils.InstantiateType <ISchedulerExporter>(loadHelper.LoadType(exporterType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Scheduler exporter of type '{0}' could not be instantiated.".FormatInvariant(exporterType), e);
                    throw initException;
                }

                tProps = cfg.GetPropertyGroup(PropertySchedulerExporterPrefix, true);

                try
                {
                    ObjectUtils.SetObjectProperties(exporter, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Scheduler exporter type '{0}' props could not be configured.".FormatInvariant(exporterType), e);
                    throw initException;
                }
            }

            bool tpInited = false;
            bool qsInited = false;


            // Get ThreadExecutor Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string threadExecutorClass = cfg.GetStringProperty(PropertyThreadExecutorType);

            if (threadExecutorClass != null)
            {
                tProps = cfg.GetPropertyGroup(PropertyThreadExecutor, true);
                try
                {
                    threadExecutor = ObjectUtils.InstantiateType <IThreadExecutor>(loadHelper.LoadType(threadExecutorClass));
                    log.Info("Using custom implementation for ThreadExecutor: " + threadExecutorClass);

                    ObjectUtils.SetObjectProperties(threadExecutor, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException(
                        "ThreadExecutor class '" + threadExecutorClass + "' could not be instantiated.", e);
                    throw initException;
                }
            }
            else
            {
                log.Info("Using default implementation for ThreadExecutor");
                threadExecutor = new DefaultThreadExecutor();
            }

            // Fire everything up
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            try
            {
                IJobRunShellFactory jrsf = new StdJobRunShellFactory();

                if (autoId)
                {
                    try
                    {
                        schedInstId = DefaultInstanceId;

                        if (js.Clustered)
                        {
                            schedInstId = instanceIdGenerator.GenerateInstanceId();
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error("Couldn't generate instance Id!", e);
                        throw new SystemException("Cannot run without an instance id.");
                    }
                }

                jobStoreSupport = js as JobStoreSupport;
                if (jobStoreSupport != null)
                {
                    jobStoreSupport.DbRetryInterval = dbFailureRetry;
                    jobStoreSupport.ThreadExecutor  = threadExecutor;
                    // object serializer
                    jobStoreSupport.ObjectSerializer = objectSerializer;
                }

                QuartzSchedulerResources rsrcs = new QuartzSchedulerResources();
                rsrcs.Name                            = schedName;
                rsrcs.ThreadName                      = threadName;
                rsrcs.InstanceId                      = schedInstId;
                rsrcs.JobRunShellFactory              = jrsf;
                rsrcs.MakeSchedulerThreadDaemon       = makeSchedulerThreadDaemon;
                rsrcs.BatchTimeWindow                 = TimeSpan.FromMilliseconds(batchTimeWindow);
                rsrcs.MaxBatchSize                    = maxBatchSize;
                rsrcs.InterruptJobsOnShutdown         = interruptJobsOnShutdown;
                rsrcs.InterruptJobsOnShutdownWithWait = interruptJobsOnShutdownWithWait;
                rsrcs.SchedulerExporter               = exporter;

                SchedulerDetailsSetter.SetDetails(tp, schedName, schedInstId);

                rsrcs.ThreadExecutor = threadExecutor;
                threadExecutor.Initialize();

                rsrcs.ThreadPool = tp;

                tp.Initialize();
                tpInited = true;

                rsrcs.JobStore = js;

                // add plugins
                foreach (ISchedulerPlugin plugin in plugins)
                {
                    rsrcs.AddSchedulerPlugin(plugin);
                }

                qs       = new QuartzScheduler(rsrcs, idleWaitTime);
                qsInited = true;

                // Create Scheduler ref...
                IScheduler sched = Instantiate(rsrcs, qs);

                // set job factory if specified
                if (jobFactory != null)
                {
                    qs.JobFactory = jobFactory;
                }

                // Initialize plugins now that we have a Scheduler instance.
                for (int i = 0; i < plugins.Length; i++)
                {
                    plugins[i].Initialize(pluginNames[i], sched);
                }

                // add listeners
                foreach (IJobListener listener in jobListeners)
                {
                    qs.ListenerManager.AddJobListener(listener, EverythingMatcher <JobKey> .AllJobs());
                }
                foreach (ITriggerListener listener in triggerListeners)
                {
                    qs.ListenerManager.AddTriggerListener(listener, EverythingMatcher <TriggerKey> .AllTriggers());
                }

                // set scheduler context data...
                foreach (string key in schedCtxtProps)
                {
                    string val = schedCtxtProps.Get(key);
                    sched.Context.Put(key, val);
                }

                // fire up job store, and runshell factory

                js.InstanceId     = schedInstId;
                js.InstanceName   = schedName;
                js.ThreadPoolSize = tp.PoolSize;
                js.Initialize(loadHelper, qs.SchedulerSignaler);

                jrsf.Initialize(sched);
                qs.Initialize();

                Log.Info("Quartz scheduler '{0}' initialized".FormatInvariant(sched.SchedulerName));

                Log.Info("Quartz scheduler version: {0}".FormatInvariant(qs.Version));

                // prevents the repository from being garbage collected
                qs.AddNoGCObject(schedRep);
                // prevents the db manager from being garbage collected
                if (dbMgr != null)
                {
                    qs.AddNoGCObject(dbMgr);
                }

                schedRep.Bind(sched);

                return(sched);
            }
            catch (SchedulerException)
            {
                ShutdownFromInstantiateException(tp, qs, tpInited, qsInited);
                throw;
            }
            catch
            {
                ShutdownFromInstantiateException(tp, qs, tpInited, qsInited);
                throw;
            }
        }
Example #2
0
        /// <summary>  </summary>
        private IScheduler Instantiate()
        {
            if (cfg == null)
            {
                Initialize();
            }

            if (initException != null)
            {
                throw initException;
            }

            ISchedulerExporter exporter = null;
            IJobStore js;
            IThreadPool tp;
            QuartzScheduler qs = null;
            DBConnectionManager dbMgr = null;
            Type instanceIdGeneratorType = null;
            NameValueCollection tProps;
            bool autoId = false;
            TimeSpan idleWaitTime = TimeSpan.Zero;
            TimeSpan dbFailureRetry = TimeSpan.FromSeconds(15);
            IThreadExecutor threadExecutor;

            SchedulerRepository schedRep = SchedulerRepository.Instance;

            // Get Scheduler Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string schedName = cfg.GetStringProperty(PropertySchedulerInstanceName, "QuartzScheduler");
            string threadName = cfg.GetStringProperty(PropertySchedulerThreadName, "{0}_QuartzSchedulerThread".FormatInvariant(schedName));
            string schedInstId = cfg.GetStringProperty(PropertySchedulerInstanceId, DefaultInstanceId);

            if (schedInstId.Equals(AutoGenerateInstanceId))
            {
                autoId = true;
                instanceIdGeneratorType = LoadType(cfg.GetStringProperty(PropertySchedulerInstanceIdGeneratorType)) ?? typeof(SimpleInstanceIdGenerator);
            }
            else if (schedInstId.Equals(SystemPropertyAsInstanceId))
            {
                autoId = true;
                instanceIdGeneratorType = typeof(SystemPropertyInstanceIdGenerator);
            }

            Type typeLoadHelperType = LoadType(cfg.GetStringProperty(PropertySchedulerTypeLoadHelperType));
            Type jobFactoryType = LoadType(cfg.GetStringProperty(PropertySchedulerJobFactoryType, null));

            idleWaitTime = cfg.GetTimeSpanProperty(PropertySchedulerIdleWaitTime, idleWaitTime);
            if (idleWaitTime > TimeSpan.Zero && idleWaitTime < TimeSpan.FromMilliseconds(1000))
            {
                throw new SchedulerException("quartz.scheduler.idleWaitTime of less than 1000ms is not legal.");
            }

            dbFailureRetry = cfg.GetTimeSpanProperty(PropertySchedulerDbFailureRetryInterval, dbFailureRetry);
            if (dbFailureRetry < TimeSpan.Zero)
            {
                throw new SchedulerException(PropertySchedulerDbFailureRetryInterval + " of less than 0 ms is not legal.");
            }

            bool makeSchedulerThreadDaemon = cfg.GetBooleanProperty(PropertySchedulerMakeSchedulerThreadDaemon);
            long batchTimeWindow = cfg.GetLongProperty(PropertySchedulerBatchTimeWindow, 0L);
            int maxBatchSize = cfg.GetIntProperty(PropertySchedulerMaxBatchSize, 1);

            bool interruptJobsOnShutdown = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdown, false);
            bool interruptJobsOnShutdownWithWait = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdownWithWait, false);

            NameValueCollection schedCtxtProps = cfg.GetPropertyGroup(PropertySchedulerContextPrefix, true);

            bool proxyScheduler = cfg.GetBooleanProperty(PropertySchedulerProxy, false);

            // Create type load helper
            ITypeLoadHelper loadHelper;
            try
            {
                loadHelper = ObjectUtils.InstantiateType<ITypeLoadHelper>(typeLoadHelperType ?? typeof(SimpleTypeLoadHelper));
            }
            catch (Exception e)
            {
                throw new SchedulerConfigException("Unable to instantiate type load helper: {0}".FormatInvariant(e.Message), e);
            }
            loadHelper.Initialize();

            // If Proxying to remote scheduler, short-circuit here...
            // ~~~~~~~~~~~~~~~~~~
            if (proxyScheduler)
            {
                if (autoId)
                {
                    schedInstId = DefaultInstanceId;
                }

                Type proxyType = loadHelper.LoadType(cfg.GetStringProperty(PropertySchedulerProxyType)) ?? typeof(RemotingSchedulerProxyFactory);
                IRemotableSchedulerProxyFactory factory;
                try
                {
                    factory = ObjectUtils.InstantiateType<IRemotableSchedulerProxyFactory>(proxyType);
                    ObjectUtils.SetObjectProperties(factory, cfg.GetPropertyGroup(PropertySchedulerProxy, true));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Remotable proxy factory '{0}' could not be instantiated.".FormatInvariant(proxyType), e);
                    throw initException;
                }

                string uid = QuartzSchedulerResources.GetUniqueIdentifier(schedName, schedInstId);

                RemoteScheduler remoteScheduler = new RemoteScheduler(uid, factory);

                schedRep.Bind(remoteScheduler);

                return remoteScheduler;
            }

            IJobFactory jobFactory = null;
            if (jobFactoryType != null)
            {
                try
                {
                    jobFactory = ObjectUtils.InstantiateType<IJobFactory>(jobFactoryType);
                }
                catch (Exception e)
                {
                    throw new SchedulerConfigException("Unable to Instantiate JobFactory: {0}".FormatInvariant(e.Message), e);
                }

                tProps = cfg.GetPropertyGroup(PropertySchedulerJobFactoryPrefix, true);
                try
                {
                    ObjectUtils.SetObjectProperties(jobFactory, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobFactory of type '{0}' props could not be configured.".FormatInvariant(jobFactoryType), e);
                    throw initException;
                }
            }

            IInstanceIdGenerator instanceIdGenerator = null;
            if (instanceIdGeneratorType != null)
            {
                try
                {
                    instanceIdGenerator = ObjectUtils.InstantiateType<IInstanceIdGenerator>(instanceIdGeneratorType);
                }
                catch (Exception e)
                {
                    throw new SchedulerConfigException("Unable to Instantiate InstanceIdGenerator: {0}".FormatInvariant(e.Message), e);
                }
                tProps = cfg.GetPropertyGroup(PropertySchedulerInstanceIdGeneratorPrefix, true);
                try
                {
                    ObjectUtils.SetObjectProperties(instanceIdGenerator, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("InstanceIdGenerator of type '{0}' props could not be configured.".FormatInvariant(instanceIdGeneratorType), e);
                    throw initException;
                }
            }

            // Get ThreadPool Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            Type tpType = loadHelper.LoadType(cfg.GetStringProperty(PropertyThreadPoolType)) ?? typeof(SimpleThreadPool);

            try
            {
                tp = ObjectUtils.InstantiateType<IThreadPool>(tpType);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e);
                throw initException;
            }
            tProps = cfg.GetPropertyGroup(PropertyThreadPoolPrefix, true);
            try
            {
                ObjectUtils.SetObjectProperties(tp, tProps);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("ThreadPool type '{0}' props could not be configured.".FormatInvariant(tpType), e);
                throw initException;
            }

            // Set up any DataSources
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string[] dsNames = cfg.GetPropertyGroups(PropertyDataSourcePrefix);
            for (int i = 0; i < dsNames.Length; i++)
            {
                string datasourceKey = "{0}.{1}".FormatInvariant( PropertyDataSourcePrefix, dsNames[i]);
                NameValueCollection propertyGroup = cfg.GetPropertyGroup(datasourceKey, true);
                PropertiesParser pp = new PropertiesParser(propertyGroup);

                Type cpType = loadHelper.LoadType(pp.GetStringProperty(PropertyDbProviderType, null));

                // custom connectionProvider...
                if (cpType != null)
                {
                    IDbProvider cp;
                    try
                    {
                        cp = ObjectUtils.InstantiateType<IDbProvider>(cpType);
                    }
                    catch (Exception e)
                    {
                        initException = new SchedulerException("ConnectionProvider of type '{0}' could not be instantiated.".FormatInvariant(cpType), e);
                        throw initException;
                    }

                    try
                    {
                        // remove the type name, so it isn't attempted to be set
                        pp.UnderlyingProperties.Remove(PropertyDbProviderType);

                        ObjectUtils.SetObjectProperties(cp, pp.UnderlyingProperties);
                        cp.Initialize();
                    }
                    catch (Exception e)
                    {
                        initException = new SchedulerException("ConnectionProvider type '{0}' props could not be configured.".FormatInvariant(cpType), e);
                        throw initException;
                    }

                    dbMgr = DBConnectionManager.Instance;
                    dbMgr.AddConnectionProvider(dsNames[i], cp);
                }
                else
                {
                    string dsProvider = pp.GetStringProperty(PropertyDataSourceProvider, null);
                    string dsConnectionString = pp.GetStringProperty(PropertyDataSourceConnectionString, null);
                    string dsConnectionStringName = pp.GetStringProperty(PropertyDataSourceConnectionStringName, null);

                    if (dsConnectionString == null && !String.IsNullOrEmpty(dsConnectionStringName))
                    {

                        ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[dsConnectionStringName];
                        if (connectionStringSettings == null)
                        {
                            initException = new SchedulerException("Named connection string '{0}' not found for DataSource: {1}".FormatInvariant(dsConnectionStringName,  dsNames[i]));
                            throw initException;
                        }
                        dsConnectionString = connectionStringSettings.ConnectionString;
                    }

                    if (dsProvider == null)
                    {
                        initException = new SchedulerException("Provider not specified for DataSource: {0}".FormatInvariant(dsNames[i]));
                        throw initException;
                    }
                    if (dsConnectionString == null)
                    {
                        initException = new SchedulerException("Connection string not specified for DataSource: {0}".FormatInvariant(dsNames[i]));
                        throw initException;
                    }
                    try
                    {
                        DbProvider dbp = new DbProvider(dsProvider, dsConnectionString);
                        dbp.Initialize();

                        dbMgr = DBConnectionManager.Instance;
                        dbMgr.AddConnectionProvider(dsNames[i], dbp);
                    }
                    catch (Exception exception)
                    {
                        initException = new SchedulerException("Could not Initialize DataSource: {0}".FormatInvariant(dsNames[i]), exception);
                        throw initException;
                    }
                }
            }

            // Get object serializer properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            IObjectSerializer objectSerializer;
            string objectSerializerType = cfg.GetStringProperty("quartz.serializer.type");
            if (objectSerializerType != null)
            {
                tProps = cfg.GetPropertyGroup(PropertyObjectSerializer, true);
                try
                {
                    objectSerializer = ObjectUtils.InstantiateType<IObjectSerializer>(loadHelper.LoadType(objectSerializerType));
                    log.Info("Using custom implementation for object serializer: " + objectSerializerType);

                    ObjectUtils.SetObjectProperties(objectSerializer, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Object serializer type '" + objectSerializerType + "' could not be instantiated.", e);
                    throw initException;
                }
            }
            else
            {
                log.Info("Using default implementation for object serializer");
                objectSerializer = new DefaultObjectSerializer();
            }

            // Get JobStore Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            Type jsType = loadHelper.LoadType(cfg.GetStringProperty(PropertyJobStoreType));
            try
            {
                js = ObjectUtils.InstantiateType<IJobStore>(jsType ?? typeof(RAMJobStore));
            }
            catch (Exception e)
            {
                initException = new SchedulerException("JobStore of type '{0}' could not be instantiated.".FormatInvariant(jsType), e);
                throw initException;
            }

            SchedulerDetailsSetter.SetDetails(js, schedName, schedInstId);

            tProps = cfg.GetPropertyGroup(PropertyJobStorePrefix, true, new string[] {PropertyJobStoreLockHandlerPrefix});

            try
            {
                ObjectUtils.SetObjectProperties(js, tProps);
            }
            catch (Exception e)
            {
                initException = new SchedulerException("JobStore type '{0}' props could not be configured.".FormatInvariant(jsType), e);
                throw initException;
            }

            if (js is JobStoreSupport)
            {
                // Install custom lock handler (Semaphore)
                Type lockHandlerType = loadHelper.LoadType(cfg.GetStringProperty(PropertyJobStoreLockHandlerType));
                if (lockHandlerType != null)
                {
                    try
                    {
                        ISemaphore lockHandler;
                        ConstructorInfo cWithDbProvider = lockHandlerType.GetConstructor(new Type[] {typeof (DbProvider)});

                        if (cWithDbProvider != null)
                        {
                            // takes db provider
                            IDbProvider dbProvider = DBConnectionManager.Instance.GetDbProvider(((JobStoreSupport) js).DataSource);
                            lockHandler = (ISemaphore) cWithDbProvider.Invoke(new object[] { dbProvider });
                        }
                        else
                        {
                            lockHandler = ObjectUtils.InstantiateType<ISemaphore>(lockHandlerType);
                        }

                        tProps = cfg.GetPropertyGroup(PropertyJobStoreLockHandlerPrefix, true);

                        // If this lock handler requires the table prefix, add it to its properties.
                        if (lockHandler is ITablePrefixAware)
                        {
                            tProps[PropertyTablePrefix] = ((JobStoreSupport) js).TablePrefix;
                            tProps[PropertySchedulerName] = schedName;
                        }

                        try
                        {
                            ObjectUtils.SetObjectProperties(lockHandler, tProps);
                        }
                        catch (Exception e)
                        {
                            initException = new SchedulerException("JobStore LockHandler type '{0}' props could not be configured.".FormatInvariant(lockHandlerType), e);
                            throw initException;
                        }

                        ((JobStoreSupport) js).LockHandler = lockHandler;
                        Log.Info("Using custom data access locking (synchronization): " + lockHandlerType);
                    }
                    catch (Exception e)
                    {
                        initException = new SchedulerException("JobStore LockHandler type '{0}' could not be instantiated.".FormatInvariant(lockHandlerType), e);
                        throw initException;
                    }
                }
            }

            // Set up any SchedulerPlugins
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string[] pluginNames = cfg.GetPropertyGroups(PropertyPluginPrefix);
            ISchedulerPlugin[] plugins = new ISchedulerPlugin[pluginNames.Length];
            for (int i = 0; i < pluginNames.Length; i++)
            {
                NameValueCollection pp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyPluginPrefix, pluginNames[i]), true);

                string plugInType = pp[PropertyPluginType] ?? null;

                if (plugInType == null)
                {
                    initException = new SchedulerException("SchedulerPlugin type not specified for plugin '{0}'".FormatInvariant(pluginNames[i]));
                    throw initException;
                }
                ISchedulerPlugin plugin;
                try
                {
                    plugin = ObjectUtils.InstantiateType<ISchedulerPlugin>(LoadType(plugInType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("SchedulerPlugin of type '{0}' could not be instantiated.".FormatInvariant(plugInType), e);
                    throw initException;
                }
                try
                {
                    ObjectUtils.SetObjectProperties(plugin, pp);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobStore SchedulerPlugin '{0}' props could not be configured.".FormatInvariant(plugInType), e);
                    throw initException;
                }
                plugins[i] = plugin;
            }

            // Set up any JobListeners
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            string[] jobListenerNames = cfg.GetPropertyGroups(PropertyJobListenerPrefix);
            IJobListener[] jobListeners = new IJobListener[jobListenerNames.Length];
            for (int i = 0; i < jobListenerNames.Length; i++)
            {
                NameValueCollection lp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyJobListenerPrefix, jobListenerNames[i]), true);

                string listenerType = lp[PropertyListenerType];

                if (listenerType == null)
                {
                    initException = new SchedulerException("JobListener type not specified for listener '{0}'".FormatInvariant(jobListenerNames[i]));
                    throw initException;
                }
                IJobListener listener;
                try
                {
                    listener = ObjectUtils.InstantiateType<IJobListener>(loadHelper.LoadType(listenerType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobListener of type '{0}' could not be instantiated.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                try
                {
                    PropertyInfo nameProperty = listener.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
                    if (nameProperty != null && nameProperty.CanWrite)
                    {
                        nameProperty.GetSetMethod().Invoke(listener, new object[] {jobListenerNames[i]});
                    }
                    ObjectUtils.SetObjectProperties(listener, lp);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("JobListener '{0}' props could not be configured.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                jobListeners[i] = listener;
            }

            // Set up any TriggerListeners
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string[] triggerListenerNames = cfg.GetPropertyGroups(PropertyTriggerListenerPrefix);
            ITriggerListener[] triggerListeners = new ITriggerListener[triggerListenerNames.Length];
            for (int i = 0; i < triggerListenerNames.Length; i++)
            {
                NameValueCollection lp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyTriggerListenerPrefix, triggerListenerNames[i]), true);

                string listenerType = lp[PropertyListenerType];

                if (listenerType == null)
                {
                    initException = new SchedulerException("TriggerListener type not specified for listener '{0}'".FormatInvariant(triggerListenerNames[i]));
                    throw initException;
                }
                ITriggerListener listener;
                try
                {
                    listener = ObjectUtils.InstantiateType<ITriggerListener>(loadHelper.LoadType(listenerType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("TriggerListener of type '{0}' could not be instantiated.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                try
                {
                    PropertyInfo nameProperty = listener.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
                    if (nameProperty != null && nameProperty.CanWrite)
                    {
                        nameProperty.GetSetMethod().Invoke(listener, new object[] {triggerListenerNames[i]});
                    }
                    ObjectUtils.SetObjectProperties(listener, lp);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("TriggerListener '{0}' props could not be configured.".FormatInvariant(listenerType), e);
                    throw initException;
                }
                triggerListeners[i] = listener;
            }

            // Get exporter
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string exporterType = cfg.GetStringProperty(PropertySchedulerExporterType, null);

            if (exporterType != null)
            {
                try
                {
                    exporter = ObjectUtils.InstantiateType<ISchedulerExporter>(loadHelper.LoadType(exporterType));
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Scheduler exporter of type '{0}' could not be instantiated.".FormatInvariant(exporterType), e);
                    throw initException;
                }

                tProps = cfg.GetPropertyGroup(PropertySchedulerExporterPrefix, true);

                try
                {
                    ObjectUtils.SetObjectProperties(exporter, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException("Scheduler exporter type '{0}' props could not be configured.".FormatInvariant(exporterType), e);
                    throw initException;
                }
            }

            bool tpInited = false;
            bool qsInited = false;

            // Get ThreadExecutor Properties
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            string threadExecutorClass = cfg.GetStringProperty(PropertyThreadExecutorType);
            if (threadExecutorClass != null)
            {
                tProps = cfg.GetPropertyGroup(PropertyThreadExecutor, true);
                try
                {
                    threadExecutor = ObjectUtils.InstantiateType<IThreadExecutor>(loadHelper.LoadType(threadExecutorClass));
                    log.Info("Using custom implementation for ThreadExecutor: " + threadExecutorClass);

                    ObjectUtils.SetObjectProperties(threadExecutor, tProps);
                }
                catch (Exception e)
                {
                    initException = new SchedulerException(
                            "ThreadExecutor class '" + threadExecutorClass + "' could not be instantiated.", e);
                    throw initException;
                }
            }
            else
            {
                log.Info("Using default implementation for ThreadExecutor");
                threadExecutor = new DefaultThreadExecutor();
            }

            // Fire everything up
            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            try
            {
                IJobRunShellFactory jrsf = new StdJobRunShellFactory();

                if (autoId)
                {
                    try
                    {
                        schedInstId = DefaultInstanceId;

                        if (js.Clustered)
                        {
                            schedInstId = instanceIdGenerator.GenerateInstanceId();
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error("Couldn't generate instance Id!", e);
                        throw new SystemException("Cannot run without an instance id.");
                    }
                }

                if (js is JobStoreSupport)
                {
                    JobStoreSupport jjs = (JobStoreSupport) js;
                    jjs.DbRetryInterval = dbFailureRetry;
                    jjs.ThreadExecutor = threadExecutor;
                    // object serializer
                    jjs.ObjectSerializer = objectSerializer;
                }

                QuartzSchedulerResources rsrcs = new QuartzSchedulerResources();
                rsrcs.Name = schedName;
                rsrcs.ThreadName = threadName;
                rsrcs.InstanceId = schedInstId;
                rsrcs.JobRunShellFactory = jrsf;
                rsrcs.MakeSchedulerThreadDaemon = makeSchedulerThreadDaemon;
                rsrcs.BatchTimeWindow = TimeSpan.FromMilliseconds(batchTimeWindow);
                rsrcs.MaxBatchSize = maxBatchSize;
                rsrcs.InterruptJobsOnShutdown = interruptJobsOnShutdown;
                rsrcs.InterruptJobsOnShutdownWithWait = interruptJobsOnShutdownWithWait;
                rsrcs.SchedulerExporter = exporter;

                SchedulerDetailsSetter.SetDetails(tp, schedName, schedInstId);

                rsrcs.ThreadExecutor = threadExecutor;
                threadExecutor.Initialize();

                rsrcs.ThreadPool = tp;

                if (tp is SimpleThreadPool)
                {
                    ((SimpleThreadPool) tp).ThreadNamePrefix = schedName + "_Worker";
                }
                tp.Initialize();
                tpInited = true;

                rsrcs.JobStore = js;

                // add plugins
                for (int i = 0; i < plugins.Length; i++)
                {
                    rsrcs.AddSchedulerPlugin(plugins[i]);
                }

                qs = new QuartzScheduler(rsrcs, idleWaitTime, dbFailureRetry);
                qsInited = true;

                // Create Scheduler ref...
                IScheduler sched = Instantiate(rsrcs, qs);

                // set job factory if specified
                if (jobFactory != null)
                {
                    qs.JobFactory = jobFactory;
                }

                // Initialize plugins now that we have a Scheduler instance.
                for (int i = 0; i < plugins.Length; i++)
                {
                    plugins[i].Initialize(pluginNames[i], sched);
                }

                // add listeners
                for (int i = 0; i < jobListeners.Length; i++)
                {
                    qs.ListenerManager.AddJobListener(jobListeners[i], EverythingMatcher<JobKey>.AllJobs());
                }
                for (int i = 0; i < triggerListeners.Length; i++)
                {
                    qs.ListenerManager.AddTriggerListener(triggerListeners[i], EverythingMatcher<TriggerKey>.AllTriggers());
                }

                // set scheduler context data...
                foreach (string key in schedCtxtProps)
                {
                    string val = schedCtxtProps.Get(key);
                    sched.Context.Put(key, val);
                }

                // fire up job store, and runshell factory

                js.InstanceId = schedInstId;
                js.InstanceName = schedName;
                js.ThreadPoolSize = tp.PoolSize;
                js.Initialize(loadHelper, qs.SchedulerSignaler);

                jrsf.Initialize(sched);
                qs.Initialize();

                Log.Info("Quartz scheduler '{0}' initialized".FormatInvariant(sched.SchedulerName));

                Log.Info("Quartz scheduler version: {0}".FormatInvariant(qs.Version));

                // prevents the repository from being garbage collected
                qs.AddNoGCObject(schedRep);
                // prevents the db manager from being garbage collected
                if (dbMgr != null)
                {
                    qs.AddNoGCObject(dbMgr);
                }

                schedRep.Bind(sched);

                return sched;
            }
            catch (SchedulerException)
            {
                if (qsInited)
                {
                    qs.Shutdown(false);
                }
                else if (tpInited)
                {
                    tp.Shutdown(false);
                }
                throw;
            }
            catch
            {
                if (qsInited)
                {
                    qs.Shutdown(false);
                }
                else if (tpInited)
                {
                    tp.Shutdown(false);
                }
                throw;
            }
        }