KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > scheduler > CmsScheduledJobInfo


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/scheduler/CmsScheduledJobInfo.java,v $
3  * Date : $Date: 2006/03/27 14:52:20 $
4  * Version: $Revision: 1.19 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.scheduler;
33
34 import org.opencms.configuration.I_CmsConfigurationParameterHandler;
35 import org.opencms.main.CmsContextInfo;
36 import org.opencms.main.CmsIllegalArgumentException;
37 import org.opencms.main.CmsLog;
38 import org.opencms.main.CmsRuntimeException;
39 import org.opencms.util.CmsStringUtil;
40
41 import java.util.Collections JavaDoc;
42 import java.util.Date JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.SortedMap JavaDoc;
45 import java.util.TreeMap JavaDoc;
46
47 import org.apache.commons.logging.Log;
48
49 import org.quartz.CronTrigger;
50 import org.quartz.Trigger;
51
52 /**
53  * Describes a scheduled job for the OpenCms scheduler.<p>
54  *
55  * <p>
56  * The time the scheduled job is executed is defined with Unix 'cron-like' definitions.
57  * </p>
58  *
59  * <p>
60  * For those unfamiliar with "cron", this means being able to create a firing
61  * schedule such as: "At 8:00am every Monday through Friday" or "At 1:30am
62  * every last Friday of the month".
63  * </p>
64  *
65  * <p>
66  * A "Cron-Expression" is a string comprised of 6 or 7 fields separated by
67  * white space. The 6 mandatory and 1 optional fields are as follows: <br>
68  *
69  * <table cellspacing="8">
70  * <tr>
71  * <th align="left">Field Name</th>
72  * <th align="left">&nbsp;</th>
73  * <th align="left">Allowed Values</th>
74  * <th align="left">&nbsp;</th>
75  * <th align="left">Allowed Special Characters</th>
76  * </tr>
77  * <tr>
78  * <td align="left"><code>Seconds</code></td>
79  * <td align="left">&nbsp;</td>
80  * <td align="left"><code>0-59</code></td>
81  * <td align="left">&nbsp;</td>
82  * <td align="left"><code>, - * /</code></td>
83  * </tr>
84  * <tr>
85  * <td align="left"><code>Minutes</code></td>
86  * <td align="left">&nbsp;</td>
87  * <td align="left"><code>0-59</code></td>
88  * <td align="left">&nbsp;</td>
89  * <td align="left"><code>, - * /</code></td>
90  * </tr>
91  * <tr>
92  * <td align="left"><code>Hours</code></td>
93  * <td align="left">&nbsp;</td>
94  * <td align="left"><code>0-23</code></td>
95  * <td align="left">&nbsp;</td>
96  * <td align="left"><code>, - * /</code></td>
97  * </tr>
98  * <tr>
99  * <td align="left"><code>Day-of-month</code></td>
100  * <td align="left">&nbsp;</td>
101  * <td align="left"><code>1-31</code></td>
102  * <td align="left">&nbsp;</td>
103  * <td align="left"><code>, - * ? / L C</code></td>
104  * </tr>
105  * <tr>
106  * <td align="left"><code>Month</code></td>
107  * <td align="left">&nbsp;</td>
108  * <td align="left"><code>1-12 or JAN-DEC</code></td>
109  * <td align="left">&nbsp;</td>
110  * <td align="left"><code>, - * /</code></td>
111  * </tr>
112  * <tr>
113  * <td align="left"><code>Day-of-Week</code></td>
114  * <td align="left">&nbsp;</td>
115  * <td align="left"><code>1-7 or SUN-SAT</code></td>
116  * <td align="left">&nbsp;</td>
117  * <td align="left"><code>, - * ? / L C #</code></td>
118  * </tr>
119  * <tr>
120  * <td align="left"><code>Year (Optional)</code></td>
121  * <td align="left">&nbsp;</td>
122  * <td align="left"><code>empty, 1970-2099</code></td>
123  * <td align="left">&nbsp;</td>
124  * <td align="left"><code>, - * /</code></td>
125  * </tr>
126  * </table>
127  * </p>
128  *
129  * <p>
130  * The '*' character is used to specify all values. For example, "*" in the
131  * minute field means "every minute".
132  * </p>
133  *
134  * <p>
135  * The '?' character is allowed for the day-of-month and day-of-week fields. It
136  * is used to specify 'no specific value'. This is useful when you need to
137  * specify something in one of the two fileds, but not the other. See the
138  * examples below for clarification.
139  * </p>
140  *
141  * <p>
142  * The '-' character is used to specify ranges For example "10-12" in the hour
143  * field means "the hours 10, 11 and 12".
144  * </p>
145  *
146  * <p>
147  * The ',' character is used to specify additional values. For example
148  * "MON,WED,FRI" in the day-of-week field means "the days Monday, Wednesday,
149  * and Friday".
150  * </p>
151  *
152  * <p>
153  * The '/' character is used to specify increments. For example "0/15" in the
154  * seconds field means "the seconds 0, 15, 30, and 45". And "5/15" in the
155  * seconds field means "the seconds 5, 20, 35, and 50". You can also specify
156  * '/' after the '*' character - in this case '*' is equivalent to having '0'
157  * before the '/'.
158  * </p>
159  *
160  * <p>
161  * The 'L' character is allowed for the day-of-month and day-of-week fields.
162  * This character is short-hand for "last", but it has different meaning in
163  * each of the two fields. For example, the value "L" in the day-of-month field
164  * means "the last day of the month" - day 31 for January, day 28 for February
165  * on non-leap years. If used in the day-of-week field by itself, it simply
166  * means "7" or "SAT". But if used in the day-of-week field after another
167  * value, it means "the last xxx day of the month" - for example "6L" means
168  * "the last friday of the month". When using the 'L' option, it is important
169  * not to specify lists, or ranges of values, as you'll get confusing results.
170  * </p>
171  *
172  * <p>
173  * The 'W' character is allowed for the day-of-month field. This character
174  * is used to specify the weekday (Monday-Friday) nearest the given day. As an
175  * example, if you were to specify "15W" as the value for the day-of-month
176  * field, the meaning is: "the nearest weekday to the 15th of the month". So
177  * if the 15th is a Saturday, the trigger will fire on Friday the 14th. If the
178  * 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is
179  * a Tuesday, then it will fire on Tuesday the 15th. However if you specify
180  * "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger
181  * will fire on Monday the 3rd, as it will not 'jump' over the boundary of a
182  * month's days. The 'W' character can only be specified when the day-of-month
183  * is a single day, not a range or list of days.
184  * </p>
185  *
186  * <p>
187  * The 'L' and 'W' characters can also be combined for the day-of-month
188  * expression to yield 'LW', which translates to "last weekday of the month".
189  * </p>
190  *
191  * <p>
192  * The '#' character is allowed for the day-of-week field. This character is
193  * used to specify "the nth" XXX day of the month. For example, the value of
194  * "6#3" in the day-of-week field means the third Friday of the month (day 6 =
195  * Friday and "#3" = the 3rd one in the month). Other examples: "2#1" = the
196  * first Monday of the month and "4#5" = the fifth Wednesday of the month. Note
197  * that if you specify "#5" and there is not 5 of the given day-of-week in the
198  * month, then no firing will occur that month.
199  * </p>
200  *
201  * <p>
202  * The 'C' character is allowed for the day-of-month and day-of-week fields.
203  * This character is short-hand for "calendar". This means values are
204  * calculated against the associated calendar, if any. If no calendar is
205  * associated, then it is equivalent to having an all-inclusive calendar. A
206  * value of "5C" in the day-of-month field means "the first day included by the
207  * calendar on or after the 5th". A value of "1C" in the day-of-week field
208  * means "the first day included by the calendar on or after sunday".
209  * </p>
210  *
211  * <p>
212  * The legal characters and the names of months and days of the week are not
213  * case sensitive.
214  * </p>
215  *
216  * <p>
217  * Here are some full examples: <br><table cellspacing="8">
218  * <tr>
219  * <th align="left">Expression</th>
220  * <th align="left">&nbsp;</th>
221  * <th align="left">Meaning</th>
222  * </tr>
223  * <tr>
224  * <td align="left"><code>"0 0 12 * * ?"</code></td>
225  * <td align="left">&nbsp;</td>
226  * <td align="left"><code>Fire at 12pm (noon) every day</code></td>
227  * </tr>
228  * <tr>
229  * <td align="left"><code>"0 15 10 ? * *"</code></td>
230  * <td align="left">&nbsp;</td>
231  * <td align="left"><code>Fire at 10:15am every day</code></td>
232  * </tr>
233  * <tr>
234  * <td align="left"><code>"0 15 10 * * ?"</code></td>
235  * <td align="left">&nbsp;</td>
236  * <td align="left"><code>Fire at 10:15am every day</code></td>
237  * </tr>
238  * <tr>
239  * <td align="left"><code>"0 15 10 * * ? *"</code></td>
240  * <td align="left">&nbsp;</td>
241  * <td align="left"><code>Fire at 10:15am every day</code></td>
242  * </tr>
243  * <tr>
244  * <td align="left"><code>"0 15 10 * * ? 2005"</code></td>
245  * <td align="left">&nbsp;</td>
246  * <td align="left"><code>Fire at 10:15am every day during the year 2005</code>
247  * </td>
248  * </tr>
249  * <tr>
250  * <td align="left"><code>"0 * 14 * * ?"</code></td>
251  * <td align="left">&nbsp;</td>
252  * <td align="left"><code>Fire every minute starting at 2pm and ending at 2:59pm, every day</code>
253  * </td>
254  * </tr>
255  * <tr>
256  * <td align="left"><code>"0 0/5 14 * * ?"</code></td>
257  * <td align="left">&nbsp;</td>
258  * <td align="left"><code>Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day</code>
259  * </td>
260  * </tr>
261  * <tr>
262  * <td align="left"><code>"0 0/5 14,18 * * ?"</code></td>
263  * <td align="left">&nbsp;</td>
264  * <td align="left"><code>Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day</code>
265  * </td>
266  * </tr>
267  * <tr>
268  * <td align="left"><code>"0 0-5 14 * * ?"</code></td>
269  * <td align="left">&nbsp;</td>
270  * <td align="left"><code>Fire every minute starting at 2pm and ending at 2:05pm, every day</code>
271  * </td>
272  * </tr>
273  * <tr>
274  * <td align="left"><code>"0 10,44 14 ? 3 WED"</code></td>
275  * <td align="left">&nbsp;</td>
276  * <td align="left"><code>Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.</code>
277  * </td>
278  * </tr>
279  * <tr>
280  * <td align="left"><code>"0 15 10 ? * MON-FRI"</code></td>
281  * <td align="left">&nbsp;</td>
282  * <td align="left"><code>Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday</code>
283  * </td>
284  * </tr>
285  * <tr>
286  * <td align="left"><code>"0 15 10 15 * ?"</code></td>
287  * <td align="left">&nbsp;</td>
288  * <td align="left"><code>Fire at 10:15am on the 15th day of every month</code>
289  * </td>
290  * </tr>
291  * <tr>
292  * <td align="left"><code>"0 15 10 L * ?"</code></td>
293  * <td align="left">&nbsp;</td>
294  * <td align="left"><code>Fire at 10:15am on the last day of every month</code>
295  * </td>
296  * </tr>
297  * <tr>
298  * <td align="left"><code>"0 15 10 ? * 6L"</code></td>
299  * <td align="left">&nbsp;</td>
300  * <td align="left"><code>Fire at 10:15am on the last Friday of every month</code>
301  * </td>
302  * </tr>
303  * <tr>
304  * <td align="left"><code>"0 15 10 ? * 6L"</code></td>
305  * <td align="left">&nbsp;</td>
306  * <td align="left"><code>Fire at 10:15am on the last Friday of every month</code>
307  * </td>
308  * </tr>
309  * <tr>
310  * <td align="left"><code>"0 15 10 ? * 6L 2002-2005"</code></td>
311  * <td align="left">&nbsp;</td>
312  * <td align="left"><code>Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005</code>
313  * </td>
314  * </tr>
315  * <tr>
316  * <td align="left"><code>"0 15 10 ? * 6#3"</code></td>
317  * <td align="left">&nbsp;</td>
318  * <td align="left"><code>Fire at 10:15am on the third Friday of every month</code>
319  * </td>
320  * </tr>
321  * </table>
322  * </p>
323  *
324  * <p>
325  * Pay attention to the effects of '?' and '*' in the day-of-week and
326  * day-of-month fields!
327  * </p>
328  *
329  * <p>
330  * <b>NOTES:</b>
331  * <ul>
332  * <li>Support for the features described for the 'C' character is not
333  * complete.</li>
334  * <li>Support for specifying both a day-of-week and a day-of-month value is
335  * not complete (you'll need to use the '?' character in on of these fields).
336  * </li>
337  * <li>Be careful when setting fire times between mid-night and 1:00 AM -
338  * "daylight savings" can cause a skip or a repeat depending on whether the
339  * time moves back or jumps forward.</li>
340  * </ul>
341  * </p>
342  *
343  *
344  * @author Alexander Kandzior
345  *
346  * @version $Revision: 1.19 $
347  *
348  * @since 6.0.0
349  */

