KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > cron > QuartzJobScheduler


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.cron;
17
18 import java.text.ParseException JavaDoc;
19 import java.util.Arrays JavaDoc;
20 import java.util.Date JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.NoSuchElementException JavaDoc;
23
24 import org.apache.avalon.framework.CascadingException;
25 import org.apache.avalon.framework.activity.Disposable;
26 import org.apache.avalon.framework.activity.Initializable;
27 import org.apache.avalon.framework.activity.Startable;
28 import org.apache.avalon.framework.component.Component;
29 import org.apache.avalon.framework.configuration.Configurable;
30 import org.apache.avalon.framework.configuration.Configuration;
31 import org.apache.avalon.framework.configuration.ConfigurationException;
32 import org.apache.avalon.framework.context.Context;
33 import org.apache.avalon.framework.context.ContextException;
34 import org.apache.avalon.framework.context.Contextualizable;
35 import org.apache.avalon.framework.logger.AbstractLogEnabled;
36 import org.apache.avalon.framework.parameters.Parameters;
37 import org.apache.avalon.framework.service.ServiceException;
38 import org.apache.avalon.framework.service.ServiceManager;
39 import org.apache.avalon.framework.service.Serviceable;
40 import org.apache.avalon.framework.thread.ThreadSafe;
41 import org.apache.cocoon.components.thread.RunnableManager;
42 import org.apache.cocoon.components.thread.ThreadPool;
43 import org.quartz.CronTrigger;
44 import org.quartz.Job;
45 import org.quartz.JobDataMap;
46 import org.quartz.JobDetail;
47 import org.quartz.Scheduler;
48 import org.quartz.SchedulerException;
49 import org.quartz.SimpleTrigger;
50 import org.quartz.Trigger;
51 import org.quartz.JobExecutionContext;
52 import org.quartz.JobExecutionException;
53 import org.quartz.impl.DirectSchedulerFactory;
54 import org.quartz.impl.jdbcjobstore.InvalidConfigurationException;
55 import org.quartz.impl.jdbcjobstore.JobStoreSupport;
56 import org.quartz.simpl.RAMJobStore;
57 import org.quartz.spi.JobStore;
58 import org.quartz.spi.TriggerFiredBundle;
59 import org.quartz.utils.ConnectionProvider;
60 import org.quartz.utils.DBConnectionManager;
61 import org.quartz.utils.JNDIConnectionProvider;
62
63 /**
64  * This component can either schedule jobs or directly execute one.
65  *
66  * @author <a HREF="mailto:giacomo@apache.org">Giacomo Pati</a>
67  * @version CVS $Id: QuartzJobScheduler.java 125647 2005-01-19 19:59:36Z rgoers $
68  *
69  * @since 2.1.1
70  */

