1 package org.apache.turbine.services.schedule;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.sql.Connection;
58 import java.util.Calendar;
59 import java.util.Date;
60 import java.util.Hashtable;
61 import org.apache.torque.om.BaseObject;
62 import org.apache.torque.om.NumberKey;
63 import org.apache.torque.util.Criteria;
64
65 /***
66 * This is a wrapper for a scheduled job. It is modeled after the
67 * Unix scheduler cron.
68 *
69 * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
70 * @version $Id: JobEntry.java,v 1.8 2002/07/11 07:34:30 mpoeschl Exp $
71 */
72 public class JobEntry extends BaseObject
73 implements Comparable
74 {
75 /*** Valid entry ( 0-60 ). **/
76 private int second = -1;
77
78 /*** Valid entry ( 0-59 ). **/
79 private int minute = -1;
80
81 /*** Valid entry ( 0-23 ). **/
82 private int hour = -1;
83
84 /*** Valid entry ( 1-7 ). **/
85 private int weekday = -1;
86
87 /*** Valid entry ( 1-31 ). **/
88 private int day_of_month = -1;
89
90 /*** The Task to perform. **/
91 private String task = null;
92
93 /*** Next runtime. **/
94 private long runtime = 0;
95
96 /*** E-mail address to send notification of job run. **/
97 private String email = "";
98
99 /*** indicates if job is currently running */
100 private boolean jobIsActive = false;
101
102 /*** schedule types **/
103 private static final int SECOND = 0;
104 private static final int MINUTE = 1;
105 private static final int WEEK_DAY = 2;
106 private static final int DAY_OF_MONTH = 3;
107 private static final int DAILY = 4;
108
109 /*** Storage for additional properties */
110 private Hashtable jobProp = null;
111
112 /***
113 * Default Constructor
114 */
115 public JobEntry()
116 {
117 }
118
119 /***
120 * Constuctor.
121 *
122 * Schedule a job to run on a certain point of time.<br>
123 *
124 * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
125 * the month - <br>
126 *
127 * JobEntry je = new JobEntry(0,0,8,15,"DefaultScheduledJob");<br>
128 *
129 * Example 2: Run the DefaultScheduledJob at 8:00am every day -
130 * <br>
131 *
132 * JobEntry je = new JobEntry(0,0,8,-1,"DefaultScheduledJob");<br>
133 *
134 * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
135 *
136 * JobEntry je = new JobEntry(0,120,-1,-1,"DefaultScheduledJob");<br>
137 *
138 * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
139 *
140 * JobEntry je = new JobEntry(30,-1,-1,-1,"DefaultScheduledJob");<br>
141 *
142 * @param sec Value for entry "seconds".
143 * @param min Value for entry "minutes".
144 * @param hour Value for entry "hours".
145 * @param wd Value for entry "week days".
146 * @param day_mo Value for entry "month days".
147 * @param task Task to execute.
148 * @exception Exception, a generic exception.
149 */
150 public JobEntry(int sec,
151 int min,
152 int hour,
153 int wd,
154 int day_mo,
155 String task)
156 throws Exception
157 {
158 if ( task == null || task.length() == 0 )
159 throw new Exception("Error in JobEntry. Bad Job parameter. Task not set.");
160
161 this.second = sec;
162 this.minute = min;
163 this.hour = hour;
164 this.weekday = wd;
165 this.day_of_month = day_mo;
166 this.task = task;
167
168 calcRunTime();
169 }
170
171
172 /***
173 * Calculate how long before the next runtime.<br>
174 *
175 * The runtime determines it's position in the job queue.
176 * Here's the logic:<br>
177 *
178 * 1. Create a date the represents when this job is to run.<br>
179 *
180 * 2. If this date has expired, them "roll" appropriate date
181 * fields forward to the next date.<br>
182 *
183 * 3. Calculate the diff in time between the current time and the
184 * next run time.<br>
185 *
186 * @exception Exception, a generic exception.
187 */
188 public void calcRunTime()
189 throws Exception
190 {
191 Calendar schedrun = Calendar.getInstance();
192 Calendar now = Calendar.getInstance();
193
194 switch( evaluateJobType() )
195 {
196 case 0:
197 // SECOND (every so many seconds...)
198 schedrun.add (Calendar.SECOND,second);
199 runtime = schedrun.getTime().getTime();
200 break;
201 case 1:
202 // MINUTE (every so many minutes...)
203 schedrun.add (Calendar.SECOND,second);
204 schedrun.add(Calendar.MINUTE,minute);
205 runtime = schedrun.getTime().getTime();
206 break;
207
208 case 2:
209 // WEEKDAY (day of the week)
210 schedrun.add (Calendar.SECOND,second);
211 schedrun.set(Calendar.MINUTE,minute);
212 schedrun.set(Calendar.HOUR_OF_DAY,hour);
213 schedrun.set(Calendar.DAY_OF_WEEK,weekday);
214
215 if ( now.before(schedrun) )
216 {
217 // Scheduled time has NOT expired.
218 runtime = schedrun.getTime().getTime();
219 }
220 else
221 {
222 // Scheduled time has expired; roll to the next week.
223 schedrun.add(Calendar.DAY_OF_WEEK,7);
224 runtime = schedrun.getTime().getTime();
225 }
226 break;
227
228 case 3:
229 // DAY_OF_MONTH (date of the month)
230 schedrun.add (Calendar.SECOND,second);
231 schedrun.set(Calendar.MINUTE,minute);
232 schedrun.set(Calendar.HOUR_OF_DAY,hour);
233 schedrun.set(Calendar.DAY_OF_MONTH,day_of_month);
234
235 if ( now.before(schedrun) )
236 {
237 // Scheduled time has NOT expired.
238 runtime = schedrun.getTime().getTime();
239 }
240 else
241 {
242 // Scheduled time has expired; roll to the next month.
243 schedrun.add(Calendar.MONTH,1);
244 runtime = schedrun.getTime().getTime();
245 }
246 break;
247
248 case 4:
249 // DAILY (certain hour:minutes of the day)
250 schedrun.add (Calendar.SECOND,second);
251 schedrun.set(Calendar.MINUTE,minute);
252 schedrun.set(Calendar.HOUR_OF_DAY,hour);
253
254 // Scheduled time has NOT expired.
255 if ( now.before(schedrun) )
256 {
257 runtime = schedrun.getTime().getTime();
258 }
259 else
260 {
261 // Scheduled time has expired; roll forward 24 hours.
262 schedrun.add(Calendar.HOUR_OF_DAY,24);
263 runtime = schedrun.getTime().getTime();
264 }
265 break;
266
267 default:
268 // Do nothing.
269 }
270 }
271
272 /***
273 * Get the next runtime for this job as a long.
274 *
275 * @return The next run time as a long.
276 */
277 public long getNextRuntime()
278 {
279 return runtime;
280 }
281
282 /***
283 * Get the next runtime for this job as a String.
284 *
285 * @return The next run time as a String.
286 */
287 public String getNextRunAsString()
288 {
289 return new Date(runtime).toString();
290 }
291
292 /***
293 * The address to send mail notifications to. This just holds the
294 * address. The ScheduledJob should handle actually sending the
295 * mail.
296 *
297 * @param mail The email address.
298 */
299 public void setEmail(String mail)
300 {
301 this.email = mail;
302 setModified(true);
303 }
304
305 /***
306 * Return the e-mail address for notification.
307 *
308 * @return The email address.
309 */
310 public String getEmail()
311 {
312 if ( email == null || email.length() == 0 )
313 {
314 return "not set";
315 }
316 else
317 {
318 return email;
319 }
320 }
321
322 /***
323 * Return the task for this job. A task name is the Class name of
324 * the ScheduledJob created by the programmer.
325 *
326 * @return A String with the name of the scheduled job.
327 */
328 public String getTask()
329 {
330 return task;
331 }
332
333 /***
334 * Set the task name for this job. A task name is the Class name
335 * of the ScheduledJob created by the programmer.
336 *
337 * @param task A String with the name of the job.
338 */
339 public void setTask(String task)
340 {
341 this.task = task;
342 setModified(true);
343 }
344
345 /***
346 * Get the value of second.
347 *
348 * @return Value of second.
349 */
350 public int getSecond()
351 {
352 return second;
353 }
354
355 /***
356 * Set the value of second.
357 *
358 * @param v Value to assign to second.
359 */
360 public void setSecond(int v)
361 {
362 this.second = v;
363 setModified(true);
364 }
365
366
367 /***
368 * Get the value of minute.
369 *
370 * @return Value of minute.
371 */
372 public int getMinute()
373 {
374 return minute;
375 }
376
377 /***
378 * Set the value of minute.
379 *
380 * @param v Value to assign to minute.
381 */
382 public void setMinute(int v)
383 {
384 this.minute = v;
385 setModified(true);
386 }
387
388 /***
389 * Get the value of hour.
390 *
391 * @return Value of hour.
392 */
393 public int getHour()
394 {
395 return hour;
396 }
397
398 /***
399 * Set the value of hour.
400 *
401 * @param v Value to assign to hour.
402 */
403 public void setHour(int v)
404 {
405 this.hour = v;
406 setModified(true);
407 }
408
409 /***
410 * Get the value of weekday.
411 *
412 * @return Value of weekday.
413 */
414 public int getWeekday()
415 {
416 return weekday;
417 }
418
419 /***
420 * Set the value of weekday.
421 *
422 * @param v Value to assign to weekday.
423 */
424 public void setWeekday(int v)
425 {
426 this.weekday = v;
427 setModified(true);
428 }
429
430 /***
431 * Get the value of day_of_month.
432 *
433 * @return Value of day_of_month.
434 */
435 public int getDay_of_month()
436 {
437 return day_of_month;
438 }
439
440 /***
441 * Set the value of day_of_month.
442 *
443 * @param v Value to assign to day_of_month.
444 */
445 public void setDay_of_month(int v)
446 {
447 this.day_of_month = v;
448 setModified(true);
449 }
450
451 /***
452 * Self-preservation.
453 *
454 * @exception Exception, a generic exception.
455 */
456 public void save()
457 throws Exception
458 {
459 Criteria criteria = new Criteria(9)
460 .add(JobEntryPeer.SECOND, getSecond())
461 .add(JobEntryPeer.MINUTE, getMinute())
462 .add(JobEntryPeer.HOUR, getHour())
463 .add(JobEntryPeer.WEEKDAY, getWeekday())
464 .add(JobEntryPeer.DAY_OF_MONTH, getDay_of_month())
465 .add(JobEntryPeer.TASK, getTask())
466 .add(JobEntryPeer.EMAIL, getEmail())
467 .add(JobEntryPeer.PROPERTY, getProperty());
468
469 NumberKey nk = (NumberKey)getPrimaryKey();
470 long key = 0;
471 if (nk != null)
472 {
473 key = ((NumberKey)getPrimaryKey()).getBigDecimal().longValue();
474 }
475 if ( isModified() && key > 0)
476 {
477 // This is an update.
478 criteria.add(JobEntryPeer.OID, getPrimaryKey());
479 JobEntryPeer.doUpdate(criteria);
480 setModified(false);
481 }
482 else
483 {
484 setPrimaryKey( JobEntryPeer.doInsert(criteria) );
485 }
486 }
487
488 /***
489 * not implemented
490 *
491 * @param conn
492 * @throws Exception
493 */
494 public void save(Connection conn) throws Exception
495 {
496 throw new Exception("not implemented");
497 }
498
499 /***
500 * not implemented
501 *
502 * @param dbname
503 * @throws Exception
504 */
505 public void save(String dbname) throws Exception
506 {
507 throw new Exception("not implemented");
508 }
509
510
511 /***
512 * What schedule am I on?
513 *
514 * I know this is kinda ugly! If you can think of a cleaner way
515 * to do this, please jump in!
516 *
517 * @return A number specifying the type of schedule. See
518 * calcRunTime().
519 * @exception Exception, a generic exception.
520 */
521 private int evaluateJobType()
522 throws Exception
523 {
524
525 // First start by checking if it's a day of the month job.
526 if ( day_of_month < 0 )
527 {
528 // Not a day of the month job... check weekday.
529 if ( weekday < 0 )
530 {
531 // Not a weekday job...check if by the hour.
532 if ( hour < 0 )
533 {
534 // Not an hourly job...check if it is by the minute
535 if ( minute < 0 )
536 {
537 // Not a by the minute job so must be by the second
538 if ( second < 0)
539 throw new Exception("Error in JobEntry. Bad Job parameter.");
540
541 return SECOND;
542 }
543 else
544 {
545 // Must be a job run by the minute so we need minutes and
546 // seconds.
547 if ( minute < 0 || second < 0 )
548 throw new Exception("Error in JobEntry. Bad Job parameter.");
549
550 return MINUTE;
551 }
552 }
553 else
554 {
555 // Must be a daily job by hours minutes, and seconds. In
556 // this case, we need the minute, second, and hour params.
557 if ( minute < 0 || hour < 0 || second < 0)
558 throw new Exception("Error in JobEntry. Bad Job parameter.");
559
560 return DAILY;
561 }
562 }
563 else
564 {
565 // Must be a weekday job. In this case, we need
566 // minute, second, and hour params
567 if ( minute < 0 || hour < 0 || second < 0 )
568 throw new Exception("Error in JobEntry. Bad Job parameter.");
569
570 return WEEK_DAY;
571 }
572 }
573 else
574 {
575 // Must be a day of the month job. In this case, we need
576 // minute, second, and hour params
577 if ( minute < 0 || hour < 0 )
578 throw new Exception("Error in JobEntry. Bad Job parameter.");
579
580 return DAY_OF_MONTH;
581 }
582 }
583
584 /***
585 * Used for ordering Jobentries
586 * Note: this comparator imposes orderings that are inconsistent with
587 * equals.
588 *
589 * @param je The first <code>JobEntry</code> object.
590 * @return An <code>int</code> indicating the result of the comparison.
591 */
592 public int compareTo(Object je)
593 {
594 long obj1Time = this.getNextRuntime();
595 long obj2Time = ((JobEntry)je).getNextRuntime();
596 if (obj1Time > obj2Time)
597 {
598 return 1;
599 }
600 else if (obj1Time < obj2Time)
601 {
602 return -1;
603 }
604 else
605 {
606 return 0;
607 }
608 }
609
610 /***
611 * Compare this Job with another.
612 *
613 * @param je The JobEntry object to compare to.
614 * @return True if they're the same.
615 */
616 public boolean equals(Object je)
617 {
618 if ( !( je instanceof JobEntry ) )
619 return false;
620
621 return ( ((JobEntry)je).getPrimaryKey().equals(this.getPrimaryKey()) );
622 }
623
624 /***
625 * Sets whether the job is running.
626 *
627 * @param isActive Whether the job is running.
628 */
629 public void setActive(boolean isActive)
630 {
631 jobIsActive = isActive;
632 }
633
634 /***
635 * Check to see if job is currently active/running
636 *
637 * @return true if job is currently geing run by the
638 * workerthread, otherwise false
639 */
640 public boolean isActive()
641 {
642 return jobIsActive;
643 }
644
645 /***
646 * Set job properties
647 *
648 */
649 public void setProperty(Hashtable prop)
650 {
651 jobProp = prop;
652 setModified(true);
653 }
654
655 /***
656 * Get extra job properties
657 *
658 */
659 public Hashtable getProperty()
660 {
661 if ( jobProp == null )
662 {
663 return new Hashtable(89);
664 }
665 else
666 {
667 return jobProp;
668 }
669 }
670 }
This page was automatically generated by Maven