350 public class CmsScheduledJobInfo implements I_CmsConfigurationParameterHandler {
351
352     /** The log object for this class. */
353     private static final Log LOG = CmsLog.getLog(CmsScheduledJobInfo.class);
354
355     /** Indicates if this job is currently active in the scheduler or not. */
356     private boolean m_active;
357
358     /** The name of the class to schedule. */
359     private String JavaDoc m_className;
360
361     /** The context information for the user to execute the job with. */
362     private CmsContextInfo m_context;
363
364     /** The cron expression for this scheduler job. */
365     private String JavaDoc m_cronExpression;
366
367     /** Indicates if the configuration of this job is finalized (frozen). */
368     private boolean m_frozen;
369
370     /** The id of this job. */
371     private String JavaDoc m_id;
372
373     /** Instance object of the scheduled job (only required when instance is re-used). */
374     private I_CmsScheduledJob m_jobInstance;
375
376     /** The name of the job (for information purposes). */
377     private String JavaDoc m_jobName;
378
379     /** The parameters used for this job entry. */
380     private SortedMap JavaDoc m_parameters;
381
382     /** Indicates if the job instance should be re-used if the job is run. */
383     private boolean m_reuseInstance;
384
385     /** The (cron) trigger used for scheduling this job. */
386     private Trigger m_trigger;
387
388     /**
389      * Default constructor.<p>
390      */

391     public CmsScheduledJobInfo() {
392
393         m_reuseInstance = false;
394         m_frozen = false;
395         // parameters are stored in a tree map
396
m_parameters = new TreeMap JavaDoc();
397         // a job is active by default
398
m_active = true;
399     }
400
401     /**
402      * Constructor for creating a new job with all required parameters.<p>
403      *
404      * @param id the id of the job of <code>null</code> if a new id should be automatically generated
405      * @param jobName the display name of the job
406      * @param className the class name of the job, must be an instance of <code>{@link I_CmsScheduledJob}</code>
407      * @param context the OpenCms user context information to use when executing the job
408      * @param cronExpression the cron expression for scheduling the job
409      * @param reuseInstance indicates if the job class should be re-used
410      * @param active indicates if the job should be active in the scheduler
411      * @param parameters the job parameters
412      */

413     public CmsScheduledJobInfo(
414         String JavaDoc id,
415         String JavaDoc jobName,
416         String JavaDoc className,
417         CmsContextInfo context,
418         String JavaDoc cronExpression,
419         boolean reuseInstance,
420         boolean active,
421         SortedMap JavaDoc parameters) {
422
423         m_frozen = false;
424         setId(id);
425         if (CmsStringUtil.isNotEmpty(jobName)) {
426             // job name is optional, if not present class name will be used
427
setJobName(jobName);
428         }
429         setClassName(className);
430         setContextInfo(context);
431         setCronExpression(cronExpression);
432         setReuseInstance(reuseInstance);
433         setActive(active);
434         setParameters(parameters);
435     }
436
437     /**
438      * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String)
439      */

440     public void addConfigurationParameter(String JavaDoc paramName, String JavaDoc paramValue) {
441
442         checkFrozen();
443         // add the configured parameter
444
m_parameters.put(paramName, paramValue);
445         if (LOG.isDebugEnabled()) {
446             LOG.debug(org.opencms.configuration.Messages.get().getBundle().key(
447                 org.opencms.configuration.Messages.LOG_ADD_CONFIG_PARAM_3,
448                 paramName,
449                 paramValue,
450                 this));
451         }
452     }
453
454     /**
455      * Clears the id of the job.<p>
456      *
457      * This is useful if you want to create a copy of a job without keeping the job id.
458      * Use <code>{@link CmsScheduledJobInfo#clone()}</code> first to create the copy,
459      * and then clear the id of the clone.<p>
460      */

461     public void clearId() {
462
463         setId(null);
464     }
465
466     /**
467      * Creates a clone of this scheduled job.<p>
468      *
469      * The clone will not be active in the scheduler until it is scheduled
470      * with <code>{@link CmsScheduleManager#scheduleJob(org.opencms.file.CmsObject, CmsScheduledJobInfo)}</code>.
471      * The job id returned by <code>{@link #getId()}</code> will be the same.
472      * The <code>{@link #isActive()}</code> flag will be set to false.
473      * The clones job instance class will be the same
474      * if the <code>{@link #isReuseInstance()}</code> flag is set.<p>
475      *
476      * @see java.lang.Object#clone()
477      */

478     public Object JavaDoc clone() {
479
480         CmsScheduledJobInfo result = new CmsScheduledJobInfo();
481
482         result.m_id = m_id;
483         result.m_active = false;
484         result.m_frozen = false;
485         result.m_className = m_className;
486         if (isReuseInstance()) {
487             result.m_jobInstance = m_jobInstance;
488         }
489         result.m_reuseInstance = m_reuseInstance;
490         result.m_context = (CmsContextInfo)m_context.clone();
491         result.m_cronExpression = m_cronExpression;
492         result.m_jobName = m_jobName;
493         result.m_parameters = new TreeMap JavaDoc(m_parameters);
494         result.m_trigger = null;
495
496         return result;
497     }
498
499     /**
500      * Returns the name of the class to schedule.<p>
501      *
502      * @return the name of the class to schedule
503      */

504     public String JavaDoc getClassName() {
505
506         return m_className;
507     }
508
509     /**
510      * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration()
511      */

512     public Map JavaDoc getConfiguration() {
513
514         // this configuration does not support parameters
515
if (LOG.isDebugEnabled()) {
516             LOG.debug(org.opencms.configuration.Messages.get().getBundle().key(
517                 org.opencms.configuration.Messages.LOG_GET_CONFIGURATION_1,
518                 this));
519         }
520         return getParameters();
521     }
522
523     /**
524      * Returns the context information for the user executing the job.<p>
525      *
526      * @return the context information for the user executing the job
527      */

528     public CmsContextInfo getContextInfo() {
529
530         return m_context;
531     }
532
533     /**
534      * Returns the cron expression for this job entry.<p>
535      *
536      * @return the cron expression for this job entry
537      */

538     public String JavaDoc getCronExpression() {
539
540         return m_cronExpression;
541     }
542
543     /**
544      * Returns the next time at which this job will be executed, after the given time.<p>
545      *
546      * If this job will not be executed after the given time, <code>null</code> will be returned..<p>
547      *
548      * @param date the after which the next execution time should be calculated
549      * @return the next time at which this job will be executed, after the given time
550      */

551     public Date JavaDoc getExecutionTimeAfter(Date JavaDoc date) {
552
553         if (!m_active || (m_trigger == null)) {
554             // if the job is not active, no time can be calculated
555
return null;
556         }
557
558         return m_trigger.getFireTimeAfter(date);
559     }
560
561     /**
562      * Returns the next time at which this job will be executed.<p>
563      *
564      * If the job will not execute again, <code>null</code> will be returned.<p>
565      *
566      * @return the next time at which this job will be executed
567      */

568     public Date JavaDoc getExecutionTimeNext() {
569
570         if (!m_active || (m_trigger == null)) {
571             // if the job is not active, no time can be calculated
572
return null;
573         }
574
575         return m_trigger.getNextFireTime();
576     }
577
578     /**
579      * Returns the previous time at which this job will be executed.<p>
580      *
581      * If this job has not yet been executed, <code>null</code> will be returned.
582      *
583      * @return the previous time at which this job will be executed
584      */

585     public Date JavaDoc getExecutionTimePrevious() {
586
587         if (!m_active || (m_trigger == null)) {
588             // if the job is not active, no time can be calculated
589
return null;
590         }
591
592         return m_trigger.getPreviousFireTime();
593     }
594
595     /**
596      * Returns the internal id of this job in the scheduler.<p>
597      *
598      * Can be used to remove this job from the scheduler with
599      * <code>{@link CmsScheduleManager#unscheduleJob(org.opencms.file.CmsObject, String)}</code>.<p>
600      *
601      * @return the internal id of this job in the scheduler
602      */

603     public String JavaDoc getId() {
604
605         return m_id;
606     }
607
608     /**
609      * Returns an instance of the configured job class.<p>
610      *
611      * If any error occurs during class invocaion, the error
612      * is written to the OpenCms log and <code>null</code> is returned.<p>
613      *
614      * @return an instance of the configured job class, or null if an error occured
615      */

616     public synchronized I_CmsScheduledJob getJobInstance() {
617
618         if (m_jobInstance != null) {
619
620             if (LOG.isDebugEnabled()) {
621                 LOG.debug(Messages.get().getBundle().key(
622                     Messages.LOG_REUSING_INSTANCE_1,
623                     m_jobInstance.getClass().getName()));
624             }
625
626             // job instance already initialized
627
return m_jobInstance;
628         }
629
630         I_CmsScheduledJob job = null;
631
632         try {
633             // create an instance of the OpenCms job class
634
job = (I_CmsScheduledJob)Class.forName(getClassName()).newInstance();
635         } catch (ClassNotFoundException JavaDoc e) {
636             LOG.error(Messages.get().getBundle().key(Messages.LOG_CLASS_NOT_FOUND_1, getClassName()), e);
637         } catch (IllegalAccessException JavaDoc e) {
638             LOG.error(Messages.get().getBundle().key(Messages.LOG_ILLEGAL_ACCESS_0), e);
639         } catch (InstantiationException JavaDoc e) {
640             LOG.error(Messages.get().getBundle().key(Messages.LOG_INSTANCE_GENERATION_0), e);
641         } catch (ClassCastException JavaDoc e) {
642             LOG.error(Messages.get().getBundle().key(Messages.LOG_BAD_INTERFACE_0), e);
643         }
644
645         if (m_reuseInstance) {
646             // job instance must be re-used
647
m_jobInstance = job;
648         }
649
650         if (LOG.isDebugEnabled()) {
651             LOG.debug(Messages.get().getBundle().key(Messages.LOG_JOB_CREATED_1, getClassName()));
652         }
653
654         return job;
655     }
656
657     /**
658      * Returns the job name.<p>
659      *
660      * @return the job name
661      */

662     public String JavaDoc getJobName() {
663
664         return m_jobName;
665     }
666
667     /**
668      * Returns the parameters.<p>
669      *
670      * @return the parameters
671      */

672     public SortedMap JavaDoc getParameters() {
673
674         return m_parameters;
675     }
676
677     /**
678      * Finalizes (freezes) the configuration of this scheduler job entry.<p>
679      *
680      * After this job entry has been frozen, any attempt to change the
681      * configuration of this entry with one of the "set..." methods
682      * will lead to a <code>RuntimeException</code>.<p>
683      *
684      * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration()
685      */

686     public void initConfiguration() {
687
688         // simple default configuration does not need to be initialized
689
if (LOG.isDebugEnabled()) {
690             LOG.debug(org.opencms.configuration.Messages.get().getBundle().key(
691                 org.opencms.configuration.Messages.LOG_INIT_CONFIGURATION_1,
692                 this));
693         }
694         setFrozen(true);
695     }
696
697     /**
698      * Returns <code>true</code> if this job is currently active in the scheduler.<p>
699      *
700      * @return <code>true</code> if this job is currently active in the scheduler
701      */

702     public boolean isActive() {
703
704         return m_active;
705     }
706
707     /**
708      * Returns true if the job instance class is reused for this job.<p>
709      *
710      * @return true if the job instance class is reused for this job
711      */

712     public boolean isReuseInstance() {
713
714         return m_reuseInstance;
715     }
716
717     /**
718      * Sets the active state of this job.<p>
719      *
720      * @param active the active state to set
721      */

722     public void setActive(boolean active) {
723
724         checkFrozen();
725         m_active = active;
726     }
727
728     /**
729      * Sets the name of the class to schedule.<p>
730      *
731      * @param className the class name to set
732      */

733     public void setClassName(String JavaDoc className) {
734
735         checkFrozen();
736         if (!CmsStringUtil.isValidJavaClassName(className)) {
737             throw new CmsIllegalArgumentException(
738                 Messages.get().container(Messages.ERR_BAD_JOB_CLASS_NAME_1, className));
739         }
740         Class JavaDoc jobClass;
741         try {
742             jobClass = Class.forName(className);
743         } catch (ClassNotFoundException JavaDoc e) {
744             throw new CmsIllegalArgumentException(Messages.get().container(
745                 Messages.ERR_JOB_CLASS_NOT_FOUND_1,
746                 className));
747         }
748         if (!I_CmsScheduledJob.class.isAssignableFrom(jobClass)) {
749             throw new CmsIllegalArgumentException(Messages.get().container(
750                 Messages.ERR_JOB_CLASS_BAD_INTERFACE_2,
751                 className,
752                 I_CmsScheduledJob.class.getName()));
753         }
754
755         m_className = className;
756         if (getJobName() == null) {
757             // initialize job name with class name as default
758
setJobName(className);
759         }
760     }
761
762     /**
763      * Sets the context information for the user executing the job.<p>
764      *
765      * This will also "freeze" the context information that is set.<p>
766      *
767      * @param contextInfo the context information for the user executing the job
768      *
769      * @see CmsContextInfo#freeze()
770      */

771     public void setContextInfo(CmsContextInfo contextInfo) {
772
773         checkFrozen();
774         if (contextInfo == null) {
775             throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_BAD_CONTEXT_INFO_0));
776         }
777         m_context = contextInfo;
778     }
779
780     /**
781      * Sets the cron expression for this job entry.<p>
782      *
783      * @param cronExpression the cron expression to set
784      */