71 public class QuartzJobScheduler extends AbstractLogEnabled
72                                 implements JobScheduler, Component, ThreadSafe,
73                                            Serviceable, Configurable, Startable,
74                                            Disposable, Contextualizable, Initializable {
75
76     /** QuartzThreadPool policy RUN */
77     private static final String JavaDoc POLICY_RUN = "RUN";
78
79     /** QuartzThreadPool policy WAIT */
80     private static final String JavaDoc POLICY_WAIT = "WAIT";
81
82     /** QuartzThreadPool policy ABORT */
83     private static final String JavaDoc POLICY_ABORT = "ABORT";
84
85     /** QuartzThreadPool policy DISCARD */
86     private static final String JavaDoc POLICY_DISCARD = "DISCARD";
87
88     /** QuartzThreadPool policy DISCARD-OLDEST */
89     private static final String JavaDoc POLICY_DISCARD_OLDEST = "DISCARDOLDEST";
90
91
92     /** Map key for the component role */
93     static final String JavaDoc DATA_MAP_ROLE = "QuartzJobScheduler.ROLE";
94
95     /** Map key for the job object */
96     static final String JavaDoc DATA_MAP_OBJECT = "QuartzJobScheduler.Object";
97
98     /** Map key for the job name */
99     static final String JavaDoc DATA_MAP_NAME = "QuartzJobScheduler.JobName";
100
101     /** Map key for the avalon context */
102     static final String JavaDoc DATA_MAP_CONTEXT = "QuartzJobScheduler.Context";
103
104     /** Map key for the service manager */
105     static final String JavaDoc DATA_MAP_MANAGER = "QuartzJobScheduler.ServiceManager";
106
107     /** Map key for the logger */
108     static final String JavaDoc DATA_MAP_LOGGER = "QuartzJobScheduler.Logger";
109
110     /** Map key for the concurrent run property */
111     static final String JavaDoc DATA_MAP_RUN_CONCURRENT = "QuartzJobScheduler.RunConcurrently";
112
113     /** Map key for additional Parameters */
114     static final String JavaDoc DATA_MAP_PARAMETERS = "QuartzJobScheduler.Parameters";
115
116     /** Map key for additional Object Map */
117     static final String JavaDoc DATA_MAP_OBJECTMAP = "QuartzJobScheduler.Map";
118
119     /* Map key for the last JobExecutionContext
120     static final String DATA_MAP_JOB_EXECUTION_CONTEXT = "QuartzJobScheduler.JobExecutionContext"; */

121
122     /** Map key for the run status */
123     static final String JavaDoc DATA_MAP_KEY_ISRUNNING = "QuartzJobExecutor.isRunning";
124
125
126     /** The group name */
127     static final String JavaDoc DEFAULT_QUARTZ_JOB_GROUP = "Cocoon";
128
129     /** The scheduler name */
130     static final String JavaDoc DEFAULT_QUARTZ_SCHEDULER_NAME = "Cocoon";
131
132     /** The Avalon Context instance */
133     private Context context;
134
135     /** The PooledExecutor instance */
136     private ThreadPool executor;
137
138     /** The quartz scheduler */
139     private Scheduler scheduler;
140
141     /** The ServiceManager instance */
142     private ServiceManager manager;
143
144     /** The configuration, parsed in initialize() */
145     private Configuration config;
146
147     /** Should we wait for running jobs to terminate on shutdown ? */
148     private boolean m_shutdownGraceful;
149
150     /* (non-Javadoc)
151      * @see org.apache.cocoon.components.cron.JobScheduler#getJobNames()
152      */

153     public String JavaDoc[] getJobNames() {
154         try {
155             final String JavaDoc[] names = scheduler.getJobNames(DEFAULT_QUARTZ_JOB_GROUP);
156             Arrays.sort(names);
157
158             return names;
159         } catch (final SchedulerException se) {
160             getLogger().error("could not gather job names", se);
161         }
162
163         return new String JavaDoc[0];
164     }
165
166     /* (non-Javadoc)
167      * @see org.apache.cocoon.components.cron.JobScheduler#getSchedulerEntry(java.lang.String)
168      */

169     public JobSchedulerEntry getJobSchedulerEntry(String JavaDoc jobname) {
170         try {
171             return new QuartzJobSchedulerEntry(jobname, scheduler);
172         } catch (final Exception JavaDoc e) {
173             getLogger().error("cannot create QuartzJobSchedulerEntry", e);
174         }
175
176         return null;
177     }
178
179     /* (non-Javadoc)
180      * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.Object, java.lang.String, boolean, org.apache.avalon.framework.parameters.Parameters, java.util.Map)
181      */

182     public void addJob(final String JavaDoc name, final Object JavaDoc job, final String JavaDoc cronSpec, final boolean canRunConcurrently,
183                        final Parameters params, final Map JavaDoc objects)
184     throws CascadingException {
185         final JobDataMap jobDataMap = new JobDataMap();
186         jobDataMap.put(DATA_MAP_OBJECT, job);
187         addJob(name, jobDataMap, cronSpec, canRunConcurrently, params, objects);
188     }
189
190     /* (non-Javadoc)
191      * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.String, java.lang.String, boolean, org.apache.avalon.framework.parameters.Parameters, java.util.Map)
192      */

193     public void addJob(final String JavaDoc name, final String JavaDoc jobrole, final String JavaDoc cronSpec,
194                        final boolean canRunConcurrently, final Parameters params, final Map JavaDoc objects)
195     throws CascadingException {
196         final JobDataMap jobDataMap = new JobDataMap();
197         jobDataMap.put(DATA_MAP_ROLE, jobrole);
198         addJob(name, jobDataMap, cronSpec, canRunConcurrently, params, objects);
199     }
200
201     /* (non-Javadoc)
202      * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.Object, java.lang.String, boolean)
203      */

204     public void addJob(final String JavaDoc name, final Object JavaDoc job, final String JavaDoc cronSpec, final boolean canRunConcurrently)
205     throws CascadingException {
206         if (!(job instanceof CronJob) && !(job instanceof Runnable JavaDoc) && !(job instanceof Job)) {
207             throw new CascadingException("Job object is neither an instance of " + CronJob.class.getName() + "," +
208                                          Runnable JavaDoc.class.getName() + " nor " + Job.class.getName());
209         }
210
211         addJob(name, job, cronSpec, canRunConcurrently, null, null);
212     }
213
214     /* (non-Javadoc)
215      * @see org.apache.cocoon.components.cron.JobScheduler#addJob(java.lang.String, java.lang.String, java.lang.String, boolean)
216      */

217     public void addJob(final String JavaDoc name, final String JavaDoc jobrole, final String JavaDoc cronSpec, final boolean canRunConcurrently)
218     throws CascadingException {
219         addJob(name, jobrole, cronSpec, canRunConcurrently, null, null);
220     }
221
222     /**
223      * Schedule a period job. Note that if a Job already has same name then it is overwritten.
224      *
225      * @param name the name of the job
226      * @param jobrole The Avalon components role name of the job itself
227      * @param period Every period seconds this job is started
228      * @param canRunConcurrently whether this job can run even previous scheduled runs are still running
229      * @param params additional Parameters to be passed to the job
230      * @param objects additional objects to be passed to the job
231      *
232      * @throws CascadingException in case of failures
233      */

234     public void addPeriodicJob(String JavaDoc name, String JavaDoc jobrole, long period, boolean canRunConcurrently, Parameters params,
235                                Map JavaDoc objects)
236     throws CascadingException {
237         final JobDataMap jobDataMap = new JobDataMap();
238         jobDataMap.put(DATA_MAP_ROLE, jobrole);
239
240         final long ms = period * 1000;
241         final SimpleTrigger timeEntry =
242             new SimpleTrigger(name, DEFAULT_QUARTZ_JOB_GROUP, new Date JavaDoc(System.currentTimeMillis() + ms), null,
243                               SimpleTrigger.REPEAT_INDEFINITELY, ms);
244
245         addJob(name, jobDataMap, timeEntry, canRunConcurrently, params, objects);
246     }
247
248     /**
249      * Schedule a periodic job. The job is started the first time when the period has passed. Note that if a job with
250      * the same name has already beed added it is overwritten.
251      *
252      * @param name the name of the job
253      * @param job The job object itself. It must implement either CronJob, Runnable or might also be an implementation
254      * specific class (i.e. org.quartz.Job)
255      * @param period Every period seconds this job is started
256      * @param canRunConcurrently whether this job can run even previous scheduled runs are still running
257      * @param params Additional Parameters to setup CronJob
258      * @param objects A Map with additional object to setup CronJob
259      */

260     public void addPeriodicJob(String JavaDoc name, Object JavaDoc job, long period, boolean canRunConcurrently, Parameters params,
261                                Map JavaDoc objects)
262     throws CascadingException {
263         if (!(job instanceof CronJob) && !(job instanceof Runnable JavaDoc) && !(job instanceof Job)) {
264             throw new CascadingException("Job object is neither an instance of " + CronJob.class.getName() + "," +
265                                          Runnable JavaDoc.class.getName() + " nor " + Job.class.getName());
266         }
267         final JobDataMap jobDataMap = new JobDataMap();
268         jobDataMap.put(DATA_MAP_OBJECT, job);
269
270         final long ms = period * 1000;
271         final SimpleTrigger timeEntry =
272             new SimpleTrigger(name, DEFAULT_QUARTZ_JOB_GROUP, new Date JavaDoc(System.currentTimeMillis() + ms), null,
273                               SimpleTrigger.REPEAT_INDEFINITELY, ms);
274
275         addJob(name, jobDataMap, timeEntry, canRunConcurrently, params, objects);
276     }
277
278     /* (non-Javadoc)
279      * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
280      */

281     public void configure(final Configuration config)
282     throws ConfigurationException {
283         this.config = config;
284     }
285
286     /* (non-Javadoc)
287      * @see org.apache.avalon.framework.activity.Disposable#dispose()
288      */

289     public void dispose() {
290         try {
291             if (getLogger().isInfoEnabled()) {
292                 getLogger().info("shutting down scheduler " +
293                                  (m_shutdownGraceful ? "graceful (waiting for running jobs to complete)"
294                                   : "immediately (killing running jobs)"));
295             }
296
297             scheduler.shutdown(m_shutdownGraceful);
298             scheduler = null;
299         } catch (final SchedulerException se) {
300             getLogger().error("failure during scheduler shutdown", se);
301         }
302
303         this.executor = null;
304     }
305
306     /* (non-Javadoc)
307      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
308      */

309     public void contextualize(Context context) throws ContextException {
310         this.context = context;
311     }
312
313     public void initialize() throws Exception JavaDoc {
314         try {
315             // If cocoon reloads (or is it the container that reload us?)
316
// we cannot create the same scheduler again
317
final String JavaDoc runID = new Date JavaDoc().toString().replace(' ', '_');
318             final QuartzThreadPool pool = createThreadPool(this.config.getChild("thread-pool"));
319             final JobStore store = createJobStore(DEFAULT_QUARTZ_SCHEDULER_NAME, runID, this.config.getChild("store"));
320             DirectSchedulerFactory.getInstance().createScheduler(DEFAULT_QUARTZ_SCHEDULER_NAME, runID, pool, store);
321             // scheduler = DirectSchedulerFactory.getInstance().getScheduler(DEFAULT_QUARTZ_SCHEDULER_NAME, runID);
322
scheduler = DirectSchedulerFactory.getInstance().getScheduler(DEFAULT_QUARTZ_SCHEDULER_NAME);
323         } catch (final SchedulerException se) {
324             throw new ConfigurationException("cannot create a quartz scheduler", se);
325         }
326
327         final Configuration[] triggers = this.config.getChild("triggers").getChildren("trigger");
328         createTriggers(triggers);
329
330         // We're finished with the configuration
331
this.config = null;
332
333         if (getLogger().isDebugEnabled() && (triggers.length == 0)) {
334             getLogger().debug("no triggers configured at startup");
335         }
336     }
337
338     /* (non-Javadoc)
339      * @see org.apache.cocoon.components.cron.JobScheduler#fireTarget(java.lang.Object)
340      */

341     public boolean fireJob(final Object JavaDoc job) {
342         return fireJob(job.getClass().getName(), job);
343     }
344
345     /* (non-Javadoc)
346      * @see org.apache.cocoon.components.cron.JobScheduler#fireTarget(java.lang.String)
347      */

348     public boolean fireJob(final String JavaDoc jobrole) {
349         Object JavaDoc job = null;
350
351         try {
352             job = manager.lookup(jobrole);
353
354             return fireJob(jobrole, job);
355         } catch (final ServiceException se) {
356             getLogger().error("cannot fire job " + jobrole, se);
357         } finally {
358             manager.release(job);
359         }
360
361         return false;
362     }
363
364     /* (non-Javadoc)
365      * @see org.apache.cocoon.components.cron.JobScheduler#fireJob(java.lang.Object, org.apache.avalon.framework.parameters.Parameters, java.util.Map)
366      */

367     public boolean fireJob(final Object JavaDoc job, final Parameters params, final Map JavaDoc objects)
368     throws CascadingException {
369         if (job instanceof ConfigurableCronJob) {
370             ((ConfigurableCronJob)job).setup(params, objects);
371         }
372
373         return fireJob(job);
374     }
375
376     /* (non-Javadoc)
377      * @see org.apache.cocoon.components.cron.JobScheduler#fireJob(java.lang.String, org.apache.avalon.framework.parameters.Parameters, java.util.Map)
378      */

379     public boolean fireJob(final String JavaDoc jobrole, final Parameters params, final Map JavaDoc objects)
380     throws CascadingException {
381         Object JavaDoc job = null;
382
383         try {
384             job = manager.lookup(jobrole);
385
386             if (job instanceof ConfigurableCronJob) {
387                 ((ConfigurableCronJob)job).setup(params, objects);
388             }
389
390             return fireJob(jobrole, job);
391         } catch (final ServiceException se) {
392             getLogger().error("cannot fire job " + jobrole, se);
393         } finally {
394             manager.release(job);
395         }
396
397         return false;
398     }
399
400     /* (non-Javadoc)
401      * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.Object)
402      */

403     public void fireJobAt(final Date JavaDoc date, final String JavaDoc name, final Object JavaDoc job)
404     throws CascadingException {
405         fireJobAt(date, name, job, null, null);
406     }
407
408     /* (non-Javadoc)
409      * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.String)
410      */

411     public void fireJobAt(final Date JavaDoc date, final String JavaDoc name, final String JavaDoc jobrole)
412     throws CascadingException {
413         fireJobAt(date, name, jobrole, null, null);
414     }
415
416     /* (non-Javadoc)
417      * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.Object, org.apache.avalon.framework.parameters.Parameters, java.util.Map)
418      */

419     public void fireJobAt(final Date JavaDoc date, final String JavaDoc name, final Object JavaDoc job, final Parameters params,
420                           final Map JavaDoc objects)
421     throws CascadingException {
422         final JobDataMap jobDataMap = new JobDataMap();
423         jobDataMap.put(DATA_MAP_OBJECT, job);
424         addJob(name, jobDataMap, date, true, params, objects);
425     }
426
427     /* (non-Javadoc)
428      * @see org.apache.cocoon.components.cron.JobScheduler#fireJobAt(java.util.Date, java.lang.String, java.lang.String, org.apache.avalon.framework.parameters.Parameters, java.util.Map)
429      */

430     public void fireJobAt(final Date JavaDoc date, final String JavaDoc name, final String JavaDoc jobrole, final Parameters params,
431                           final Map JavaDoc objects)
432     throws CascadingException {
433         final JobDataMap jobDataMap = new JobDataMap();
434         jobDataMap.put(DATA_MAP_ROLE, jobrole);
435         addJob(name, jobDataMap, date, true, params, objects);
436     }
437
438     /* (non-Javadoc)
439      * @see org.apache.cocoon.components.cron.JobScheduler#removeJob(java.lang.String)
440      */

441     public void removeJob(final String JavaDoc name)
442     throws NoSuchElementException JavaDoc {
443         try {
444             if (scheduler.deleteJob(name, DEFAULT_QUARTZ_JOB_GROUP)) {
445                 getLogger().info("job " + name + " removed by request");
446             } else {
447                 getLogger().error("couldn't remove requested job " + name);
448             }
449         } catch (final SchedulerException se) {
450             getLogger().error("cannot remove job " + name, se);
451             throw new NoSuchElementException JavaDoc(se.getMessage());
452         }
453     }
454
455     /* (non-Javadoc)
456      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
457      */

458     public void service(final ServiceManager manager)
459     throws ServiceException {
460         this.manager = manager;
461     }
462
463     /* (non-Javadoc)
464      * @see org.apache.avalon.framework.activity.Startable#start()
465      */

466     public void start()
467     throws Exception JavaDoc {
468         scheduler.start();
469     }
470
471     /* (non-Javadoc)
472      * @see org.apache.avalon.framework.activity.Startable#stop()
473      */

474     public void stop()
475     throws Exception JavaDoc {
476         scheduler.pause();
477     }
478
479     /**
480      * Add a job to the scheduler
481      *
482      * @param name The name of the job to add
483      * @param jobDataMap The JobDataMap to use for this job
484      * @param date the date to schedule this job
485      * @param canRunConcurrently whether this job can be run concurrently
486      * @param params Additional Parameters to setup CronJob
487      * @param objects A Map with additional object to setup CronJob
488      *
489      * @throws CascadingException thrown in case of errors
490      */

491     private void addJob(final String JavaDoc name, final JobDataMap jobDataMap, final Date JavaDoc date,
492                         final boolean canRunConcurrently, final Parameters params, final Map JavaDoc objects)
493     throws CascadingException {
494         final SimpleTrigger trigger = new SimpleTrigger(name, DEFAULT_QUARTZ_JOB_GROUP, date);
495         addJob(name, jobDataMap, trigger, canRunConcurrently, params, objects);
496     }
497
498     /**
499      * Add a job to the scheduler
500      *
501      * @param name The name of the job to add
502      * @param jobDataMap The JobDataMap to use for this job
503      * @param cronSpec a Cron time expression
504      * @param canRunConcurrently whether this job can be run concurrently
505      * @param params Additional Parameters to setup CronJob
506      * @param objects A Map with additional object to setup CronJob
507      *
508      * @throws CascadingException thrown in case of errors
509      */

510     private void addJob(final String JavaDoc name, final JobDataMap jobDataMap, final String JavaDoc cronSpec,
511                         final boolean canRunConcurrently, final Parameters params, final Map JavaDoc objects)
512     throws CascadingException {
513         final CronTrigger cronJobEntry = new CronTrigger(name, DEFAULT_QUARTZ_JOB_GROUP);
514
515         try {
516             cronJobEntry.setCronExpression(cronSpec);
517         } catch (final ParseException JavaDoc pe) {
518             throw new CascadingException(pe.getMessage(), pe);
519         }
520
521         addJob(name, jobDataMap, cronJobEntry, canRunConcurrently, params, objects);
522     }
523
524     /**
525      * Add a job to the scheduler
526      *
527      * @param name The name of the job to add
528      * @param jobDataMap The JobDataMap to use for this job
529      * @param trigger a Trigger
530      * @param canRunConcurrently whether this job can be run concurrently
531      * @param params Additional Parameters to setup CronJob (might be null)
532      * @param objects A Map with additional object to setup CronJob (might be null)
533      *
534      * @throws CascadingException thrown in case of errors
535      */

536     private void addJob(final String JavaDoc name, final JobDataMap jobDataMap, final Trigger trigger,
537                         final boolean canRunConcurrently, final Parameters params, final Map JavaDoc objects)
538     throws CascadingException {
539         try {
540             final JobDetail jobdetail = scheduler.getJobDetail(name, DEFAULT_QUARTZ_JOB_GROUP);
541             if (jobdetail != null) {
542                 removeJob(name);
543             }
544         } catch (final SchedulerException ignored) {
545         }
546
547         initDataMap(jobDataMap, name, canRunConcurrently, params, objects);
548         
549         final JobDetail detail = createJobDetail(name, jobDataMap);
550
551         if (getLogger().isInfoEnabled()) {
552             getLogger().info("Adding CronJob '" + trigger.getFullName() + "'");
553         }
554
555         try {
556             scheduler.scheduleJob(detail, trigger);
557         } catch (final SchedulerException se) {
558             throw new CascadingException(se.getMessage(), se);
559         }
560
561         if (getLogger().isDebugEnabled()) {
562             if (trigger instanceof CronTrigger) {
563                 getLogger().debug("Time schedule summary:\n" + ((CronTrigger)trigger).getExpressionSummary());
564             } else {
565                 getLogger().debug("Next scheduled time: " + trigger.getNextFireTime());
566             }
567         }
568     }
569
570     protected JobDataMap initDataMap(JobDataMap jobDataMap, String JavaDoc jobName, boolean concurent,
571                                      Parameters params, Map JavaDoc objects) {
572         jobDataMap.put(DATA_MAP_NAME, jobName);
573         jobDataMap.put(DATA_MAP_LOGGER, getLogger());
574         jobDataMap.put(DATA_MAP_CONTEXT, this.context);
575         jobDataMap.put(DATA_MAP_MANAGER, this.manager);
576         jobDataMap.put(DATA_MAP_RUN_CONCURRENT, concurent? Boolean.TRUE: Boolean.FALSE);
577         if (null != params) {
578             jobDataMap.put(DATA_MAP_PARAMETERS, params);
579         }
580         if (null != objects) {
581             jobDataMap.put(DATA_MAP_OBJECTMAP, objects);
582         }
583         return jobDataMap;
584     }
585     
586     protected JobDetail createJobDetail(String JavaDoc name, JobDataMap jobDataMap) {
587         final JobDetail detail = new JobDetail(name, DEFAULT_QUARTZ_JOB_GROUP, QuartzJobExecutor.class);
588         detail.setJobDataMap(jobDataMap);
589         return detail;
590     }
591
592     /**
593      * Create a QuartzThreadPool
594      *
595      * @param poolConfig Configuration element for the thread pool
596      *
597      * @return QuartzThreadPool
598      */

599     private QuartzThreadPool createThreadPool(final Configuration poolConfig)
600     throws ServiceException {
601         final boolean useQueueing = poolConfig.getChild("use-queueing").getValueAsBoolean(false);
602         final int queueSize = poolConfig.getChild("queue-size").getValueAsInteger(-1);
603         final int maxPoolSize = poolConfig.getChild("max-pool-size").getValueAsInteger(-1);
604         final int minPoolSize = poolConfig.getChild("min-pool-size").getValueAsInteger(-1);
605         final int keepAliveTimeMs = poolConfig.getChild("keep-alive-time-ms").getValueAsInteger(-1);
606         final String JavaDoc blockPolicy = poolConfig.getChild("block-policy").getValue(null);
607         m_shutdownGraceful = poolConfig.getChild("shutdown-graceful").getValueAsBoolean(true);
608
609         final int shutdownWaitTimeMs = poolConfig.getChild("shutdown-wait-time-ms").getValueAsInteger(-1);
610         final RunnableManager runnableManager = (RunnableManager)this.manager.lookup(RunnableManager.ROLE);
611         this.executor = runnableManager.createPool(queueSize,
612                                                    maxPoolSize,
613                                                    minPoolSize,
614                                                    Thread.NORM_PRIORITY,
615                                                    false, // no daemon
616
keepAliveTimeMs,
617                                                    blockPolicy,
618                                                    m_shutdownGraceful,
619                                                    shutdownWaitTimeMs);
620         final QuartzThreadPool pool = new QuartzThreadPool(this.executor);
621         return pool;
622     }
623
624     /**
625      * Create the triggers
626      *
627      * @param triggers array of trigger configuration elements
628      *
629      * @throws ConfigurationException thrown in case of configuration failures
630      */

631     private void createTriggers(final Configuration[] triggers)
632     throws ConfigurationException {
633         for (int i = 0; i < triggers.length; i++) {
634             String JavaDoc cron = triggers[i].getChild("cron").getValue(null);
635
636             if (null == cron) {
637                 final String JavaDoc seconds = triggers[i].getChild("seconds").getValue("0");
638                 final String JavaDoc minutes = triggers[i].getChild("minutes").getValue("*");
639                 final String JavaDoc hours = triggers[i].getChild("hours").getValue("*");
640                 final String JavaDoc days = triggers[i].getChild("days").getValue("*");
641                 final String JavaDoc months = triggers[i].getChild("months").getValue("*");
642                 final String JavaDoc weekdays = triggers[i].getChild("weekdays").getValue("?");
643                 final String JavaDoc years = triggers[i].getChild("years").getValue("*");
644                 cron = seconds + " " + minutes + " " + hours + " " + days + " " + months + " " + weekdays + " " +
645                        years;
646             }
647
648             try {
649                 addJob(triggers[i].getAttribute("name"), triggers[i].getAttribute("target"), cron,
650                        triggers[i].getAttributeAsBoolean("concurrent-runs", true));
651             } catch (final CascadingException ce) {
652                 throw new ConfigurationException("failed adding trigger to scheduler", ce);
653             }
654         }
655     }
656
657     private JobStore createJobStore(String JavaDoc instanceName, String JavaDoc instanceID, final Configuration configuration)
658     throws ConfigurationException {
659         String JavaDoc type = configuration.getAttribute("type", "ram");
660         if (type.equals("ram")) {
661             return new RAMJobStore();
662         }
663
664         JobStoreSupport store = null;
665         if (type.equals("tx")) {
666             store = new QuartzJobStoreTX(getLogger(), this.manager, this.context);
667         } else if (type.equals("cmt")) {
668             store = new QuartzJobStoreCMT(getLogger(), this.manager, this.context);
669         } else {
670             throw new ConfigurationException("Unknown store type: " + type);
671         }
672
673         Configuration dsConfig = configuration.getChild("datasource", false);
674         if (dsConfig == null) {
675             throw new ConfigurationException("Store " + type + " requires datasource configuration.");
676         }
677
678         String JavaDoc dsName = dsConfig.getValue();
679         String JavaDoc dsType = dsConfig.getAttribute("provider", "jndi");
680
681         ConnectionProvider provider;
682         if (dsType.equals("jndi")) {
683             provider = new JNDIConnectionProvider(dsName, false);
684         } else if (dsType.equals("excalibur")) {
685             provider = new DataSourceComponentConnectionProvider(dsName, this.manager);
686         } else {
687             // assume class name
688
try {
689                 provider = (ConnectionProvider)Class.forName(dsType).newInstance();
690             } catch (Exception JavaDoc e) {
691                 throw new ConfigurationException("Could not instantiate ConnectionProvider class " + dsType);
692             }
693         }
694
695         store.setInstanceName(instanceName);
696         store.setInstanceId(instanceID);
697         store.setDataSource(dsType + ":" + dsName);
698         DBConnectionManager.getInstance().addConnectionProvider(dsType + ":" + dsName, provider);
699
700         String JavaDoc delegate = configuration.getAttribute("delegate", null);
701         try {
702             if (delegate != null) {
703                 store.setDriverDelegateClass(delegate);
704             }
705         } catch (InvalidConfigurationException e) {
706             throw new ConfigurationException("Could not instantiate DriverDelegate class " + delegate, e);
707         }
708
709         return store;
710     }
711
712     /* (non-Javadoc)
713      * @see org.apache.cocoon.components.cron.JobScheduler#fireTarget(java.lang.Object)
714      */

715     private boolean fireJob(final String JavaDoc name, final Object JavaDoc job) {
716         try {
717             if (job instanceof CronJob) {
718                 JobDataMap jobDataMap = new JobDataMap();
719                 jobDataMap.put(DATA_MAP_OBJECT, job);
720                 initDataMap(jobDataMap, name, true, null, null);
721
722                 final JobDetail detail = createJobDetail(name, jobDataMap);
723
724                 TriggerFiredBundle trigger = new TriggerFiredBundle(detail, null, null, false, null, null, null, null);
725
726                 final Job executor = createJobExecutor();
727                 final JobExecutionContext context = new JobExecutionContext(this.scheduler, trigger, executor);
728
729                 this.executor.execute(new Runnable JavaDoc() {
730                         public void run() {
731                             // ((CronJob)job).execute(name);
732
try {
733                                 executor.execute(context);
734                             } catch (JobExecutionException e) {
735                                 getLogger().error("Job '" + job + "' died.", e);
736                             }
737                         }
738                     });
739             } else if (job instanceof Runnable JavaDoc) {
740                 this.executor.execute((Runnable JavaDoc)job);
741             } else {
742                 getLogger().error("Job named '" + name + "' is of invalid class: " + job.getClass().getName());
743                 return false;
744             }
745
746             return true;
747         } catch (final InterruptedException JavaDoc ie) {
748             getLogger().error("job " + name + " interrupted", ie);
749         }
750
751         return false;
752     }
753
754     protected Job createJobExecutor() {
755         return new QuartzJobExecutor();
756     }
757     
758     /**
759      * A QuartzThreadPool for the Quartz Scheduler based on Doug Leas concurrency utilities PooledExecutor
760      *
761      * @author <a HREF="mailto:giacomo@otego.com">Giacomo Pati</a>
762      * @version CVS $Id: QuartzJobScheduler.java 125647 2005-01-19 19:59:36Z rgoers $
763      */

764     private static class QuartzThreadPool extends AbstractLogEnabled implements org.quartz.spi.ThreadPool {
765         /** Our executor thread pool */
766         private ThreadPool executor;
767
768         /**
769          *
770          */

771         public QuartzThreadPool(final ThreadPool executor) {
772             super();
773             this.executor = executor;
774         }
775
776         /* (non-Javadoc)
777          * @see org.quartz.spi.QuartzThreadPool#getPoolSize()
778          */

779         public int getPoolSize() {
780             return this.executor.getMaximumPoolSize();
781         }
782
783         /* (non-Javadoc)
784          * @see org.quartz.spi.QuartzThreadPool#initialize()
785          */

786         public void initialize() {
787         }
788
789         /* (non-Javadoc)
790          * @see org.quartz.spi.QuartzThreadPool#runInThread(java.lang.Runnable)
791          */

792         public boolean runInThread(final Runnable JavaDoc job) {
793             try {
794                 this.executor.execute(job);
795             } catch (final InterruptedException JavaDoc ie) {
796                 getLogger().error("Cronjob failed", ie);
797             }
798
799             return true;
800         }
801
802         /* (non-Javadoc)
803          * @see org.quartz.spi.QuartzThreadPool#shutdown(boolean)
804          */

805         public void shutdown(final boolean waitForJobsToComplete) {
806             this.executor.shutdown();
807         }
808     }
809 }
810
Popular Tags