removing refs to linking of files from Quartz1x projects
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using Spring.Objects.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception that wraps an exception thrown from a target method.
|
||||
/// Propagated to the Quartz scheduler from a Job that reflectively invokes
|
||||
/// an arbitrary target method.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="MethodInvokingJobDetailFactoryObject" />
|
||||
public class JobMethodInvocationFailedException : Exception // TODO, in Java NestedRuntimeException
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for JobMethodInvocationFailedException.
|
||||
/// </summary>
|
||||
/// <param name="methodInvoker">the MethodInvoker used for reflective invocation</param>
|
||||
/// <param name="cause">the root cause (as thrown from the target method)</param>
|
||||
public JobMethodInvocationFailedException(MethodInvoker methodInvoker, Exception cause) :
|
||||
base("Invocation of method '" + methodInvoker.TargetMethod +
|
||||
"' on target class [" + methodInvoker.TargetType + "] failed", cause)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using Quartz.Util;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobDetail = Quartz.IJobDetail;
|
||||
#else
|
||||
using JobDetail = Quartz.JobDetail;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// JobFactory implementation that supports <see cref="ThreadStart" />
|
||||
/// objects as well as standard Quartz <see cref="IJob" /> instances.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="DelegatingJob" />
|
||||
/// <seealso cref="AdaptJob(object)" />
|
||||
public class AdaptableJobFactory : IJobFactory
|
||||
{
|
||||
#if QUARTZ_2_0
|
||||
/// <summary>
|
||||
/// Called by the scheduler at the time of the trigger firing, in order to
|
||||
/// produce a <see cref="IJob"/> instance on which to call Execute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It should be extremely rare for this method to throw an exception -
|
||||
/// basically only the the case where there is no way at all to instantiate
|
||||
/// and prepare the Job for execution. When the exception is thrown, the
|
||||
/// Scheduler will move all triggers associated with the Job into the
|
||||
/// <see cref="TriggerState.Error"/> state, which will require human
|
||||
/// intervention (e.g. an application restart after fixing whatever
|
||||
/// configuration problem led to the issue wih instantiating the Job.
|
||||
/// </remarks>
|
||||
/// <param name="bundle">The TriggerFiredBundle from which the <see cref="JobDetail"/>
|
||||
/// and other info relating to the trigger firing can be obtained.</param>
|
||||
/// <param name="scheduler">The scheduler instance.</param>
|
||||
/// <returns>the newly instantiated Job</returns>
|
||||
/// <throws>SchedulerException if there is a problem instantiating the Job.</throws>
|
||||
public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||
#else
|
||||
/// <summary>
|
||||
/// Called by the scheduler at the time of the trigger firing, in order to
|
||||
/// produce a <see cref="IJob"/> instance on which to call Execute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It should be extremely rare for this method to throw an exception -
|
||||
/// basically only the the case where there is no way at all to instantiate
|
||||
/// and prepare the Job for execution. When the exception is thrown, the
|
||||
/// Scheduler will move all triggers associated with the Job into the
|
||||
/// <see cref="TriggerState.Error"/> state, which will require human
|
||||
/// intervention (e.g. an application restart after fixing whatever
|
||||
/// configuration problem led to the issue wih instantiating the Job.
|
||||
/// </remarks>
|
||||
/// <param name="bundle">The TriggerFiredBundle from which the <see cref="JobDetail"/>
|
||||
/// and other info relating to the trigger firing can be obtained.</param>
|
||||
/// <returns>the newly instantiated Job</returns>
|
||||
/// <throws>SchedulerException if there is a problem instantiating the Job.</throws>
|
||||
public virtual IJob NewJob(TriggerFiredBundle bundle)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
object jobObject = CreateJobInstance(bundle);
|
||||
return AdaptJob(jobObject);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new SchedulerException("Job instantiation failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of the specified job class.
|
||||
/// <p>
|
||||
/// Can be overridden to post-process the job instance.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <param name="bundle">
|
||||
/// The TriggerFiredBundle from which the JobDetail
|
||||
/// and other info relating to the trigger firing can be obtained.
|
||||
/// </param>
|
||||
/// <returns>The job instance.</returns>
|
||||
protected virtual object CreateJobInstance(TriggerFiredBundle bundle)
|
||||
{
|
||||
#if QUARTZ_2_0
|
||||
return ObjectUtils.InstantiateType<object>(bundle.JobDetail.JobType);
|
||||
#else
|
||||
return ObjectUtils.InstantiateType(bundle.JobDetail.JobType);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapt the given job object to the Quartz Job interface.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default implementation supports straight Quartz Jobs
|
||||
/// as well as Runnables, which get wrapped in a DelegatingJob.
|
||||
/// </remarks>
|
||||
/// <param name="jobObject">
|
||||
/// The original instance of the specified job class.
|
||||
/// </param>
|
||||
/// <returns>The adapted Quartz Job instance.</returns>
|
||||
/// <seealso cref="DelegatingJob" />
|
||||
protected virtual IJob AdaptJob(object jobObject)
|
||||
{
|
||||
if (jobObject is IJob)
|
||||
{
|
||||
return (IJob)jobObject;
|
||||
}
|
||||
if (jobObject is ThreadStart)
|
||||
{
|
||||
return new DelegatingJob((ThreadStart)jobObject);
|
||||
}
|
||||
if (jobObject is IThreadRunnable)
|
||||
{
|
||||
return new DelegatingJob(((IThreadRunnable)jobObject).Run);
|
||||
}
|
||||
|
||||
string message = string.Format("Unable to execute job class [{0}]: only [IJob] and [ThreadStart] supported.", jobObject.GetType().FullName);
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System.Threading;
|
||||
|
||||
using Quartz;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobExecutionContext = Quartz.IJobExecutionContext;
|
||||
#else
|
||||
using JobExecutionContext = Quartz.JobExecutionContext;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple Quartz IJob adapter that delegates to a
|
||||
/// given <see cref="ThreadStart" /> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Typically used in combination with property injection on the
|
||||
/// Runnable instance, receiving parameters from the Quartz JobDataMap
|
||||
/// that way instead of via the JobExecutionContext.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
/// <seealso cref="IJob.Execute(JobExecutionContext)" />
|
||||
public class DelegatingJob : IJob
|
||||
{
|
||||
private readonly ThreadStart delegateInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Return the wrapped Runnable implementation.
|
||||
/// </summary>
|
||||
/// <value>The delegate.</value>
|
||||
public virtual ThreadStart Delegate
|
||||
{
|
||||
get { return delegateInstance; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new DelegatingJob.
|
||||
/// </summary>
|
||||
/// <param name="delegateInstance">
|
||||
/// The Runnable implementation to delegate to.
|
||||
/// </param>
|
||||
public DelegatingJob(ThreadStart delegateInstance)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(delegateInstance, "delegateInstance", "Delegate must not be null");
|
||||
this.delegateInstance = delegateInstance;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Delegates execution to the underlying ThreadStart.
|
||||
/// </summary>
|
||||
public virtual void Execute(JobExecutionContext context)
|
||||
{
|
||||
delegateInstance.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobDetail = Quartz.IJobDetail;
|
||||
#else
|
||||
using JobDetail = Quartz.JobDetail;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to be implemented by Quartz Triggers that are aware
|
||||
/// of the JobDetail object that they are associated with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// SchedulerFactoryObject will auto-detect Triggers that implement this
|
||||
/// interface and register them for the respective JobDetail accordingly.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// The alternative is to configure a Trigger for a Job name and group:
|
||||
/// This involves the need to register the JobDetail object separately
|
||||
/// with SchedulerFactoryObject.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerAccessor.Triggers" />
|
||||
/// <seealso cref="SchedulerAccessor.JobDetails" />
|
||||
public interface IJobDetailAwareTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the JobDetail that this Trigger is associated with.
|
||||
/// </summary>
|
||||
/// <returns>The associated JobDetail, or <code>null</code> if none</returns>
|
||||
JobDetail JobDetail { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Callback interface to be implemented by Spring-managed
|
||||
/// Quartz artifacts that need access to the SchedulerContext
|
||||
/// (without having natural access to it).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently only supported for custom JobFactory implementations
|
||||
/// that are passed in via Spring's SchedulerFactoryObject.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="IJobFactory" />
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public interface ISchedulerContextAware
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the SchedulerContext of the current Quartz Scheduler.
|
||||
/// </summary>
|
||||
/// <seealso cref="IScheduler.Context" />
|
||||
SchedulerContext SchedulerContext { set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace Spring.Scheduling
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ISchedulingTaskExecutor : ITaskExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether<65>this instance prefers short lived tasks.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if prefers short lived tasks; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
bool PrefersShortLivedTasks { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace Spring.Scheduling
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ITaskExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes this instance.
|
||||
/// </summary>
|
||||
void Execute(ThreadStart runnable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl.AdoJobStore;
|
||||
using Quartz.Util;
|
||||
|
||||
using Spring.Data.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclass of Quartz's JobStoreCMT class that delegates to a Spring-managed
|
||||
/// DataSource instead of using a Quartz-managed connection pool. This JobStore
|
||||
/// will be used if SchedulerFactoryObject's "dbProvider" property is set.
|
||||
///</summary>
|
||||
/// <remarks>
|
||||
/// <p>Operations performed by this JobStore will properly participate in any
|
||||
/// kind of Spring-managed transaction, as it uses Spring's DataSourceUtils
|
||||
/// connection handling methods that are aware of a current transaction.</p>
|
||||
///
|
||||
/// <p>Note that all Quartz Scheduler operations that affect the persistent
|
||||
/// job store should usually be performed within active transactions,
|
||||
/// as they assume to get proper locks etc.</p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="ConnectionUtils.GetConnection" />
|
||||
/// <seealso cref="ConnectionUtils.DisposeConnection" />
|
||||
public class LocalDataSourceJobStore : JobStoreCMT
|
||||
{
|
||||
/// <summary>
|
||||
/// Name used for the transactional ConnectionProvider for Quartz.
|
||||
/// This provider will delegate to the local Spring-managed DataSource.
|
||||
/// <seealso cref="DBConnectionManager.AddConnectionProvider" />
|
||||
/// <seealso cref="SchedulerFactoryObject.DbProvider" />
|
||||
/// </summary>
|
||||
public const string TX_DATA_SOURCE_PREFIX = "springTxDataSource.";
|
||||
|
||||
private Data.Common.IDbProvider dbProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the instance.
|
||||
/// </summary>
|
||||
/// <value>The name of the instance.</value>
|
||||
public override string InstanceName
|
||||
{
|
||||
get { return base.InstanceName; }
|
||||
set
|
||||
{
|
||||
// use to catch property setting
|
||||
base.InstanceName = value;
|
||||
DataSource = TX_DATA_SOURCE_PREFIX + InstanceName;
|
||||
// Register transactional ConnectionProvider for Quartz.
|
||||
// Absolutely needs thread-bound DataSource to initialize.
|
||||
dbProvider = SchedulerFactoryObject.ConfigTimeDbProvider;
|
||||
if (dbProvider == null)
|
||||
{
|
||||
throw new SchedulerConfigException(
|
||||
"No db provider found for configuration - " +
|
||||
"'DbProvider' property must be set on SchedulerFactoryObject");
|
||||
}
|
||||
DBConnectionManager.Instance.AddConnectionProvider(
|
||||
TX_DATA_SOURCE_PREFIX + InstanceName, new SpringDbProviderAdapter(dbProvider));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the non managed TX connection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override ConnectionAndTransactionHolder GetNonManagedTXConnection()
|
||||
{
|
||||
ConnectionTxPair pair = ConnectionUtils.DoGetConnection(dbProvider);
|
||||
return new ConnectionAndTransactionHolder(pair.Connection, pair.Transaction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the connection.
|
||||
/// </summary>
|
||||
/// <param name="connectionAndTransactionHolder">The connection and transaction holder.</param>
|
||||
protected override void CloseConnection(ConnectionAndTransactionHolder connectionAndTransactionHolder)
|
||||
{
|
||||
// Will work for transactional and non-transactional connections.
|
||||
ConnectionUtils.DisposeConnection(connectionAndTransactionHolder.Connection, dbProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Common.Logging;
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Quartz ThreadPool adapter that delegates to a Spring-managed
|
||||
/// TaskExecutor instance, specified on SchedulerFactoryObject.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerFactoryObject.TaskExecutor" />
|
||||
public class LocalTaskExecutorThreadPool : IThreadPool
|
||||
{
|
||||
/// <summary>
|
||||
/// Logger available to subclasses.
|
||||
/// </summary>
|
||||
private readonly ILog logger;
|
||||
|
||||
private ITaskExecutor taskExecutor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalTaskExecutorThreadPool"/> class.
|
||||
/// </summary>
|
||||
public LocalTaskExecutorThreadPool()
|
||||
{
|
||||
logger = LogManager.GetLogger(GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
protected ILog Logger
|
||||
{
|
||||
get { return logger; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the pool.
|
||||
/// </summary>
|
||||
/// <value>The size of the pool.</value>
|
||||
public virtual int PoolSize
|
||||
{
|
||||
get { return - 1; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inform the <see cref="T:Quartz.Spi.IThreadPool"/> of the Scheduler instance's Id,
|
||||
/// prior to initialize being invoked.
|
||||
/// </summary>
|
||||
public string InstanceId
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inform the <see cref="T:Quartz.Spi.IThreadPool"/> of the Scheduler instance's name,
|
||||
/// prior to initialize being invoked.
|
||||
/// </summary>
|
||||
public string InstanceName
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the QuartzScheduler before the <see cref="T:System.Threading.ThreadPool"/> is
|
||||
/// used, in order to give the it a chance to Initialize.
|
||||
/// </summary>
|
||||
public virtual void Initialize()
|
||||
{
|
||||
// Absolutely needs thread-bound TaskExecutor to Initialize.
|
||||
taskExecutor = SchedulerFactoryObject.ConfigTimeTaskExecutor;
|
||||
if (taskExecutor == null)
|
||||
{
|
||||
throw new SchedulerConfigException("No local TaskExecutor found for configuration - " +
|
||||
"'taskExecutor' property must be set on SchedulerFactoryObject");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the QuartzScheduler to inform the <see cref="T:System.Threading.ThreadPool"/>
|
||||
/// that it should free up all of it's resources because the scheduler is
|
||||
/// shutting down.
|
||||
/// </summary>
|
||||
/// <param name="waitForJobsToComplete"></param>
|
||||
public virtual void Shutdown(bool waitForJobsToComplete)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Execute the given <see cref="T:Quartz.IThreadRunnable"/> in the next
|
||||
/// available <see cref="T:System.Threading.Thread"/>.
|
||||
/// </summary>
|
||||
/// <param name="runnable"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// The implementation of this interface should not throw exceptions unless
|
||||
/// there is a serious problem (i.e. a serious misconfiguration). If there
|
||||
/// are no available threads, rather it should either queue the Runnable, or
|
||||
/// block until a thread is available, depending on the desired strategy.
|
||||
/// </remarks>
|
||||
public virtual bool RunInThread(IThreadRunnable runnable)
|
||||
{
|
||||
if (runnable == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
taskExecutor.Execute(runnable.Run);
|
||||
return true;
|
||||
}
|
||||
catch (TaskRejectedException ex)
|
||||
{
|
||||
logger.Error("Task has been rejected by TaskExecutor", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the number of threads that are currently available in in
|
||||
/// the pool. Useful for determining the number of times
|
||||
/// <see cref="M:Quartz.Spi.IThreadPool.RunInThread(Quartz.IThreadRunnable)"/> can be called before returning
|
||||
/// false.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the number of currently available threads
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The implementation of this method should block until there is at
|
||||
/// least one available thread.
|
||||
/// </remarks>
|
||||
public virtual int BlockForAvailableThreads()
|
||||
{
|
||||
// The present implementation always returns 1, making Quartz (1.6)
|
||||
// always schedule any tasks that it feels like scheduling.
|
||||
// This could be made smarter for specific TaskExecutors,
|
||||
// for example calling <code>getMaximumPoolSize() - getActiveCount()</code>
|
||||
// on a <code>java.util.concurrent.ThreadPoolExecutor</code>.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using Common.Logging;
|
||||
|
||||
using Quartz;
|
||||
|
||||
using Spring.Objects.Support;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobExecutionContext = Quartz.IJobExecutionContext;
|
||||
#else
|
||||
using JobExecutionContext = Quartz.JobExecutionContext;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Quartz Job implementation that invokes a specified method.
|
||||
/// Automatically applied by MethodInvokingJobDetailFactoryObject.
|
||||
/// </summary>
|
||||
public class MethodInvokingJob : QuartzJobObject
|
||||
{
|
||||
private static readonly ILog logger = LogManager.GetLogger(typeof(MethodInvokingJob));
|
||||
private MethodInvoker methodInvoker;
|
||||
private string errorMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Set the MethodInvoker to use.
|
||||
/// </summary>
|
||||
public virtual MethodInvoker MethodInvoker
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentException("Method invoker cannot be null", "value");
|
||||
}
|
||||
methodInvoker = value;
|
||||
errorMessage =
|
||||
string.Format("Could not invoke method '{0}' on target object [{1}]", methodInvoker.TargetMethod,
|
||||
methodInvoker.TargetObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invoke the method via the MethodInvoker.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected override void ExecuteInternal(JobExecutionContext context)
|
||||
{
|
||||
if (methodInvoker == null)
|
||||
{
|
||||
throw new JobExecutionException("Could not execute job when method invoker is null");
|
||||
}
|
||||
try
|
||||
{
|
||||
context.Result = methodInvoker.Invoke();
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
logger.Error(errorMessage, ex.GetBaseException());
|
||||
if (ex.GetBaseException() is JobExecutionException)
|
||||
{
|
||||
// -> JobExecutionException, to be logged at info level by Quartz
|
||||
throw ex.GetBaseException();
|
||||
}
|
||||
// -> "unhandled exception", to be logged at error level by Quartz
|
||||
throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// -> "unhandled exception", to be logged at error level by Quartz
|
||||
throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using Common.Logging;
|
||||
|
||||
using Quartz;
|
||||
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapter that implements the Runnable interface as a configurable
|
||||
/// method invocation based on Spring's MethodInvoker.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Derives from ArgumentConvertingMethodInvoker, inheriting common
|
||||
/// configuration properties from MethodInvoker.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Useful to generically encapsulate a method invocation as timer task for
|
||||
/// <code>java.util.Timer</code>, in combination with a DelegatingTimerTask adapter.
|
||||
/// Can also be used with JDK 1.5's <code>java.util.concurrent.Executor</code>
|
||||
/// abstraction, which works with plain Runnables.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Extended by Spring's MethodInvokingTimerTaskFactoryObject adapter
|
||||
/// for <code>TimerTask</code>. Note that you can populate a
|
||||
/// ScheduledTimerTask object with a plain MethodInvokingRunnable instance
|
||||
/// as well, which will automatically get wrapped with a DelegatingTimerTask.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="MethodInvoker" />
|
||||
/// <seealso cref="ArgumentConvertingMethodInvoker" />
|
||||
public class MethodInvokingRunnable : ArgumentConvertingMethodInvoker, IInitializingObject, IThreadRunnable
|
||||
{
|
||||
/// <summary>
|
||||
/// Logger instance shared by this instance and its sub-class instances.
|
||||
/// </summary>
|
||||
private readonly ILog logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MethodInvokingRunnable"/> class.
|
||||
/// </summary>
|
||||
public MethodInvokingRunnable()
|
||||
{
|
||||
logger = LogManager.GetLogger(GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logger instance.
|
||||
/// </summary>
|
||||
protected ILog Logger
|
||||
{
|
||||
get { return logger; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the invocation failure message.
|
||||
/// </summary>
|
||||
/// <value>The invocation failure message.</value>
|
||||
protected virtual string InvocationFailureMessage
|
||||
{
|
||||
get { return string.Format("Invocation of method '{0}' on target object [{1}] failed", TargetMethod, TargetObject); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
Prepare();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method has to be implemented in order that starting of the thread causes the object's
|
||||
/// run method to be called in that separately executing thread.
|
||||
/// </summary>
|
||||
public virtual void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Invoke();
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
logger.Error(InvocationFailureMessage, ex);
|
||||
// Do not throw exception, else the main loop of the Timer will stop!
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(InvocationFailureMessage, ex);
|
||||
// Do not throw exception, else the main loop of the Timer will stop!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using Quartz;
|
||||
|
||||
using Spring.Objects;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobExecutionContext = Quartz.IJobExecutionContext;
|
||||
#else
|
||||
using JobExecutionContext = Quartz.JobExecutionContext;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple implementation of the Quartz Job interface, applying the
|
||||
/// passed-in JobDataMap and also the SchedulerContext as object property
|
||||
/// values. This is appropriate because a new Job instance will be created
|
||||
/// for each execution. JobDataMap entries will override SchedulerContext
|
||||
/// entries with the same keys.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// For example, let's assume that the JobDataMap contains a key
|
||||
/// "myParam" with value "5": The Job implementation can then expose
|
||||
/// a object property "myParam" of type int to receive such a value,
|
||||
/// i.e. a method "setMyParam(int)". This will also work for complex
|
||||
/// types like business objects etc.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Note: The QuartzJobObject class itself only implements the standard
|
||||
/// Quartz IJob interface. Let your subclass explicitly implement the
|
||||
/// Quartz IStatefulJob interface to mark your concrete job object as stateful.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="JobExecutionContext.MergedJobDataMap" />
|
||||
/// <seealso cref="IScheduler.Context" />
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
/// <seealso cref="CronTriggerObject.JobDataAsMap" />
|
||||
/// <seealso cref="SchedulerFactoryObject.SchedulerContextAsMap" />
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
public abstract class QuartzJobObject : IJob
|
||||
{
|
||||
/// <summary>
|
||||
/// This implementation applies the passed-in job data map as object property
|
||||
/// values, and delegates to <code>ExecuteInternal</code> afterwards.
|
||||
/// </summary>
|
||||
/// <seealso cref="ExecuteInternal" />
|
||||
public void Execute(JobExecutionContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
ObjectWrapper bw = new ObjectWrapper(this);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.AddAll(context.Scheduler.Context);
|
||||
pvs.AddAll(context.MergedJobDataMap);
|
||||
bw.SetPropertyValues(pvs, true);
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
throw new JobExecutionException(ex);
|
||||
}
|
||||
ExecuteInternal(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the actual job. The job data map will already have been
|
||||
/// applied as object property values by execute. The contract is
|
||||
/// exactly the same as for the standard Quartz execute method.
|
||||
/// </summary>
|
||||
/// <seealso cref="Execute" />
|
||||
protected abstract void ExecuteInternal(JobExecutionContext context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Spring class for accessing a Quartz Scheduler, i.e. for registering jobs,
|
||||
/// triggers and listeners on a given <see cref="IScheduler" /> instance.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="Scheduler" />
|
||||
/// <seealso cref="SchedulerName" />
|
||||
public class SchedulerAccessorObject : SchedulerAccessor, IObjectFactoryAware, IInitializingObject
|
||||
{
|
||||
private string schedulerName;
|
||||
private IScheduler scheduler;
|
||||
private IObjectFactory objectFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Specify the Quartz Scheduler to operate on via its scheduler name in the Spring
|
||||
/// application context or also in the Quartz {@link org.quartz.impl.SchedulerRepository}.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Schedulers can be registered in the repository through custom bootstrapping,
|
||||
/// e.g. via the <see cref="StdSchedulerFactory" /> or
|
||||
/// <see cref="DirectSchedulerFactory" /> factory classes.
|
||||
/// However, in general, it's preferable to use Spring's <see cref="SchedulerFactoryObject" />
|
||||
/// which includes the job/trigger/listener capabilities of this accessor as well.
|
||||
/// </remarks>
|
||||
public string SchedulerName
|
||||
{
|
||||
set { schedulerName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Quartz Scheduler instance that this accessor operates on.
|
||||
/// </summary>
|
||||
protected IScheduler Scheduler
|
||||
{
|
||||
set { scheduler = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Template method that determines the Scheduler to operate on.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override IScheduler GetScheduler()
|
||||
{
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Quartz Scheduler instance that this accessor operates on.
|
||||
/// </summary>
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set { objectFactory = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
if (scheduler == null)
|
||||
{
|
||||
if (schedulerName != null)
|
||||
{
|
||||
scheduler = FindScheduler(schedulerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("No Scheduler specified");
|
||||
}
|
||||
}
|
||||
RegisterListeners();
|
||||
RegisterJobsAndTriggers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the scheduler.
|
||||
/// </summary>
|
||||
/// <param name="schedulerName">Name of the scheduler.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual IScheduler FindScheduler(string schedulerName)
|
||||
{
|
||||
if (objectFactory is IListableObjectFactory)
|
||||
{
|
||||
IListableObjectFactory lbf = (IListableObjectFactory) objectFactory;
|
||||
string[] objectNames = lbf.GetObjectNamesForType(typeof(IScheduler));
|
||||
for (int i = 0; i < objectNames.Length; i++)
|
||||
{
|
||||
IScheduler schedulerObject = (IScheduler)lbf.GetObject(objectNames[i]);
|
||||
if (schedulerName.Equals(schedulerObject.SchedulerName))
|
||||
{
|
||||
return schedulerObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
IScheduler schedulerInRepo = SchedulerRepository.Instance.Lookup(schedulerName);
|
||||
if (schedulerInRepo == null)
|
||||
{
|
||||
throw new InvalidOperationException("No Scheduler named '" + schedulerName + "' found");
|
||||
}
|
||||
return schedulerInRepo;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,871 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
#if QUARTZ_2_0
|
||||
using System.Linq;
|
||||
#endif
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Simpl;
|
||||
using Quartz.Spi;
|
||||
using Quartz.Util;
|
||||
|
||||
using Spring.Context;
|
||||
using Spring.Context.Events;
|
||||
using Spring.Core.IO;
|
||||
using Spring.Data.Common;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// FactoryObject that sets up a Quartz Scheduler and exposes it for object references.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Allows registration of JobDetails, Calendars and Triggers, automatically
|
||||
/// starting the scheduler on initialization and shutting it down on destruction.
|
||||
/// In scenarios that just require static registration of jobs at startup, there
|
||||
/// is no need to access the Scheduler instance itself in application code.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// For dynamic registration of jobs at runtime, use a object reference to
|
||||
/// this SchedulerFactoryObject to get direct access to the Quartz Scheduler
|
||||
/// (<see cref="IScheduler" />). This allows you to create new jobs
|
||||
/// and triggers, and also to control and monitor the entire Scheduler.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Note that Quartz instantiates a new Job for each execution, in
|
||||
/// contrast to Timer which uses a TimerTask instance that is shared
|
||||
/// between repeated executions. Just JobDetail descriptors are shared.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// When using persistent jobs, it is strongly recommended to perform all
|
||||
/// operations on the Scheduler within Spring-managed transactions.
|
||||
/// Else, database locking will not properly work and might even break.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// The preferred way to achieve transactional execution is to demarcate
|
||||
/// declarative transactions at the business facade level, which will
|
||||
/// automatically apply to Scheduler operations performed within those scopes.
|
||||
/// Alternatively, define a TransactionProxyFactoryObject for the Scheduler itself.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
/// <seealso cref="IScheduler" />
|
||||
/// <seealso cref="ISchedulerFactory" />
|
||||
/// <seealso cref="StdSchedulerFactory" />
|
||||
public class SchedulerFactoryObject : SchedulerAccessor, IFactoryObject, IObjectNameAware,
|
||||
IApplicationContextAware, IApplicationEventListener, IInitializingObject, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Default thread count to be set to thread pool.
|
||||
/// </summary>
|
||||
public const int DEFAULT_THREAD_COUNT = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Property name for thread count in thread pool.
|
||||
/// </summary>
|
||||
public const string PROP_THREAD_COUNT = "quartz.threadPool.threadCount";
|
||||
|
||||
[ThreadStatic]
|
||||
private static IDbProvider configTimeDbProvider;
|
||||
|
||||
[ThreadStatic]
|
||||
private static ITaskExecutor configTimeTaskExecutor;
|
||||
|
||||
/// <summary>
|
||||
/// Return the IDbProvider for the currently configured Quartz Scheduler,
|
||||
/// to be used by LocalDataSourceJobStore.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This instance will be set before initialization of the corresponding
|
||||
/// Scheduler, and reset immediately afterwards. It is thus only available
|
||||
/// during configuration.
|
||||
/// </remarks>
|
||||
/// <seealso cref="DbProvider" />
|
||||
/// <seealso cref="LocalDataSourceJobStore" />
|
||||
public static IDbProvider ConfigTimeDbProvider
|
||||
{
|
||||
get { return configTimeDbProvider; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the TaskExecutor for the currently configured Quartz Scheduler,
|
||||
/// to be used by LocalTaskExecutorThreadPool.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This instance will be set before initialization of the corresponding
|
||||
/// Scheduler, and reset immediately afterwards. It is thus only available
|
||||
/// during configuration.
|
||||
/// </remarks>
|
||||
public static ITaskExecutor ConfigTimeTaskExecutor
|
||||
{
|
||||
get { return configTimeTaskExecutor; }
|
||||
}
|
||||
|
||||
private IApplicationContext applicationContext;
|
||||
private string applicationContextSchedulerContextKey;
|
||||
private bool autoStartup = true;
|
||||
private IResource configLocation;
|
||||
private IJobFactory jobFactory;
|
||||
private bool jobFactorySet;
|
||||
private IDictionary quartzProperties;
|
||||
private IScheduler scheduler;
|
||||
private IDictionary schedulerContextMap;
|
||||
private Type schedulerFactoryType;
|
||||
private string schedulerName;
|
||||
private TimeSpan startupDelay = TimeSpan.Zero;
|
||||
private ITaskExecutor taskExecutor;
|
||||
private bool exposeSchedulerInRepository;
|
||||
private bool waitForJobsToCompleteOnShutdown;
|
||||
private IDbProvider dbProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchedulerFactoryObject"/> class.
|
||||
/// </summary>
|
||||
public SchedulerFactoryObject()
|
||||
{
|
||||
schedulerFactoryType = typeof (StdSchedulerFactory);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the Quartz SchedulerFactory implementation to use.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Default is StdSchedulerFactory, reading in the standard
|
||||
/// quartz.properties from Quartz' dll. To use custom Quartz
|
||||
/// properties, specify "configLocation" or "quartzProperties".
|
||||
/// </remarks>
|
||||
/// <value>The scheduler factory class.</value>
|
||||
/// <seealso cref="StdSchedulerFactory"/>
|
||||
/// <seealso cref="ConfigLocation"/>
|
||||
/// <seealso cref="QuartzProperties"/>
|
||||
public virtual Type SchedulerFactoryType
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null || !typeof (ISchedulerFactory).IsAssignableFrom(value))
|
||||
{
|
||||
throw new ArgumentException("schedulerFactoryType must implement [Quartz.ISchedulerFactory]");
|
||||
}
|
||||
schedulerFactoryType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the Scheduler to fetch from the SchedulerFactory.
|
||||
/// If not specified, the default Scheduler will be used.
|
||||
/// </summary>
|
||||
/// <value>The name of the scheduler.</value>
|
||||
/// <seealso cref="ISchedulerFactory.GetScheduler(string)"/>
|
||||
/// <seealso cref="ISchedulerFactory.GetScheduler()"/>
|
||||
public virtual string SchedulerName
|
||||
{
|
||||
set { schedulerName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the location of the Quartz properties config file, for example
|
||||
/// as assembly resource "assembly:quartz.properties".
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: Can be omitted when all necessary properties are specified
|
||||
/// locally via this object, or when relying on Quartz' default configuration.
|
||||
/// </remarks>
|
||||
/// <seealso cref="QuartzProperties" />
|
||||
public virtual IResource ConfigLocation
|
||||
{
|
||||
set { configLocation = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set Quartz properties, like "quartz.threadPool.type".
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can be used to override values in a Quartz properties config file,
|
||||
/// or to specify all necessary properties locally.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ConfigLocation" />
|
||||
public virtual IDictionary QuartzProperties
|
||||
{
|
||||
set { quartzProperties = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the Spring TaskExecutor to use as Quartz backend.
|
||||
/// Exposed as thread pool through the Quartz SPI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, a Quartz SimpleThreadPool will be used, configured through
|
||||
/// the corresponding Quartz properties.
|
||||
/// </remarks>
|
||||
/// <value>The task executor.</value>
|
||||
/// <seealso cref="QuartzProperties"/>
|
||||
/// <seealso cref="LocalTaskExecutorThreadPool"/>
|
||||
public virtual ITaskExecutor TaskExecutor
|
||||
{
|
||||
set { taskExecutor = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register objects in the Scheduler context via a given Map.
|
||||
/// These objects will be available to any Job that runs in this Scheduler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: When using persistent Jobs whose JobDetail will be kept in the
|
||||
/// database, do not put Spring-managed object or an ApplicationContext
|
||||
/// reference into the JobDataMap but rather into the SchedulerContext.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// Map with string keys and any objects as
|
||||
/// values (for example Spring-managed objects)
|
||||
/// </value>
|
||||
/// <seealso cref="JobDetailObject.JobDataAsMap" />
|
||||
public virtual IDictionary SchedulerContextAsMap
|
||||
{
|
||||
set { schedulerContextMap = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the key of an IApplicationContext reference to expose in the
|
||||
/// SchedulerContext, for example "applicationContext". Default is none.
|
||||
/// Only applicable when running in a Spring ApplicationContext.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Note: When using persistent Jobs whose JobDetail will be kept in the
|
||||
/// database, do not put an IApplicationContext reference into the JobDataMap
|
||||
/// but rather into the SchedulerContext.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// In case of a QuartzJobObject, the reference will be applied to the Job
|
||||
/// instance as object property. An "applicationContext" attribute will
|
||||
/// correspond to a "setApplicationContext" method in that scenario.
|
||||
/// </p>
|
||||
///
|
||||
/// <p>
|
||||
/// Note that ObjectFactory callback interfaces like IApplicationContextAware
|
||||
/// are not automatically applied to Quartz Job instances, because Quartz
|
||||
/// itself is reponsible for the lifecycle of its Jobs.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <value>The application context scheduler context key.</value>
|
||||
/// <seealso cref="JobDetailObject.ApplicationContextJobDataKey"/>
|
||||
public virtual string ApplicationContextSchedulerContextKey
|
||||
{
|
||||
set { applicationContextSchedulerContextKey = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the Quartz JobFactory to use for this Scheduler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Default is Spring's <see cref="AdaptableJobFactory" />, which supports
|
||||
/// standard Quartz <see cref="IJob" /> instances. Note that this default only applies
|
||||
/// to a <i>local</i> Scheduler, not to a RemoteScheduler (where setting
|
||||
/// a custom JobFactory is not supported by Quartz).
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Specify an instance of Spring's <see cref="SpringObjectJobFactory" /> here
|
||||
/// (typically as an inner object definition) to automatically populate a job's
|
||||
/// object properties from the specified job data map and scheduler context.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="AdaptableJobFactory" />
|
||||
/// <seealso cref="SpringObjectJobFactory" />
|
||||
public virtual IJobFactory JobFactory
|
||||
{
|
||||
set
|
||||
{
|
||||
jobFactory = value;
|
||||
jobFactorySet = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to expose the Spring-managed <see cref="IScheduler" /> instance in the
|
||||
/// Quartz <see cref="SchedulerRepository" />. Default is "false", since the Spring-managed
|
||||
/// Scheduler is usually exclusively intended for access within the Spring context.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Switch this flag to "true" in order to expose the Scheduler globally.
|
||||
/// This is not recommended unless you have an existing Spring application that
|
||||
/// relies on this behavior.
|
||||
/// </remarks>
|
||||
public virtual bool ExposeSchedulerInRepository
|
||||
{
|
||||
set { exposeSchedulerInRepository = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to automatically start the scheduler after initialization.
|
||||
/// Default is "true"; set this to "false" to allow for manual startup.
|
||||
/// </summary>
|
||||
public virtual bool AutoStartup
|
||||
{
|
||||
set { autoStartup = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the time span to wait after initialization before
|
||||
/// starting the scheduler asynchronously. Default is 0, meaning
|
||||
/// immediate synchronous startup on initialization of this object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting this to 10 or 20 seconds makes sense if no jobs
|
||||
/// should be run before the entire application has started up.
|
||||
/// </remarks>
|
||||
public virtual TimeSpan StartupDelay
|
||||
{
|
||||
set { startupDelay = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to wait for running jobs to complete on Shutdown.
|
||||
/// Default is "false".
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [wait for jobs to complete on Shutdown]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
/// <seealso cref="IScheduler.Shutdown(bool)"/>
|
||||
public virtual bool WaitForJobsToCompleteOnShutdown
|
||||
{
|
||||
set { waitForJobsToCompleteOnShutdown = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default DbProvider to be used by the Scheduler. If set,
|
||||
/// this will override corresponding settings in Quartz properties.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Note: If this is set, the Quartz settings should not define
|
||||
/// a job store "dataSource" to avoid meaningless double configuration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// A Spring-specific subclass of Quartz' JobStoreSupport will be used.
|
||||
/// It is therefore strongly recommended to perform all operations on
|
||||
/// the Scheduler within Spring-managed transactions.
|
||||
/// Else, database locking will not properly work and might even break
|
||||
/// (e.g. if trying to obtain a lock on Oracle without a transaction).
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="QuartzProperties" />
|
||||
/// <seealso cref="LocalDataSourceJobStore" />
|
||||
public IDbProvider DbProvider
|
||||
{
|
||||
set { dbProvider = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
/// </summary>
|
||||
/// <value>The name of the object in the factory.</value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public string ObjectName
|
||||
{
|
||||
set
|
||||
{
|
||||
if (schedulerName == null)
|
||||
{
|
||||
schedulerName = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="SchedulerFactoryObject"/> is running.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if running; otherwise, <c>false</c>.</value>
|
||||
public virtual bool Running
|
||||
{
|
||||
get
|
||||
{
|
||||
if (scheduler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return !scheduler.InStandbyMode;
|
||||
}
|
||||
catch (SchedulerException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#region IApplicationContextAware Members
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="Spring.Context.IApplicationContext"/> that this
|
||||
/// object runs in.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Normally this call will be used to initialize the object.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Invoked after population of normal object properties but before an
|
||||
/// init callback such as
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// or a custom init-method. Invoked after the setting of any
|
||||
/// <see cref="Spring.Context.IResourceLoaderAware"/>'s
|
||||
/// <see cref="Spring.Context.IResourceLoaderAware.ResourceLoader"/>
|
||||
/// property.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Context.ApplicationContextException">
|
||||
/// In the case of application context initialization errors.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// If thrown by any application context methods.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Objects.Factory.ObjectInitializationException"/>
|
||||
public virtual IApplicationContext ApplicationContext
|
||||
{
|
||||
set { applicationContext = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Shut down the Quartz scheduler on object factory Shutdown,
|
||||
/// stopping all scheduled jobs.
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
logger.Info("Shutting down Quartz Scheduler");
|
||||
scheduler.Shutdown(waitForJobsToCompleteOnShutdown);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Template method that determines the Scheduler to operate on.
|
||||
/// To be implemented by subclasses.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override IScheduler GetScheduler()
|
||||
{
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
#region IFactoryObject Members
|
||||
|
||||
/// <summary>
|
||||
/// Return an instance (possibly shared or independent) of the object
|
||||
/// managed by this factory.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An instance (possibly shared or independent) of the object managed by
|
||||
/// this factory.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <note type="caution">
|
||||
/// If this method is being called in the context of an enclosing IoC container and
|
||||
/// returns <see langword="null"/>, the IoC container will consider this factory
|
||||
/// object as not being fully initialized and throw a corresponding (and most
|
||||
/// probably fatal) exception.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
public virtual object GetObject()
|
||||
{
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <see cref="System.Type"/> of object that this
|
||||
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates, or
|
||||
/// <see langword="null"/> if not known in advance.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual Type ObjectType
|
||||
{
|
||||
get { return (scheduler != null) ? scheduler.GetType() : typeof (IScheduler); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the object managed by this factory a singleton or a prototype?
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public virtual bool IsSingleton
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of IInitializingObject interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
// Create SchedulerFactory instance.
|
||||
#if QUARTZ_2_0
|
||||
ISchedulerFactory schedulerFactory = ObjectUtils.InstantiateType<ISchedulerFactory>(schedulerFactoryType);
|
||||
#else
|
||||
ISchedulerFactory schedulerFactory = (ISchedulerFactory) ObjectUtils.InstantiateType(schedulerFactoryType);
|
||||
#endif
|
||||
|
||||
InitSchedulerFactory(schedulerFactory);
|
||||
|
||||
if (taskExecutor != null)
|
||||
{
|
||||
// Make given TaskExecutor available for SchedulerFactory configuration.
|
||||
configTimeTaskExecutor = taskExecutor;
|
||||
}
|
||||
if (dbProvider != null)
|
||||
{
|
||||
// Make given db provider available for SchedulerFactory configuration.
|
||||
configTimeDbProvider = dbProvider;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// Get Scheduler instance from SchedulerFactory.
|
||||
scheduler = CreateScheduler(schedulerFactory, schedulerName);
|
||||
PopulateSchedulerContext();
|
||||
|
||||
if (!jobFactorySet && !(scheduler is RemoteScheduler))
|
||||
{
|
||||
// Use AdaptableJobFactory as default for a local Scheduler, unless when
|
||||
// explicitly given a null value through the "jobFactory" object property.
|
||||
jobFactory = new AdaptableJobFactory();
|
||||
}
|
||||
|
||||
if (jobFactory != null)
|
||||
{
|
||||
if (jobFactory is ISchedulerContextAware)
|
||||
{
|
||||
((ISchedulerContextAware) jobFactory).SchedulerContext = scheduler.Context;
|
||||
}
|
||||
scheduler.JobFactory = jobFactory;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (taskExecutor != null)
|
||||
{
|
||||
configTimeTaskExecutor = null;
|
||||
}
|
||||
if (dbProvider != null)
|
||||
{
|
||||
configTimeDbProvider = null;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterListeners();
|
||||
RegisterJobsAndTriggers();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Load and/or apply Quartz properties to the given SchedulerFactory.
|
||||
/// </summary>
|
||||
/// <param name="schedulerFactory">the SchedulerFactory to Initialize</param>
|
||||
private void InitSchedulerFactory(ISchedulerFactory schedulerFactory)
|
||||
{
|
||||
if (!(schedulerFactory is StdSchedulerFactory))
|
||||
{
|
||||
if (configLocation != null || quartzProperties != null || schedulerName != null ||
|
||||
taskExecutor != null || dbProvider != null)
|
||||
{
|
||||
|
||||
throw new ArgumentException("StdSchedulerFactory required for applying Quartz properties: " + schedulerFactory);
|
||||
}
|
||||
// Otherwise assume that no initialization is necessary...
|
||||
return;
|
||||
}
|
||||
NameValueCollection mergedProps = new NameValueCollection();
|
||||
|
||||
// Set necessary default properties here, as Quartz will not apply
|
||||
// its default configuration when explicitly given properties.
|
||||
if (taskExecutor != null)
|
||||
{
|
||||
mergedProps[StdSchedulerFactory.PropertyThreadPoolType] =
|
||||
typeof (LocalTaskExecutorThreadPool).AssemblyQualifiedName;
|
||||
}
|
||||
else
|
||||
{
|
||||
mergedProps.Set(StdSchedulerFactory.PropertyThreadPoolType, typeof(SimpleThreadPool).AssemblyQualifiedName);
|
||||
mergedProps[PROP_THREAD_COUNT] = Convert.ToString(DEFAULT_THREAD_COUNT);
|
||||
}
|
||||
|
||||
if (configLocation != null)
|
||||
{
|
||||
if (logger.IsInfoEnabled)
|
||||
{
|
||||
logger.Info("Loading Quartz config from [" + configLocation + "]");
|
||||
}
|
||||
using (StreamReader sr = new StreamReader(configLocation.InputStream))
|
||||
{
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
string[] lineItems = line.Split(new char[] { '=' }, 2);
|
||||
if (lineItems.Length == 2)
|
||||
{
|
||||
mergedProps[lineItems[0].Trim()] = lineItems[1].Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (quartzProperties != null)
|
||||
{
|
||||
// if given quartz properties, merge to them to configuration
|
||||
MergePropertiesIntoMap(quartzProperties, mergedProps);
|
||||
}
|
||||
|
||||
if (dbProvider != null)
|
||||
{
|
||||
mergedProps.Add(StdSchedulerFactory.PropertyJobStoreType, typeof(LocalDataSourceJobStore).AssemblyQualifiedName);
|
||||
}
|
||||
|
||||
|
||||
// Make sure to set the scheduler name as configured in the Spring configuration.
|
||||
if (schedulerName != null)
|
||||
{
|
||||
mergedProps.Add(StdSchedulerFactory.PropertySchedulerInstanceName, schedulerName);
|
||||
}
|
||||
|
||||
((StdSchedulerFactory) schedulerFactory).Initialize(mergedProps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges the properties into map. This effectively also
|
||||
/// overwrites existing properties with same key in map.
|
||||
/// </summary>
|
||||
/// <param name="properties">The properties to merge into given map.</param>
|
||||
/// <param name="map">The map to merge to.</param>
|
||||
protected virtual void MergePropertiesIntoMap(IDictionary properties, NameValueCollection map)
|
||||
{
|
||||
foreach (string key in properties.Keys)
|
||||
{
|
||||
map[key] = (string) properties[key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create the Scheduler instance for the given factory and scheduler name.
|
||||
/// Called by afterPropertiesSet.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Default implementation invokes SchedulerFactory's <code>GetScheduler</code>
|
||||
/// method. Can be overridden for custom Scheduler creation.
|
||||
/// </remarks>
|
||||
/// <param name="schedulerFactory">the factory to create the Scheduler with</param>
|
||||
/// <param name="schedName">the name of the scheduler to create</param>
|
||||
/// <returns>the Scheduler instance</returns>
|
||||
/// <seealso cref="AfterPropertiesSet"/>
|
||||
/// <seealso cref="ISchedulerFactory.GetScheduler()"/>
|
||||
protected virtual IScheduler CreateScheduler(ISchedulerFactory schedulerFactory, string schedName)
|
||||
{
|
||||
SchedulerRepository repository = SchedulerRepository.Instance;
|
||||
lock (repository)
|
||||
{
|
||||
IScheduler existingScheduler = (schedulerName != null ? repository.Lookup(schedulerName) : null);
|
||||
IScheduler newScheduler = schedulerFactory.GetScheduler();
|
||||
if (newScheduler == existingScheduler) {
|
||||
throw new InvalidOperationException(
|
||||
string.Format(
|
||||
"Active Scheduler of name '{0}' already registered in Quartz SchedulerRepository. Cannot create a new Spring-managed Scheduler of the same name!",
|
||||
schedulerName));
|
||||
}
|
||||
if (!exposeSchedulerInRepository) {
|
||||
// Need to explicitly remove it if not intended for exposure,
|
||||
// since Quartz shares the Scheduler instance by default!
|
||||
SchedulerRepository.Instance.Remove(newScheduler.SchedulerName);
|
||||
}
|
||||
return newScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expose the specified context attributes and/or the current
|
||||
/// IApplicationContext in the Quartz SchedulerContext.
|
||||
/// </summary>
|
||||
private void PopulateSchedulerContext()
|
||||
{
|
||||
// Put specified objects into Scheduler context.
|
||||
if (schedulerContextMap != null)
|
||||
{
|
||||
#if QUARTZ_2_0
|
||||
var dictionary = schedulerContextMap.Cast<DictionaryEntry>().ToDictionary(entry => entry.Key.ToString(), entry => entry.Value);
|
||||
scheduler.Context.PutAll(dictionary);
|
||||
#else
|
||||
scheduler.Context.PutAll(schedulerContextMap);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Register IApplicationContext in Scheduler context.
|
||||
if (applicationContextSchedulerContextKey != null)
|
||||
{
|
||||
if (applicationContext == null)
|
||||
{
|
||||
throw new SystemException("SchedulerFactoryObject needs to be set up in an IApplicationContext " +
|
||||
"to be able to handle an 'applicationContextSchedulerContextKey'");
|
||||
}
|
||||
scheduler.Context.Put(applicationContextSchedulerContextKey, applicationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Start the Quartz Scheduler, respecting the "startDelay" setting.
|
||||
/// </summary>
|
||||
/// <param name="sched">the Scheduler to start</param>
|
||||
/// <param name="startDelay">the time span to wait before starting
|
||||
/// the Scheduler asynchronously</param>
|
||||
protected virtual void StartScheduler(IScheduler sched, TimeSpan startDelay)
|
||||
{
|
||||
if (startDelay.TotalSeconds <= 0)
|
||||
{
|
||||
logger.Info("Starting Quartz Scheduler now");
|
||||
sched.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.IsInfoEnabled)
|
||||
{
|
||||
logger.Info(
|
||||
string.Format("Will start Quartz Scheduler [{0}] in {1} seconds", sched.SchedulerName,
|
||||
startDelay));
|
||||
}
|
||||
sched.StartDelayed(startDelay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of Lifecycle interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Starts this instance.
|
||||
/// </summary>
|
||||
public virtual void Start()
|
||||
{
|
||||
if (scheduler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
scheduler.Start();
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
throw new SchedulingException("Could not start Quartz Scheduler", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops this instance.
|
||||
/// </summary>
|
||||
public virtual void Stop()
|
||||
{
|
||||
if (scheduler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
scheduler.Standby();
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
throw new SchedulingException("Could not stop Quartz Scheduler", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the application context's refresh event and starts the scheduler.
|
||||
/// </summary>
|
||||
public void HandleApplicationEvent(object sender, ApplicationEventArgs e)
|
||||
{
|
||||
// auto-start Scheduler if demanded
|
||||
if (e is ContextRefreshedEventArgs && autoStartup)
|
||||
{
|
||||
try
|
||||
{
|
||||
StartScheduler(scheduler, startupDelay);
|
||||
}
|
||||
catch (SchedulerException ex)
|
||||
{
|
||||
throw new ObjectInitializationException("failed to auto-start scheduler", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic scheduling exception.
|
||||
/// </summary>
|
||||
public class SchedulingException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchedulingException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public SchedulingException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchedulingException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="ex">The original exception.</param>
|
||||
public SchedulingException(string message, Exception ex) : base(message, ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Simpl;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclass of Quartz's SimpleThreadPool that implements Spring's
|
||||
/// TaskExecutor interface and listens to Spring lifecycle callbacks.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SimpleThreadPool" />
|
||||
/// <seealso cref="ITaskExecutor" />
|
||||
/// <seealso cref="SchedulerFactoryObject.TaskExecutor" />
|
||||
public class SimpleThreadPoolTaskExecutor : SimpleThreadPool, ISchedulingTaskExecutor, IInitializingObject, IDisposable
|
||||
{
|
||||
private bool waitForJobsToCompleteOnShutdown = false;
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to wait for running jobs to complete on Shutdown.
|
||||
/// Default is "false".
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [wait for jobs to complete on shutdown]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
/// <seealso cref="SimpleThreadPool.Shutdown(bool)"/>
|
||||
public virtual bool WaitForJobsToCompleteOnShutdown
|
||||
{
|
||||
set { waitForJobsToCompleteOnShutdown = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This method allows the object instance to perform the kind of
|
||||
/// initialization only possible when all of it's dependencies have
|
||||
/// been injected (set), and to throw an appropriate exception in the
|
||||
/// event of misconfiguration.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Please do consult the class level documentation for the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> interface for a
|
||||
/// description of exactly <i>when</i> this method is invoked. In
|
||||
/// particular, it is worth noting that the
|
||||
/// <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
|
||||
/// and <see cref="Spring.Context.IApplicationContextAware"/>
|
||||
/// callbacks will have been invoked <i>prior</i> to this method being
|
||||
/// called.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specified task.
|
||||
/// </summary>
|
||||
/// <param name="task">The task.</param>
|
||||
public virtual void Execute(ThreadStart task)
|
||||
{
|
||||
if (task == null)
|
||||
{
|
||||
throw new ArgumentException("Runnable must not be null", "task");
|
||||
}
|
||||
if (!RunInThread(new ThreadRunnableDelegate(task)))
|
||||
{
|
||||
throw new SchedulingException("Quartz SimpleThreadPool already shut down");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> This task executor prefers short-lived work units.</summary>
|
||||
public virtual bool PrefersShortLivedTasks
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Shutdown(waitForJobsToCompleteOnShutdown);
|
||||
}
|
||||
|
||||
internal class ThreadRunnableDelegate : IThreadRunnable
|
||||
{
|
||||
private ThreadStart ts;
|
||||
|
||||
|
||||
public ThreadRunnableDelegate(ThreadStart ts)
|
||||
{
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
ts.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
|
||||
using Quartz.Impl.AdoJobStore;
|
||||
using Quartz.Impl.AdoJobStore.Common;
|
||||
|
||||
using IDbMetadata=Spring.Data.Common.IDbMetadata;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapts Spring's <see cref="Data.Common.IDbProvider"/> to Quartz's
|
||||
/// <see cref="IDbProvider"/>.
|
||||
/// </summary>
|
||||
public class SpringDbProviderAdapter : IDbProvider
|
||||
{
|
||||
private readonly Data.Common.IDbProvider dbProvider;
|
||||
private readonly DbMetadata metadata;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SpringDbProviderAdapter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dbProvider">The Spring db provider.</param>
|
||||
public SpringDbProviderAdapter(Data.Common.IDbProvider dbProvider)
|
||||
{
|
||||
this.dbProvider = dbProvider;
|
||||
metadata = new SpringMetadataAdapter(dbProvider.DbMetadata);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the command.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDbCommand CreateCommand()
|
||||
{
|
||||
return dbProvider.CreateCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the command builder.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public object CreateCommandBuilder()
|
||||
{
|
||||
return dbProvider.CreateCommandBuilder();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the connection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDbConnection CreateConnection()
|
||||
{
|
||||
return dbProvider.CreateConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the parameter.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDbDataParameter CreateParameter()
|
||||
{
|
||||
return dbProvider.CreateParameter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shutdowns this instance.
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection string.
|
||||
/// </summary>
|
||||
/// <value>The connection string.</value>
|
||||
public string ConnectionString
|
||||
{
|
||||
get { return dbProvider.ConnectionString; }
|
||||
set { dbProvider.ConnectionString = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the metadata.
|
||||
/// </summary>
|
||||
/// <value>The metadata.</value>
|
||||
public DbMetadata Metadata
|
||||
{
|
||||
get { return metadata; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to map between Quartz and Spring DB metadata.
|
||||
/// </summary>
|
||||
public class SpringMetadataAdapter : DbMetadata
|
||||
{
|
||||
private readonly IDbMetadata metadata;
|
||||
private readonly Enum dbTypeBinary;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SpringMetadataAdapter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="metadata">The metadata to wrap and adapt.</param>
|
||||
public SpringMetadataAdapter(IDbMetadata metadata)
|
||||
{
|
||||
this.metadata = metadata;
|
||||
// determine correct binary enum type
|
||||
Type parameterType = metadata.ParameterDbType;
|
||||
FieldInfo blobField = parameterType.GetField("Blob");
|
||||
FieldInfo imageField = parameterType.GetField("Image");
|
||||
if (blobField != null)
|
||||
{
|
||||
// uses Blob, for example Oracle
|
||||
dbTypeBinary = (Enum) blobField.GetValue(Activator.CreateInstance(parameterType));
|
||||
}
|
||||
else if (imageField != null)
|
||||
{
|
||||
// uses Image, SQL Server
|
||||
dbTypeBinary = (Enum) imageField.GetValue(Activator.CreateInstance(parameterType));
|
||||
}
|
||||
else
|
||||
{
|
||||
// use standard binary type
|
||||
dbTypeBinary = DbType.Binary;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the product.
|
||||
/// </summary>
|
||||
/// <value>The name of the product.</value>
|
||||
public override string ProductName
|
||||
{
|
||||
get { return metadata.ProductName; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the connection.
|
||||
/// </summary>
|
||||
/// <value>The type of the connection.</value>
|
||||
public override Type ConnectionType
|
||||
{
|
||||
get { return metadata.ConnectionType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the command.
|
||||
/// </summary>
|
||||
/// <value>The type of the command.</value>
|
||||
public override Type CommandType
|
||||
{
|
||||
get { return metadata.CommandType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the parameter.
|
||||
/// </summary>
|
||||
/// <value>The type of the parameter.</value>
|
||||
public override Type ParameterType
|
||||
{
|
||||
get { return metadata.ParameterType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the command builder.
|
||||
/// </summary>
|
||||
/// <value>The type of the command builder.</value>
|
||||
public override Type CommandBuilderType
|
||||
{
|
||||
get { return metadata.CommandBuilderType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the command builder derive parameters method.
|
||||
/// </summary>
|
||||
/// <value>The command builder derive parameters method.</value>
|
||||
public override MethodInfo CommandBuilderDeriveParametersMethod
|
||||
{
|
||||
get { return metadata.CommandBuilderDeriveParametersMethod; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter name prefix.
|
||||
/// </summary>
|
||||
/// <value>The parameter name prefix.</value>
|
||||
public override string ParameterNamePrefix
|
||||
{
|
||||
get { return metadata.ParameterNamePrefix; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the exception.
|
||||
/// </summary>
|
||||
/// <value>The type of the exception.</value>
|
||||
public override Type ExceptionType
|
||||
{
|
||||
get { return metadata.ExceptionType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [bind by name].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [bind by name]; otherwise, <c>false</c>.</value>
|
||||
public override bool BindByName
|
||||
{
|
||||
get { return metadata.BindByName; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the parameter db.
|
||||
/// </summary>
|
||||
/// <value>The type of the parameter db.</value>
|
||||
public override Type ParameterDbType
|
||||
{
|
||||
get { return metadata.ParameterDbType; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter db type property.
|
||||
/// </summary>
|
||||
/// <value>The parameter db type property.</value>
|
||||
public override PropertyInfo ParameterDbTypeProperty
|
||||
{
|
||||
get { return metadata.ParameterDbTypeProperty; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter is nullable property.
|
||||
/// </summary>
|
||||
/// <value>The parameter is nullable property.</value>
|
||||
public override PropertyInfo ParameterIsNullableProperty
|
||||
{
|
||||
get { return metadata.ParameterIsNullableProperty; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the db binary.
|
||||
/// </summary>
|
||||
/// <value>The type of the db binary.</value>
|
||||
public override Enum DbBinaryType
|
||||
{
|
||||
get { return dbTypeBinary; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [use parameter name prefix in parameter collection].
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [use parameter name prefix in parameter collection]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public override bool UseParameterNamePrefixInParameterCollection
|
||||
{
|
||||
get { return metadata.UseParameterNamePrefixInParameterCollection; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using Spring.Objects;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclass of AdaptableJobFactory that also supports Spring-style
|
||||
/// dependency injection on object properties. This is essentially the direct
|
||||
/// equivalent of Spring's QuartzJobObject in the shape of a
|
||||
/// Quartz JobFactory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Applies scheduler context, job data map and trigger data map entries
|
||||
/// as object property values. If no matching object property is found, the entry
|
||||
/// is by default simply ignored. This is analogous to QuartzJobObject's behavior.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <seealso cref="SchedulerFactoryObject.JobFactory" />
|
||||
/// <seealso cref="QuartzJobObject" />
|
||||
public class SpringObjectJobFactory : AdaptableJobFactory, ISchedulerContextAware
|
||||
{
|
||||
private string[] ignoredUnknownProperties;
|
||||
private SchedulerContext schedulerContext;
|
||||
|
||||
/// <summary>
|
||||
/// Specify the unknown properties (not found in the object) that should be ignored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Default is <code>null</code>, indicating that all unknown properties
|
||||
/// should be ignored. Specify an empty array to throw an exception in case
|
||||
/// of any unknown properties, or a list of property names that should be
|
||||
/// ignored if there is no corresponding property found on the particular
|
||||
/// job class (all other unknown properties will still trigger an exception).
|
||||
/// </remarks>
|
||||
public virtual string[] IgnoredUnknownProperties
|
||||
{
|
||||
set { ignoredUnknownProperties = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the SchedulerContext of the current Quartz Scheduler.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <seealso cref="IScheduler.Context"/>
|
||||
public virtual SchedulerContext SchedulerContext
|
||||
{
|
||||
set { schedulerContext = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create the job instance, populating it with property values taken
|
||||
/// from the scheduler context, job data map and trigger data map.
|
||||
/// </summary>
|
||||
protected override object CreateJobInstance(TriggerFiredBundle bundle)
|
||||
{
|
||||
ObjectWrapper ow = new ObjectWrapper(bundle.JobDetail.JobType);
|
||||
if (IsEligibleForPropertyPopulation(ow.WrappedInstance))
|
||||
{
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
if (schedulerContext != null)
|
||||
{
|
||||
pvs.AddAll(schedulerContext);
|
||||
}
|
||||
pvs.AddAll(bundle.JobDetail.JobDataMap);
|
||||
pvs.AddAll(bundle.Trigger.JobDataMap);
|
||||
if (ignoredUnknownProperties != null)
|
||||
{
|
||||
for (int i = 0; i < ignoredUnknownProperties.Length; i++)
|
||||
{
|
||||
string propName = ignoredUnknownProperties[i];
|
||||
if (pvs.Contains(propName))
|
||||
{
|
||||
pvs.Remove(propName);
|
||||
}
|
||||
}
|
||||
ow.SetPropertyValues(pvs);
|
||||
}
|
||||
else
|
||||
{
|
||||
ow.SetPropertyValues(pvs, true);
|
||||
}
|
||||
}
|
||||
return ow.WrappedInstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the given job object is eligible for having
|
||||
/// its object properties populated.
|
||||
/// <p>
|
||||
/// The default implementation ignores QuartzJobObject instances,
|
||||
/// which will inject object properties themselves.
|
||||
/// </p>
|
||||
/// </summary>
|
||||
/// <param name="jobObject">
|
||||
/// The job object to introspect.
|
||||
/// </param>
|
||||
/// <seealso cref="QuartzJobObject" />
|
||||
protected virtual bool IsEligibleForPropertyPopulation(object jobObject)
|
||||
{
|
||||
return (!(jobObject is QuartzJobObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Spring.Scheduling
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TaskRejectedException.
|
||||
/// </summary>
|
||||
public class TaskRejectedException : ApplicationException
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -51,69 +51,31 @@
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\JobMethodInvocationFailedException.cs">
|
||||
<Link>JobMethodInvocationFailedException.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\AdaptableJobFactory.cs">
|
||||
<Link>Scheduling\Quartz\AdaptableJobFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\DelegatingJob.cs">
|
||||
<Link>Scheduling\Quartz\DelegatingJob.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\IJobDetailAwareTrigger.cs">
|
||||
<Link>Scheduling\Quartz\IJobDetailAwareTrigger.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\ISchedulerContextAware.cs">
|
||||
<Link>Scheduling\Quartz\ISchedulerContextAware.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\ISchedulingTaskExecutor.cs">
|
||||
<Link>Scheduling\Quartz\ISchedulingTaskExecutor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\ITaskExecutor.cs">
|
||||
<Link>Scheduling\Quartz\ITaskExecutor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\LocalDataSourceJobStore.cs">
|
||||
<Link>Scheduling\Quartz\LocalDataSourceJobStore.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\LocalTaskExecutorThreadPool.cs">
|
||||
<Link>Scheduling\Quartz\LocalTaskExecutorThreadPool.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\MethodInvokingJob.cs">
|
||||
<Link>Scheduling\Quartz\MethodInvokingJob.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\MethodInvokingRunnable.cs">
|
||||
<Link>Scheduling\Quartz\MethodInvokingRunnable.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\QuartzJobObject.cs">
|
||||
<Link>Scheduling\Quartz\QuartzJobObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\SchedulerAccessorObject.cs">
|
||||
<Link>Scheduling\Quartz\SchedulerAccessorObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\SchedulerFactoryObject.cs">
|
||||
<Link>Scheduling\Quartz\SchedulerFactoryObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\SchedulingException.cs">
|
||||
<Link>Scheduling\Quartz\SchedulingException.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\SimpleThreadPoolTaskExecutor.cs">
|
||||
<Link>Scheduling\Quartz\SimpleThreadPoolTaskExecutor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\SpringDbProviderAdapter.cs">
|
||||
<Link>Scheduling\Quartz\SpringDbProviderAdapter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\SpringObjectJobFactory.cs">
|
||||
<Link>Scheduling\Quartz\SpringObjectJobFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz\Scheduling\Quartz\TaskRejectedException.cs">
|
||||
<Link>Scheduling\Quartz\TaskRejectedException.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="JobMethodInvocationFailedException.cs" />
|
||||
<Compile Include="Scheduling\Quartz\AdaptableJobFactory.cs" />
|
||||
<Compile Include="Scheduling\Quartz\CronTriggerObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\DelegatingJob.cs" />
|
||||
<Compile Include="Scheduling\Quartz\IJobDetailAwareTrigger.cs" />
|
||||
<Compile Include="Scheduling\Quartz\ISchedulerContextAware.cs" />
|
||||
<Compile Include="Scheduling\Quartz\ISchedulingTaskExecutor.cs" />
|
||||
<Compile Include="Scheduling\Quartz\ITaskExecutor.cs" />
|
||||
<Compile Include="Scheduling\Quartz\JobDetailObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\LocalDataSourceJobStore.cs" />
|
||||
<Compile Include="Scheduling\Quartz\LocalTaskExecutorThreadPool.cs" />
|
||||
<Compile Include="Scheduling\Quartz\MethodInvokingJob.cs" />
|
||||
<Compile Include="Scheduling\Quartz\MethodInvokingJobDetailFactoryObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\MethodInvokingRunnable.cs" />
|
||||
<Compile Include="Scheduling\Quartz\QuartzJobObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SchedulerAccessor.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SchedulerAccessorObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SchedulerFactoryObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SchedulingException.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SimpleThreadPoolTaskExecutor.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SimpleTriggerObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SpringDbProviderAdapter.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SpringObjectJobFactory.cs" />
|
||||
<Compile Include="Scheduling\Quartz\StatefulMethodInvokingJob.cs" />
|
||||
<Compile Include="Scheduling\Quartz\TaskRejectedException.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.2010.csproj">
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2004-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using Spring.Scheduling.Quartz;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring
|
||||
{
|
||||
/// <summary>Test that the assembly is built with the correct DebugAttributes in release and debug builds.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
[TestFixture]
|
||||
public sealed class QuartzCompilerOptionTests : CompilerOptionsTests
|
||||
{
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureSetUp()
|
||||
{
|
||||
AssemblyToCheck = Assembly.GetAssembly(typeof (SchedulingException));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
using Quartz.Spi;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="AdaptableJobFactory" />.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class AdaptableJobFactoryTest
|
||||
{
|
||||
private AdaptableJobFactory jobFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
jobFactory = new AdaptableJobFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job creation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestNewJob_IncompatibleJob()
|
||||
{
|
||||
try
|
||||
{
|
||||
// this actually fails already in Quartz level
|
||||
TriggerFiredBundle bundle = TestUtil.CreateMinimalFiredBundleWithTypedJobDetail(typeof (object));
|
||||
#if QUARTZ_2_0
|
||||
jobFactory.NewJob(bundle, null);
|
||||
#else
|
||||
jobFactory.NewJob(bundle);
|
||||
#endif
|
||||
Assert.Fail("Created job which was not an IJob");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// ok
|
||||
}
|
||||
catch (SchedulerException)
|
||||
{
|
||||
// ok
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Assert.Fail("Got exception that was not instance of SchedulerException or ArgumentException");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job creation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestNewJob_ThreadStartJob()
|
||||
{
|
||||
// TODO ThreadStart is not the way to go
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job creation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestNewJob_NormalIJob()
|
||||
{
|
||||
TriggerFiredBundle bundle = TestUtil.CreateMinimalFiredBundleWithTypedJobDetail(typeof (NoOpJob));
|
||||
#if QUARTZ_2_0
|
||||
IJob job = jobFactory.NewJob(bundle, null);
|
||||
#else
|
||||
IJob job = jobFactory.NewJob(bundle);
|
||||
#endif
|
||||
|
||||
Assert.IsNotNull(job, "Returned job was null");
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoOpThreadStartJob : NoOpJob
|
||||
{
|
||||
public void Execute()
|
||||
{
|
||||
Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobDetail = Quartz.Impl.JobDetailImpl;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="CronTriggerObject" />.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class CronTriggerObjectTest : TriggerObjectTest
|
||||
{
|
||||
private CronTriggerObject cronTrigger;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
cronTrigger = new CronTriggerObject();
|
||||
cronTrigger.ObjectName = TRIGGER_NAME;
|
||||
Trigger = cronTrigger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests all possible misfire instructions for cron trigger
|
||||
/// from strings to int.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMisfireInstructionNames()
|
||||
{
|
||||
string[] names = new string[] { "DoNothing", "FireOnceNow", "SmartPolicy" };
|
||||
foreach (string name in names)
|
||||
{
|
||||
cronTrigger.MisfireInstructionName = name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that JobDetail defaults values as expected in AfterPropertiesSet.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public override void TestAfterPropertiesSet_JobDetailGiven()
|
||||
{
|
||||
const string jobName = "jobName";
|
||||
const string jobGroup = "jobGroup";
|
||||
JobDetail jd = new JobDetail(jobName, jobGroup, typeof (NoOpJob));
|
||||
cronTrigger.JobDetail = jd;
|
||||
cronTrigger.AfterPropertiesSet();
|
||||
base.TestAfterPropertiesSet_JobDetailGiven();
|
||||
Assert.AreSame(jd, cronTrigger.JobDetail, "job details weren't same");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that JobDetail maps job data map as expected.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestJobDataAsMap()
|
||||
{
|
||||
#if QUARTZ_2_0
|
||||
IDictionary data = new Dictionary<string, object>();
|
||||
#else
|
||||
Hashtable data = new Hashtable();
|
||||
#endif
|
||||
data["foo"] = "bar";
|
||||
data["number"] = 123;
|
||||
cronTrigger.JobDataAsMap = data;
|
||||
CollectionAssert.AreEquivalent(data, cronTrigger.JobDataMap, "Data differed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that StartDelay is respected.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestStartDelay()
|
||||
{
|
||||
TimeSpan expectedDelay = TimeSpan.FromMinutes(10);
|
||||
cronTrigger.StartDelay = expectedDelay;
|
||||
Assert.AreEqual(expectedDelay, cronTrigger.StartDelay);
|
||||
|
||||
cronTrigger.AfterPropertiesSet();
|
||||
DateTime now = DateTime.UtcNow;
|
||||
TimeSpan delay = cronTrigger.StartTimeUtc - now;
|
||||
|
||||
// check roughly
|
||||
Assert.IsTrue(delay > TimeSpan.FromMinutes(9).Add(TimeSpan.FromSeconds(55)));
|
||||
Assert.IsTrue(delay < TimeSpan.FromMinutes(10).Add(TimeSpan.FromSeconds(5)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
|
||||
using Spring.Context.Support;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="JobDetailObject" />.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class JobDetailObjectTest
|
||||
{
|
||||
private JobDetailObject jobDetail;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
jobDetail = new JobDetailObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void TestJobType_Null()
|
||||
{
|
||||
jobDetail.JobType = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestJobType_NonIJob()
|
||||
{
|
||||
jobDetail.JobType = typeof(object);
|
||||
Assert.AreEqual(typeof(object), jobDetail.JobType, "JobDetail did not create same type as expected");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestJobType_IJob()
|
||||
{
|
||||
Type CORRECT_IJOB = typeof (NoOpJob);
|
||||
jobDetail.JobType = CORRECT_IJOB;
|
||||
Assert.AreEqual(jobDetail.JobType, CORRECT_IJOB, "JobDetail did not register correct job type");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void TestJobDataAsMap_Null()
|
||||
{
|
||||
jobDetail.JobDataAsMap = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestJobDataAsMap_ProperValues()
|
||||
{
|
||||
IDictionary values = new Hashtable();
|
||||
values["baz"] = "foo";
|
||||
values["foo"] = 123;
|
||||
values["bar"] = null;
|
||||
jobDetail.JobDataAsMap = values;
|
||||
Assert.AreEqual(values.Count, jobDetail.JobDataMap.Count, "Data of inequal size");
|
||||
CollectionAssert.AreEquivalent(values.Keys, jobDetail.JobDataMap.Keys, "JobDataMap values not equal");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_Defaults()
|
||||
{
|
||||
const string objectName = "springJobDetailObject";
|
||||
jobDetail.ObjectName = objectName;
|
||||
jobDetail.Group = null;
|
||||
jobDetail.AfterPropertiesSet();
|
||||
Assert.AreEqual(SchedulerConstants.DefaultGroup, jobDetail.Group, "Groups differ");
|
||||
Assert.AreEqual(objectName, jobDetail.Name, "Names differ");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_CustomNameAndGroup()
|
||||
{
|
||||
const string objectName = "springJobDetailObject";
|
||||
const string jobDetailName = "jobDetailName";
|
||||
const string jobDetailGroup = "jobDetailGroup";
|
||||
jobDetail.ObjectName = objectName;
|
||||
jobDetail.Name = jobDetailName;
|
||||
jobDetail.Group = jobDetailGroup;
|
||||
jobDetail.AfterPropertiesSet();
|
||||
Assert.AreEqual(jobDetailGroup, jobDetail.Group, "Groups differ");
|
||||
Assert.AreEqual(jobDetailName, jobDetail.Name, "Names differ");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_ApplicationContextJobDataKeySetWithApplicationContext()
|
||||
{
|
||||
const string objectName = "springJobDetailObject";
|
||||
jobDetail.ObjectName = objectName;
|
||||
StaticApplicationContext ctx = new StaticApplicationContext();
|
||||
jobDetail.ApplicationContext = ctx;
|
||||
string key = "applicationContextJobDataKey";
|
||||
jobDetail.ApplicationContextJobDataKey = key;
|
||||
jobDetail.AfterPropertiesSet();
|
||||
Assert.AreSame(ctx, jobDetail.ApplicationContext, "ApplicationContext was not set correctly");
|
||||
Assert.AreSame(ctx, jobDetail.JobDataMap[key], "ApplicationContext was not set to job data map");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job detail's property behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void TestAfterPropertiesSet_ApplicationContextJobDataKeySetWithoutApplicationContext()
|
||||
{
|
||||
const string objectName = "springJobDetailObject";
|
||||
jobDetail.ObjectName = objectName;
|
||||
jobDetail.ApplicationContextJobDataKey = "applicationContextJobDataKey";
|
||||
jobDetail.AfterPropertiesSet();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobDetail = Quartz.Impl.JobDetailImpl;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for MethodInvokingJobDetailFactoryObject.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class MethodInvokingJobDetailFactoryObjectTest
|
||||
{
|
||||
private const string FACTORY_NAME = "springObjectFactory";
|
||||
private MethodInvokingJobDetailFactoryObject factory;
|
||||
|
||||
/// <summary>
|
||||
/// Setup for the test.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
factory = new MethodInvokingJobDetailFactoryObject();
|
||||
factory.ObjectName = FACTORY_NAME;
|
||||
factory.TargetMethod = "Invoke";
|
||||
factory.TargetObject = new InvocationCountingJob();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests JobDetail retrieval and it's set properties.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetObject_MinimalDefaults()
|
||||
{
|
||||
factory.AfterPropertiesSet();
|
||||
JobDetail jd = (JobDetail) factory.GetObject();
|
||||
Assert.IsNotNull(jd, "job detail was null");
|
||||
Assert.AreEqual(FACTORY_NAME, jd.Name, "job name did not default to factory name");
|
||||
Assert.AreEqual(jd.JobType, typeof(MethodInvokingJob), "factory did not create method invoking job");
|
||||
Assert.IsTrue(jd.Durable, "job was not durable");
|
||||
#if !QUARTZ_2_0
|
||||
Assert.IsTrue(jd.Volatile, "job was not volatile");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests JobDetail retrieval and it's set properties.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetObject_ConcurrentJob()
|
||||
{
|
||||
factory.Concurrent = false;
|
||||
factory.AfterPropertiesSet();
|
||||
JobDetail jd = (JobDetail)factory.GetObject();
|
||||
Assert.IsNotNull(jd, "job detail was null");
|
||||
Assert.AreEqual(jd.JobType, typeof(StatefulMethodInvokingJob), "factory did not create stateful method invoking job");
|
||||
}
|
||||
|
||||
#if !QUARTZ_2_0
|
||||
/// <summary>
|
||||
/// Tests JobDetail retrieval and it's set properties.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetObject_TriggerListenersSet()
|
||||
{
|
||||
string[] LISTENER_NAMES = new string[] {"Foo", "Bar"};
|
||||
factory.JobListenerNames = LISTENER_NAMES;
|
||||
factory.AfterPropertiesSet();
|
||||
JobDetail jd = (JobDetail)factory.GetObject();
|
||||
CollectionAssert.AreEquivalent(LISTENER_NAMES, jd.JobListenerNames);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
using Quartz.Spi;
|
||||
|
||||
using Rhino.Mocks;
|
||||
|
||||
using Spring.Objects.Support;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobExecutionContext = Quartz.Impl.JobExecutionContextImpl;
|
||||
using JobDetail = Quartz.Impl.JobDetailImpl;
|
||||
using SimpleTrigger = Quartz.Impl.Triggers.SimpleTriggerImpl;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for MethodInvokingJob.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class MethodInvokingJobTest
|
||||
{
|
||||
private MethodInvokingJob methodInvokingJob;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
methodInvokingJob = new MethodInvokingJob();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method invoke via execute.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void TestMethodInvoker_SetWithNull()
|
||||
{
|
||||
methodInvokingJob.MethodInvoker = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method invoke via execute.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[ExpectedException(typeof(JobExecutionException))]
|
||||
public void TestMethodInvocation_NullMethodInvokder()
|
||||
{
|
||||
methodInvokingJob.Execute(CreateMinimalJobExecutionContext());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method invoke via execute.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMethodInvoker_MethodSetCorrectly()
|
||||
{
|
||||
InvocationCountingJob job = new InvocationCountingJob();
|
||||
MethodInvoker mi = new MethodInvoker();
|
||||
mi.TargetObject = job;
|
||||
mi.TargetMethod = "Invoke";
|
||||
mi.Prepare();
|
||||
methodInvokingJob.MethodInvoker = mi;
|
||||
methodInvokingJob.Execute(CreateMinimalJobExecutionContext());
|
||||
Assert.AreEqual(1, job.CounterValue, "Job was not invoked once");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that invocation result is set to execution context (SPRNET-1340).
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMethodInvoker_ShouldSetResultToExecutionContext()
|
||||
{
|
||||
InvocationCountingJob job = new InvocationCountingJob();
|
||||
MethodInvoker mi = new MethodInvoker();
|
||||
mi.TargetObject = job;
|
||||
mi.TargetMethod = "InvokeWithReturnValue";
|
||||
mi.Prepare();
|
||||
methodInvokingJob.MethodInvoker = mi;
|
||||
JobExecutionContext context = CreateMinimalJobExecutionContext();
|
||||
methodInvokingJob.Execute(context);
|
||||
|
||||
Assert.AreEqual(InvocationCountingJob.DefaultReturnValue, context.Result, "result value was not set to context");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method invoke via execute.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMethodInvoker_MethodSetCorrectlyThrowsException()
|
||||
{
|
||||
InvocationCountingJob job = new InvocationCountingJob();
|
||||
MethodInvoker mi = new MethodInvoker();
|
||||
mi.TargetObject = job;
|
||||
mi.TargetMethod = "InvokeAndThrowException";
|
||||
mi.Prepare();
|
||||
methodInvokingJob.MethodInvoker = mi;
|
||||
try
|
||||
{
|
||||
methodInvokingJob.Execute(CreateMinimalJobExecutionContext());
|
||||
Assert.Fail("Successful invoke when method threw exception");
|
||||
}
|
||||
catch (JobMethodInvocationFailedException)
|
||||
{
|
||||
// ok
|
||||
}
|
||||
Assert.AreEqual(1, job.CounterValue, "Job was not invoked once");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test method invoke via execute.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMethodInvoker_PrivateMethod()
|
||||
{
|
||||
InvocationCountingJob job = new InvocationCountingJob();
|
||||
MethodInvoker mi = new MethodInvoker();
|
||||
mi.TargetObject = job;
|
||||
mi.TargetMethod = "PrivateMethod";
|
||||
mi.Prepare();
|
||||
methodInvokingJob.MethodInvoker = mi;
|
||||
methodInvokingJob.Execute(CreateMinimalJobExecutionContext());
|
||||
}
|
||||
|
||||
private static JobExecutionContext CreateMinimalJobExecutionContext()
|
||||
{
|
||||
MockRepository repo = new MockRepository();
|
||||
IScheduler sched = (IScheduler) repo.DynamicMock(typeof (IScheduler));
|
||||
JobExecutionContext ctx = new JobExecutionContext(sched, ConstructMinimalTriggerFiredBundle(), null);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
private static TriggerFiredBundle ConstructMinimalTriggerFiredBundle()
|
||||
{
|
||||
JobDetail jd = new JobDetail("jobName", "jobGroup", typeof(NoOpJob));
|
||||
SimpleTrigger trigger = new SimpleTrigger("triggerName", "triggerGroup");
|
||||
TriggerFiredBundle retValue = new TriggerFiredBundle(jd, trigger, null, false, null, null, null, null);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test class for method invoker.
|
||||
/// </summary>
|
||||
public class InvocationCountingJob
|
||||
{
|
||||
private int counter;
|
||||
internal const string DefaultReturnValue = "return value";
|
||||
|
||||
/// <summary>
|
||||
/// Increments method invoke counter.
|
||||
/// </summary>
|
||||
public void Invoke()
|
||||
{
|
||||
Interlocked.Increment(ref counter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws exception after incrementing counter.
|
||||
/// </summary>
|
||||
public void InvokeAndThrowException()
|
||||
{
|
||||
Interlocked.Increment(ref counter);
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private void PrivateMethod()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see cref="DefaultReturnValue" /> as return value.
|
||||
/// </summary>
|
||||
public string InvokeWithReturnValue()
|
||||
{
|
||||
return DefaultReturnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invocation count.
|
||||
/// </summary>
|
||||
public int CounterValue
|
||||
{
|
||||
get { return counter; }
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple test object for Quartz.NET to run
|
||||
/// that simulates imports and exports.
|
||||
/// </summary>
|
||||
/// <author>Rob Harrop</author>
|
||||
public class QuartzTestObject
|
||||
{
|
||||
private int exportCount;
|
||||
private int importCount;
|
||||
|
||||
/// <summary>
|
||||
/// Executes a fake import and increments counter.
|
||||
/// </summary>
|
||||
public void DoImport()
|
||||
{
|
||||
++importCount;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// Executes a fake export and increments counter.
|
||||
///</summary>
|
||||
public void DoExport()
|
||||
{
|
||||
++exportCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells how many times import has been done.
|
||||
/// </summary>
|
||||
public int ImportCount
|
||||
{
|
||||
get { return importCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells how many times export has been done.
|
||||
/// </summary>
|
||||
public int ExportCount
|
||||
{
|
||||
get { return exportCount; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Spi;
|
||||
using Rhino.Mocks;
|
||||
|
||||
using Spring.Core.IO;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using Trigger = Quartz.ITrigger;
|
||||
using JobExecutionContext = Quartz.IJobExecutionContext;
|
||||
using JobDetail = Quartz.IJobDetail;
|
||||
using SimpleTrigger = Quartz.Impl.Triggers.SimpleTriggerImpl;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for SchedulerFactoryObject.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class SchedulerFactoryObjectTest
|
||||
{
|
||||
private static readonly MethodInfo m_InitSchedulerFactory = typeof(SchedulerFactoryObject).GetMethod("InitSchedulerFactory",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
private SchedulerFactoryObject factory;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
factory = new SchedulerFactoryObject();
|
||||
|
||||
TestSchedulerFactory.Initialize();
|
||||
TestSchedulerFactory.MockScheduler.Stub(x => x.SchedulerName).Return("scheduler").Repeat.Any();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_Defaults()
|
||||
{
|
||||
factory.AfterPropertiesSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_NullJobFactory()
|
||||
{
|
||||
factory.JobFactory = null;
|
||||
factory.AfterPropertiesSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_NoAutoStartup()
|
||||
{
|
||||
// set expectations
|
||||
TestSchedulerFactory.MockScheduler.JobFactory = null;
|
||||
|
||||
factory.SchedulerFactoryType = typeof(TestSchedulerFactory);
|
||||
factory.AutoStartup = false;
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.JobFactory = null);
|
||||
}
|
||||
|
||||
#if !QUARTZ_2_0
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_AddListeners()
|
||||
{
|
||||
InitForAfterPropertiesSetTest();
|
||||
|
||||
factory.SchedulerListeners = new ISchedulerListener[] { MockRepository.GenerateMock<ISchedulerListener>() };
|
||||
|
||||
factory.GlobalJobListeners = new IJobListener[] { MockRepository.GenerateMock<IJobListener>() };
|
||||
|
||||
factory.JobListeners = new IJobListener[] { MockRepository.GenerateMock<IJobListener>() };
|
||||
|
||||
factory.GlobalTriggerListeners = new ITriggerListener[] { MockRepository.GenerateMock<ITriggerListener>() };
|
||||
|
||||
factory.TriggerListeners = new ITriggerListener[] { MockRepository.GenerateMock<ITriggerListener>() };
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.AddSchedulerListener(Arg<ISchedulerListener>.Is.NotNull));
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.AddGlobalJobListener(Arg<IJobListener>.Is.NotNull));
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.AddJobListener(Arg<IJobListener>.Is.NotNull));
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.AddGlobalTriggerListener(Arg<ITriggerListener>.Is.NotNull));
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.AddTriggerListener(Arg<ITriggerListener>.Is.NotNull));
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_Calendars()
|
||||
{
|
||||
InitForAfterPropertiesSetTest();
|
||||
|
||||
const string calendarName = "calendar";
|
||||
ICalendar cal = MockRepository.GenerateMock<ICalendar>();
|
||||
Hashtable calTable = new Hashtable();
|
||||
calTable[calendarName] = cal;
|
||||
factory.Calendars = calTable;
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.AddCalendar(calendarName, cal, true, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_Trigger_TriggerExists()
|
||||
{
|
||||
InitForAfterPropertiesSetTest();
|
||||
|
||||
const string TRIGGER_NAME = "trigName";
|
||||
const string TRIGGER_GROUP = "trigGroup";
|
||||
SimpleTrigger trigger = new SimpleTrigger(TRIGGER_NAME, TRIGGER_GROUP);
|
||||
factory.Triggers = new Trigger[] { trigger };
|
||||
|
||||
#if QUARTZ_2_0
|
||||
TestSchedulerFactory.MockScheduler.Stub(x => x.GetTrigger(new TriggerKey(TRIGGER_NAME, TRIGGER_GROUP))).Return(trigger);
|
||||
#else
|
||||
TestSchedulerFactory.MockScheduler.Stub(x => x.GetTrigger(TRIGGER_NAME, TRIGGER_GROUP)).Return(trigger);
|
||||
#endif
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_Trigger_TriggerDoesntExist()
|
||||
{
|
||||
InitForAfterPropertiesSetTest();
|
||||
|
||||
const string TRIGGER_NAME = "trigName";
|
||||
const string TRIGGER_GROUP = "trigGroup";
|
||||
SimpleTrigger trigger = new SimpleTrigger(TRIGGER_NAME, TRIGGER_GROUP);
|
||||
factory.Triggers = new Trigger[] { trigger };
|
||||
|
||||
factory.AfterPropertiesSet();
|
||||
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.ScheduleJob(trigger));
|
||||
}
|
||||
|
||||
|
||||
private void InitForAfterPropertiesSetTest()
|
||||
{
|
||||
factory.AutoStartup = false;
|
||||
// set expectations
|
||||
factory.SchedulerFactoryType = typeof(TestSchedulerFactory);
|
||||
TestSchedulerFactory.MockScheduler.JobFactory = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestStart()
|
||||
{
|
||||
factory.SchedulerFactoryType = typeof(TestSchedulerFactory);
|
||||
factory.AutoStartup = false;
|
||||
factory.AfterPropertiesSet();
|
||||
factory.Start();
|
||||
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.JobFactory = Arg<IJobFactory>.Is.NotNull);
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.Start());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestStop()
|
||||
{
|
||||
factory.SchedulerFactoryType = typeof(TestSchedulerFactory);
|
||||
factory.AutoStartup = false;
|
||||
factory.AfterPropertiesSet();
|
||||
factory.Stop();
|
||||
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.JobFactory = Arg<IJobFactory>.Is.NotNull);
|
||||
TestSchedulerFactory.MockScheduler.AssertWasCalled(x => x.Standby());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetObject()
|
||||
{
|
||||
factory.AfterPropertiesSet();
|
||||
IScheduler sched = (IScheduler)factory.GetObject();
|
||||
Assert.IsNotNull(sched, "scheduler was null");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void TestSchedulerFactoryType_InvalidType()
|
||||
{
|
||||
factory.SchedulerFactoryType = typeof(SchedulerFactoryObjectTest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSchedulerFactoryType_ValidType()
|
||||
{
|
||||
factory.SchedulerFactoryType = typeof(StdSchedulerFactory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInitSchedulerFactory_MinimalDefaults()
|
||||
{
|
||||
factory.SchedulerName = "testFactoryObject";
|
||||
StdSchedulerFactory factoryToPass = new StdSchedulerFactory();
|
||||
m_InitSchedulerFactory.Invoke(factory, new object[] { factoryToPass });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInitSchedulerFactory_ConfigLocationReadingShouldPreserverExtraEqualsMarksAndTrimKeysAndValues()
|
||||
{
|
||||
const string ConnectionStringValue = "Server=(local);Database=quartz;Trusted_Connection=True;";
|
||||
const string ConnectionStringKey = "quartz.dataSource.default.connectionString";
|
||||
string configuration =
|
||||
@"quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz
|
||||
quartz.jobStore.useProperties = false
|
||||
quartz.jobStore.dataSource = default" + Environment.NewLine +
|
||||
ConnectionStringKey+ " = " + ConnectionStringValue + Environment.NewLine +
|
||||
"quartz.dataSource.default.provider = SqlServer-20";
|
||||
|
||||
// initialize data
|
||||
MemoryStream ms = new MemoryStream();
|
||||
byte[] data = Encoding.UTF8.GetBytes(configuration);
|
||||
ms.Write(data, 0, data.Length);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
ms.Position = 0;
|
||||
|
||||
// intercept call
|
||||
InterceptingStdSChedulerFactory factoryToPass = new InterceptingStdSChedulerFactory();
|
||||
|
||||
factory.ConfigLocation = new TestConfigLocation(ms, "description");
|
||||
|
||||
m_InitSchedulerFactory.Invoke(factory, new object[] { factoryToPass });
|
||||
|
||||
Assert.AreEqual(ConnectionStringValue, factoryToPass.Properties[ConnectionStringKey]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestConfigLocation : InputStreamResource
|
||||
{
|
||||
public TestConfigLocation(Stream inputStream, string description) : base(inputStream, description)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ISchedulerFactory implementation for testing purposes.
|
||||
/// </summary>
|
||||
public class TestSchedulerFactory : ISchedulerFactory
|
||||
{
|
||||
private static IScheduler mockScheduler;
|
||||
|
||||
/// <summary>
|
||||
/// The mocked scheduler.
|
||||
/// </summary>
|
||||
public static IScheduler MockScheduler
|
||||
{
|
||||
get { return mockScheduler; }
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///</summary>
|
||||
///<returns></returns>
|
||||
public IScheduler GetScheduler()
|
||||
{
|
||||
return mockScheduler;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///</summary>
|
||||
///<param name="schedName"></param>
|
||||
///<returns></returns>
|
||||
public IScheduler GetScheduler(string schedName)
|
||||
{
|
||||
return mockScheduler;
|
||||
}
|
||||
|
||||
#if QUARTZ_2_0
|
||||
///<summary>
|
||||
///</summary>
|
||||
public ICollection<IScheduler> AllSchedulers
|
||||
{
|
||||
get { return new List<IScheduler>(); }
|
||||
}
|
||||
#else
|
||||
///<summary>
|
||||
///</summary>
|
||||
public ICollection AllSchedulers
|
||||
{
|
||||
get { return new ArrayList(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
mockScheduler = MockRepository.GenerateMock<IScheduler>();
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// Scheduler factory that supports property interception.
|
||||
///</summary>
|
||||
public class InterceptingStdSChedulerFactory : StdSchedulerFactory
|
||||
{
|
||||
private NameValueCollection properties;
|
||||
|
||||
///<summary>
|
||||
/// Initializes the factory.
|
||||
///</summary>
|
||||
///<param name="props"></param>
|
||||
public override void Initialize(NameValueCollection props)
|
||||
{
|
||||
this.properties = props;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return propeties given to this factory at initialization time.
|
||||
/// </summary>
|
||||
public NameValueCollection Properties
|
||||
{
|
||||
get { return properties; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobDetail = Quartz.Impl.JobDetailImpl;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="SimpleTriggerObject" />.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class SimpleTriggerObjectTest : TriggerObjectTest
|
||||
{
|
||||
private SimpleTriggerObject simpleTrigger;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
simpleTrigger = new SimpleTriggerObject();
|
||||
simpleTrigger.ObjectName = TRIGGER_NAME;
|
||||
Trigger = simpleTrigger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests all possible misfire instructions for cron trigger
|
||||
/// from strings to int.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMisfireInstructionNames()
|
||||
{
|
||||
string[] names = new string[] { "FireNow", "RescheduleNextWithExistingCount", "RescheduleNextWithRemainingCount", "RescheduleNowWithExistingRepeatCount", "RescheduleNowWithRemainingRepeatCount", "SmartPolicy" };
|
||||
foreach (string name in names)
|
||||
{
|
||||
simpleTrigger.MisfireInstructionName = name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public override void TestAfterPropertiesSet_Defaults()
|
||||
{
|
||||
simpleTrigger.AfterPropertiesSet();
|
||||
base.TestAfterPropertiesSet_Defaults();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public override void TestAfterPropertiesSet_ValuesGiven()
|
||||
{
|
||||
simpleTrigger.StartDelay = TimeSpan.FromMilliseconds(100);
|
||||
simpleTrigger.AfterPropertiesSet();
|
||||
base.TestAfterPropertiesSet_ValuesGiven();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAfterPropertiesSet_StartDelayGiven()
|
||||
{
|
||||
const int START_DELAY = 100000;
|
||||
simpleTrigger.StartDelay = TimeSpan.FromMilliseconds(START_DELAY);
|
||||
DateTime startTime = DateTime.UtcNow;
|
||||
simpleTrigger.AfterPropertiesSet();
|
||||
AssertDateTimesEqualityWithAllowedDelta(startTime.AddMilliseconds(START_DELAY), simpleTrigger.StartTimeUtc, 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public override void TestAfterPropertiesSet_JobDetailGiven()
|
||||
{
|
||||
const string jobName = "jobName";
|
||||
const string jobGroup = "jobGroup";
|
||||
JobDetail jd = new JobDetail(jobName, jobGroup, typeof(NoOpJob));
|
||||
simpleTrigger.JobDetail = jd;
|
||||
simpleTrigger.AfterPropertiesSet();
|
||||
base.TestAfterPropertiesSet_JobDetailGiven();
|
||||
Assert.AreSame(jd, simpleTrigger.JobDetail, "job details weren't same");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests AfterPropertiesSet behavior.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestJobDataAsMap()
|
||||
{
|
||||
#if QUARTZ_2_0
|
||||
IDictionary data = new Dictionary<string, object>();
|
||||
#else
|
||||
Hashtable data = new Hashtable();
|
||||
#endif
|
||||
data["foo"] = "bar";
|
||||
data["number"] = 123;
|
||||
simpleTrigger.JobDataAsMap = data;
|
||||
CollectionAssert.AreEquivalent(data, simpleTrigger.JobDataMap, "Data differed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Job;
|
||||
using Quartz.Spi;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using Trigger = Quartz.Spi.IOperableTrigger;
|
||||
using JobExecutionContext = Quartz.IJobExecutionContext;
|
||||
using JobDetail = Quartz.IJobDetail;
|
||||
using SimpleTrigger = Quartz.Impl.Triggers.SimpleTriggerImpl;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for SpringObjectJobFactory.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
[TestFixture]
|
||||
public class SpringObjectJobFactoryTest
|
||||
{
|
||||
private SpringObjectJobFactory factory;
|
||||
|
||||
/// <summary>
|
||||
/// Test setup.
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
factory = new SpringObjectJobFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job instane creation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCreateJobInstance_SimpleDefaults()
|
||||
{
|
||||
Trigger trigger = new SimpleTrigger();
|
||||
TriggerFiredBundle bundle = TestUtil.CreateMinimalFiredBundleWithTypedJobDetail(typeof (NoOpJob), trigger);
|
||||
|
||||
#if QUARTZ_2_0
|
||||
IJob job = factory.NewJob(bundle, null);
|
||||
#else
|
||||
IJob job = factory.NewJob(bundle);
|
||||
#endif
|
||||
Assert.IsNotNull(job, "Created job was null");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job instane creation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCreateJobInstance_SchedulerContextGiven()
|
||||
{
|
||||
Trigger trigger = new SimpleTrigger();
|
||||
TriggerFiredBundle bundle = TestUtil.CreateMinimalFiredBundleWithTypedJobDetail(typeof(InjectableJob), trigger);
|
||||
|
||||
#if QUARTZ_2_0
|
||||
IDictionary<string, object> items = new Dictionary<string, object>();
|
||||
items["foo"] = "bar";
|
||||
items["number"] = 123;
|
||||
factory.SchedulerContext = new SchedulerContext(items);
|
||||
InjectableJob job = (InjectableJob)factory.NewJob(bundle, null);
|
||||
#else
|
||||
IDictionary items = new Hashtable();
|
||||
items["foo"] = "bar";
|
||||
items["number"] = 123;
|
||||
factory.SchedulerContext = new SchedulerContext(items);
|
||||
InjectableJob job = (InjectableJob) factory.NewJob(bundle);
|
||||
#endif
|
||||
|
||||
Assert.IsNotNull(job, "Created job was null");
|
||||
Assert.AreEqual("bar", job.Foo, "string injection failed");
|
||||
Assert.AreEqual(123, job.Number, "integer injection failed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests job instane creation.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCreateJobInstance_IgnoredProperties()
|
||||
{
|
||||
factory.IgnoredUnknownProperties = new string[] {"foo", "baz"};
|
||||
Trigger trigger = new SimpleTrigger();
|
||||
trigger.JobDataMap["foo"] = "should not be injected";
|
||||
trigger.JobDataMap["number"] = 123;
|
||||
TriggerFiredBundle bundle = TestUtil.CreateMinimalFiredBundleWithTypedJobDetail(typeof(InjectableJob), trigger);
|
||||
|
||||
#if QUARTZ_2_0
|
||||
InjectableJob job = (InjectableJob)factory.NewJob(bundle, null);
|
||||
#else
|
||||
InjectableJob job = (InjectableJob)factory.NewJob(bundle);
|
||||
#endif
|
||||
Assert.IsNotNull(job, "Created job was null");
|
||||
Assert.AreEqual(123, job.Number, "integer injection failed");
|
||||
Assert.IsNull(job.Foo, "foo was injected when it was not supposed to ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test job object that has injectable properties
|
||||
/// </summary>
|
||||
public class InjectableJob : NoOpJob
|
||||
{
|
||||
private int number;
|
||||
private string foo;
|
||||
|
||||
/// <summary>
|
||||
/// Simple int property.
|
||||
/// </summary>
|
||||
public int Number
|
||||
{
|
||||
get { return number; }
|
||||
set { number = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple string property.
|
||||
/// </summary>
|
||||
public string Foo
|
||||
{
|
||||
get { return foo; }
|
||||
set { foo = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Simple test task.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
public class TestMethodInvokingTask
|
||||
{
|
||||
/// <summary>
|
||||
/// Counter for DoSomething and DoWait calls.
|
||||
/// </summary>
|
||||
public int counter;
|
||||
private readonly object lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Simple test method.
|
||||
/// </summary>
|
||||
public void DoSomething()
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits until stop is called.
|
||||
/// </summary>
|
||||
public void DoWait()
|
||||
{
|
||||
counter++;
|
||||
// wait until stop is called
|
||||
lock (lockObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
Monitor.Wait(lockObject);
|
||||
}
|
||||
catch (ThreadInterruptedException)
|
||||
{
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Informs test object that stop should be called.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
lock (lockObject)
|
||||
{
|
||||
Monitor.Pulse(lockObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using JobDetail = Quartz.Impl.JobDetailImpl;
|
||||
using Trigger = Quartz.Spi.IOperableTrigger;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Quartz.NET integration testing helpers.
|
||||
/// </summary>
|
||||
/// <author>Marko Lahma (.NET)</author>
|
||||
public class TestUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the minimal fired bundle with job detail that has
|
||||
/// given job type.
|
||||
/// </summary>
|
||||
/// <param name="jobType">Type of the job.</param>
|
||||
/// <returns>Minimal TriggerFiredBundle</returns>
|
||||
public static TriggerFiredBundle CreateMinimalFiredBundleWithTypedJobDetail(Type jobType)
|
||||
{
|
||||
return CreateMinimalFiredBundleWithTypedJobDetail(jobType, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the minimal fired bundle with job detail that has
|
||||
/// given job type.
|
||||
/// </summary>
|
||||
/// <param name="jobType">Type of the job.</param>
|
||||
/// <param name="trigger">The trigger.</param>
|
||||
/// <returns>Minimal TriggerFiredBundle</returns>
|
||||
public static TriggerFiredBundle CreateMinimalFiredBundleWithTypedJobDetail(Type jobType, Trigger trigger)
|
||||
{
|
||||
JobDetail jd = new JobDetail("jobName", "jobGroup", jobType);
|
||||
TriggerFiredBundle bundle = new TriggerFiredBundle(jd, trigger, null, false, null, null, null, null);
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Quartz;
|
||||
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
#if QUARTZ_2_0
|
||||
using Trigger = Quartz.Spi.IOperableTrigger;
|
||||
#endif
|
||||
|
||||
namespace Spring.Scheduling.Quartz
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for testing triggers. Contains common functionality.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public abstract class TriggerObjectTest
|
||||
{
|
||||
private Trigger trigger;
|
||||
|
||||
/// <summary>
|
||||
/// Constant name for tested triggers.
|
||||
/// </summary>
|
||||
protected const string TRIGGER_NAME = "trigger";
|
||||
|
||||
/// <summary>
|
||||
/// TriggerObject under test.
|
||||
/// </summary>
|
||||
protected Trigger Trigger
|
||||
{
|
||||
set { trigger = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that TriggerObject defaults values as expected in AfterPropertiesSet.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public virtual void TestAfterPropertiesSet_Defaults()
|
||||
{
|
||||
((IInitializingObject) trigger).AfterPropertiesSet();
|
||||
|
||||
#if QUARTZ_2_0
|
||||
Assert.AreEqual(TRIGGER_NAME, trigger.Key.Name, "trigger name mismatch");
|
||||
Assert.AreEqual(SchedulerConstants.DefaultGroup, trigger.Key.Group, "trigger group name mismatch");
|
||||
Assert.IsNull(trigger.JobKey, "trigger job name not null");
|
||||
#else
|
||||
Assert.AreEqual(TRIGGER_NAME, trigger.Name, "trigger name mismatch");
|
||||
Assert.AreEqual(SchedulerConstants.DefaultGroup, trigger.Group, "trigger group name mismatch");
|
||||
Assert.IsNull(trigger.JobName, "trigger job name not null");
|
||||
Assert.AreEqual(SchedulerConstants.DefaultGroup, trigger.JobGroup, "trigger job group was not default");
|
||||
#endif
|
||||
AssertDateTimesEqualityWithAllowedDelta(DateTime.UtcNow, trigger.StartTimeUtc, 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that TriggerObject defaults values as expected in AfterPropertiesSet.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public virtual void TestAfterPropertiesSet_ValuesGiven()
|
||||
{
|
||||
((IInitializingObject)trigger).AfterPropertiesSet();
|
||||
|
||||
const string NAME = "newName";
|
||||
const string GROUP = "newGroup";
|
||||
DateTime START_TIME = new DateTime(1982, 6, 28, 13, 10, 0);
|
||||
trigger.StartTimeUtc = START_TIME;
|
||||
#if QUARTZ_2_0
|
||||
trigger.Key = new TriggerKey(NAME, GROUP);
|
||||
Assert.AreEqual(NAME, trigger.Key.Name, "trigger name mismatch");
|
||||
Assert.AreEqual(GROUP, trigger.Key.Group, "trigger group name mismatch");
|
||||
#else
|
||||
trigger.Name = NAME;
|
||||
trigger.Group = GROUP;
|
||||
Assert.AreEqual(NAME, trigger.Name, "trigger name mismatch");
|
||||
Assert.AreEqual(GROUP, trigger.Group, "trigger group name mismatch");
|
||||
#endif
|
||||
AssertDateTimesEqualityWithAllowedDelta(START_TIME, trigger.StartTimeUtc, 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that TriggerObject defaults values as expected in AfterPropertiesSet.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public virtual void TestAfterPropertiesSet_JobDetailGiven()
|
||||
{
|
||||
((IInitializingObject)trigger).AfterPropertiesSet();
|
||||
|
||||
const string jobName = "jobName";
|
||||
const string jobGroup = "jobGroup";
|
||||
#if QUARTZ_2_0
|
||||
Assert.AreEqual(jobName, trigger.JobKey.Name, "trigger job name was not from job detail");
|
||||
Assert.AreEqual(jobGroup, trigger.JobKey.Group, "trigger job group was not from job detail");
|
||||
#else
|
||||
Assert.AreEqual(jobName, trigger.JobName, "trigger job name was not from job detail");
|
||||
Assert.AreEqual(jobGroup, trigger.JobGroup, "trigger job group was not from job detail");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QUARTZ_2_0
|
||||
/// <summary>
|
||||
/// Tests whether two datetimes are close enough.
|
||||
/// </summary>
|
||||
/// <param name="d1"></param>
|
||||
/// <param name="d2"></param>
|
||||
/// <param name="allowedDeltaInMilliseconds"></param>
|
||||
protected static void AssertDateTimesEqualityWithAllowedDelta(DateTimeOffset d1, DateTimeOffset d2, int allowedDeltaInMilliseconds)
|
||||
{
|
||||
int diffInMillis = (int) Math.Abs((d1 - d2).TotalMilliseconds);
|
||||
Assert.LessOrEqual(diffInMillis, allowedDeltaInMilliseconds, "too much difference in times");
|
||||
}
|
||||
#else
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether two datetimes are close enough.
|
||||
/// </summary>
|
||||
/// <param name="d1"></param>
|
||||
/// <param name="d2"></param>
|
||||
/// <param name="allowedDeltaInMilliseconds"></param>
|
||||
protected static void AssertDateTimesEqualityWithAllowedDelta(DateTime d1, DateTime d2, int allowedDeltaInMilliseconds)
|
||||
{
|
||||
int diffInMillis = (int)Math.Abs((d1 - d2).TotalMilliseconds);
|
||||
Assert.LessOrEqual(diffInMillis, allowedDeltaInMilliseconds, "too much difference in times");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests that TriggerObject defaults values as expected in AfterPropertiesSet.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public virtual void TestTriggerListenerNames_Valid()
|
||||
{
|
||||
((IInitializingObject)trigger).AfterPropertiesSet();
|
||||
|
||||
string[] LISTENER_NAMES = new string[] { "Foo", "Bar", "Baz" };
|
||||
trigger.TriggerListenerNames = LISTENER_NAMES;
|
||||
CollectionAssert.AreEqual(LISTENER_NAMES, trigger.TriggerListenerNames, "Trigger listeners were not equal");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,50 +71,6 @@
|
||||
<Name>Spring.Core.Tests.2010</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\QuartzCompilerOptionsTests.cs">
|
||||
<Link>QuartzCompilerOptionsTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\AdaptableJobFactoryTest.cs">
|
||||
<Link>Scheduling\Quartz\AdaptableJobFactoryTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\CronTriggerObjectTest.cs">
|
||||
<Link>Scheduling\Quartz\CronTriggerObjectTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\JobDetailObjectTest.cs">
|
||||
<Link>Scheduling\Quartz\JobDetailObjectTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\MethodInvokingJobDetailFactoryObjectTest.cs">
|
||||
<Link>Scheduling\Quartz\MethodInvokingJobDetailFactoryObjectTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\MethodInvokingJobTest.cs">
|
||||
<Link>Scheduling\Quartz\MethodInvokingJobTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\QuartzSupportTests.cs">
|
||||
<Link>Scheduling\Quartz\QuartzSupportTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\QuartzTestObject.cs">
|
||||
<Link>Scheduling\Quartz\QuartzTestObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\SchedulerFactoryObjectTest.cs">
|
||||
<Link>Scheduling\Quartz\SchedulerFactoryObjectTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\SimpleTriggerObjectTest.cs">
|
||||
<Link>Scheduling\Quartz\SimpleTriggerObjectTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\SpringObjectJobFactoryTest.cs">
|
||||
<Link>Scheduling\Quartz\SpringObjectJobFactoryTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\TestMethodInvokingTask.cs">
|
||||
<Link>Scheduling\Quartz\TestMethodInvokingTask.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\TestUtil.cs">
|
||||
<Link>Scheduling\Quartz\TestUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Scheduling.Quartz.Tests\Scheduling\Quartz\TriggerObjectTest.cs">
|
||||
<Link>Scheduling\Quartz\TriggerObjectTest.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="job-scheduling-data.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
@@ -137,6 +93,23 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="QuartzCompilerOptionsTests.cs" />
|
||||
<Compile Include="Scheduling\Quartz\AdaptableJobFactoryTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\CronTriggerObjectTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\JobDetailObjectTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\MethodInvokingJobDetailFactoryObjectTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\MethodInvokingJobTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\QuartzSupportTests.cs" />
|
||||
<Compile Include="Scheduling\Quartz\QuartzTestObject.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SchedulerFactoryObjectTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SimpleTriggerObjectTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\SpringObjectJobFactoryTest.cs" />
|
||||
<Compile Include="Scheduling\Quartz\TestMethodInvokingTask.cs" />
|
||||
<Compile Include="Scheduling\Quartz\TestUtil.cs" />
|
||||
<Compile Include="Scheduling\Quartz\TriggerObjectTest.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
Reference in New Issue
Block a user