785     public void setCronExpression(String JavaDoc cronExpression) {
786
787         checkFrozen();
788
789         try {
790             // check if the cron expression is valid
791
new CronTrigger().setCronExpression(cronExpression);
792         } catch (Exception JavaDoc e) {
793             throw new CmsIllegalArgumentException(Messages.get().container(
794                 Messages.ERR_BAD_CRON_EXPRESSION_2,
795                 getJobName(),
796                 cronExpression));
797         }
798
799         m_cronExpression = cronExpression;
800     }
801
802     /**
803      * Sets the job name.<p>
804      *
805      * @param jobName the job name to set
806      */

807     public void setJobName(String JavaDoc jobName) {
808
809         checkFrozen();
810         if (CmsStringUtil.isEmpty(jobName) || !jobName.trim().equals(jobName)) {
811             throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_BAD_JOB_NAME_1, jobName));
812
813         }
814         m_jobName = jobName;
815     }
816
817     /**
818      * Sets the job parameters.<p>
819      *
820      * @param parameters the parameters to set
821      */

822     public void setParameters(SortedMap JavaDoc parameters) {
823
824         checkFrozen();
825         if (parameters == null) {
826             throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_BAD_JOB_PARAMS_0));
827         }
828         // make sure the parameters are a sorted map
829
m_parameters = new TreeMap JavaDoc(parameters);
830     }
831
832     /**
833      * Controls if the job instance class is reused for this job,
834      * of if a new instance is generated every time the job is run.<p>
835      *
836      * @param reuseInstance must be true if the job instance class is to be reused
837      */

838     public void setReuseInstance(boolean reuseInstance) {
839
840         checkFrozen();
841         m_reuseInstance = reuseInstance;
842     }
843
844     /**
845      * Checks if this job info configuration is frozen.<p>
846      *
847      * @throws CmsRuntimeException in case the configuration is already frozen
848      */

849     protected void checkFrozen() throws CmsRuntimeException {
850
851         if (m_frozen) {
852             throw new CmsRuntimeException(Messages.get().container(Messages.ERR_JOB_INFO_FROZEN_1, getJobName()));
853         }
854     }
855
856     /**
857      * Returns the Quartz trigger used for scheduling this job.<p>
858      *
859      * This is an internal operation that should only by performed by the
860      * <code>{@link CmsScheduleManager}</code>, never by using this API directly.<p>
861      *
862      * @return the Quartz trigger used for scheduling this job
863      */

864     protected Trigger getTrigger() {
865
866         return m_trigger;
867     }
868
869     /**
870      * Sets the "frozen" state of this job.<p>
871      *
872      * This is an internal operation to be used only by the <code>{@link CmsScheduleManager}</code>.<p>
873      *
874      * @param frozen the "frozen" state to set
875      */

876     protected synchronized void setFrozen(boolean frozen) {
877
878         if (frozen && !m_frozen) {
879             // "freeze" the job configuration
880
m_parameters = Collections.unmodifiableSortedMap(m_parameters);
881             m_context.freeze();
882             m_frozen = true;
883         } else if (!frozen && m_frozen) {
884             // "unfreeze" the job configuration
885
m_parameters = new TreeMap JavaDoc(m_parameters);
886             m_frozen = false;
887         }
888     }
889
890     /**
891      * Sets the is used for scheduling this job.<p>
892      *
893      * This is an internal operation that should only by performed by the
894      * <code>{@link CmsScheduleManager}</code>, never by using this API directly.<p>
895      *
896      * @param id the id to set
897      */

898     protected void setId(String JavaDoc id) {
899
900         checkFrozen();
901         m_id = id;
902     }
903
904     /**
905      * Sets the Quartz trigger used for scheduling this job.<p>
906      *
907      * This is an internal operation that should only by performed by the
908      * <code>{@link CmsScheduleManager}</code>, never by using this API directly.<p>
909      *
910      * @param trigger the Quartz trigger to set
911      */

912     protected void setTrigger(Trigger trigger) {
913
914         checkFrozen();
915         m_trigger = trigger;
916     }
917 }
Popular Tags