View Javadoc

1   package org.apache.turbine.services.schedule;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Calendar;
23  import java.util.Date;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.turbine.util.TurbineException;
29  
30  /**
31   * This class provides the basic implementation of common features for a scheduled job entry.
32   *
33   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
34   */
35  public abstract class AbstractJobEntry implements JobEntry
36  {
37      /** Logging */
38      protected static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME);
39  
40      /** indicates if job is currently running */
41      private boolean jobIsActive = false;
42  
43      /** Next runtime. **/
44      private long runtime = 0;
45  
46      /** schedule types **/
47      protected enum ScheduleType {
48          SECOND,
49          MINUTE,
50          WEEK_DAY,
51          DAY_OF_MONTH,
52          DAILY
53      }
54  
55      /**
56       * Default constructor
57       */
58      public AbstractJobEntry()
59      {
60          super();
61      }
62  
63      /**
64       * Constructor.
65       *
66       * Schedule a job to run on a certain point of time.<br>
67       *
68       * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
69       * the month - <br>
70       *
71       * JobEntry je = new JobEntry(0,0,8,-1,15,"DefaultScheduledJob");<br>
72       *
73       * Example 2: Run the DefaultScheduledJob at 8:00am every day -
74       * <br>
75       *
76       * JobEntry je = new JobEntry(0,0,8,-1,-1,"DefaultScheduledJob");<br>
77       *
78       * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
79       *
80       * JobEntry je = new JobEntry(0,120,-1,-1,-1,"DefaultScheduledJob");<br>
81       *
82       * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
83       *
84       * JobEntry je = new JobEntry(30,-1,-1,-1,-1,"DefaultScheduledJob");<br>
85       *
86       * @param sec Value for entry "seconds".
87       * @param min Value for entry "minutes".
88       * @param hour Value for entry "hours".
89       * @param wd Value for entry "week days".
90       * @param day_mo Value for entry "month days".
91       * @param task Task to execute.
92       * @exception TurbineException a generic exception.
93       */
94      public AbstractJobEntry(int sec,
95                      int min,
96                      int hour,
97                      int wd,
98                      int day_mo,
99                      String task)
100             throws TurbineException
101     {
102         this();
103 
104         if (StringUtils.isEmpty(task))
105         {
106             throw new TurbineException("Error in JobEntry. " +
107                     "Bad Job parameter. Task not set.");
108         }
109 
110         setSecond(sec);
111         setMinute(min);
112         setHour(hour);
113         setWeekDay(wd);
114         setDayOfMonth(day_mo);
115         setTask(task);
116 
117         calcRunTime();
118     }
119 
120     /**
121      * Used for ordering Jobentries
122      * Note: this comparator imposes orderings that are inconsistent with
123      * equals.
124      *
125      * @param je The first <code>JobEntry</code> object.
126      * @return An <code>int</code> indicating the result of the comparison.
127      */
128     @Override
129     public int compareTo(JobEntry je)
130     {
131         return getJobId() - je.getJobId();
132     }
133 
134     /**
135      * Sets whether the job is running.
136      *
137      * @param isActive Whether the job is running.
138      */
139     @Override
140     public void setActive(boolean isActive)
141     {
142         jobIsActive = isActive;
143     }
144 
145     /**
146      * Check to see if job is currently active/running
147      *
148      * @return true if job is currently queuing run by the
149      *  worker thread, otherwise false
150      */
151     @Override
152     public boolean isActive()
153     {
154         return jobIsActive;
155     }
156 
157     /**
158      * Get the next runtime for this job as a long.
159      *
160      * @return The next run time as a long.
161      */
162     @Override
163     public long getNextRuntime()
164     {
165         return runtime;
166     }
167 
168     /**
169      * Gets the next runtime as a date
170      *
171      * @return Next run date
172      */
173     @Override
174     public Date getNextRunDate()
175     {
176         return new Date(runtime);
177     }
178 
179     /**
180      * Get the next runtime for this job as a String.
181      *
182      * @return The next run time as a String.
183      */
184     @Override
185     public String getNextRunAsString()
186     {
187         return getNextRunDate().toString();
188     }
189 
190     /**
191      * Calculate how long before the next runtime.<br>
192      *
193      * The runtime determines it's position in the job queue.
194      * Here's the logic:<br>
195      *
196      * 1. Create a date the represents when this job is to run.<br>
197      *
198      * 2. If this date has expired, them "roll" appropriate date
199      * fields forward to the next date.<br>
200      *
201      * 3. Calculate the diff in time between the current time and the
202      * next run time.<br>
203      *
204      * @exception TurbineException a generic exception.
205      */
206     @Override
207     public void calcRunTime()
208             throws TurbineException
209     {
210         Calendar schedrun = Calendar.getInstance();
211         Calendar now = Calendar.getInstance();
212 
213         switch (evaluateJobType())
214         {
215             case SECOND:
216                 // SECOND (every so many seconds...)
217                 schedrun.add(Calendar.SECOND, getSecond());
218                 runtime = schedrun.getTime().getTime();
219                 break;
220 
221             case MINUTE:
222                 // MINUTE (every so many minutes...)
223                 schedrun.add(Calendar.SECOND, getSecond());
224                 schedrun.add(Calendar.MINUTE, getMinute());
225                 runtime = schedrun.getTime().getTime();
226                 break;
227 
228             case WEEK_DAY:
229                 // WEEKDAY (day of the week)
230                 schedrun.set(Calendar.SECOND, getSecond());
231                 schedrun.set(Calendar.MINUTE, getMinute());
232                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
233                 schedrun.set(Calendar.DAY_OF_WEEK, getWeekDay());
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 week.
243                     schedrun.add(Calendar.DAY_OF_WEEK, 7);
244                     runtime = schedrun.getTime().getTime();
245                 }
246                 break;
247 
248             case DAY_OF_MONTH:
249                 // DAY_OF_MONTH (date of the month)
250                 schedrun.set(Calendar.SECOND, getSecond());
251                 schedrun.set(Calendar.MINUTE, getMinute());
252                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
253                 schedrun.set(Calendar.DAY_OF_MONTH, getDayOfMonth());
254 
255                 if (now.before(schedrun))
256                 {
257                     // Scheduled time has NOT expired.
258                     runtime = schedrun.getTime().getTime();
259                 }
260                 else
261                 {
262                     // Scheduled time has expired; roll to the next month.
263                     schedrun.add(Calendar.MONTH, 1);
264                     runtime = schedrun.getTime().getTime();
265                 }
266                 break;
267 
268             case DAILY:
269                 // DAILY (certain hour:minutes of the day)
270                 schedrun.set(Calendar.SECOND, getSecond());
271                 schedrun.set(Calendar.MINUTE, getMinute());
272                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
273 
274                 // Scheduled time has NOT expired.
275                 if (now.before(schedrun))
276                 {
277                     runtime = schedrun.getTime().getTime();
278                 }
279                 else
280                 {
281                     // Scheduled time has expired; roll forward 24 hours.
282                     schedrun.add(Calendar.HOUR_OF_DAY, 24);
283                     runtime = schedrun.getTime().getTime();
284                 }
285                 break;
286 
287             default:
288                 // Do nothing.
289         }
290 
291         log.info("Next runtime for task " + this.getTask() + " is " + this.getNextRunDate());
292     }
293 
294     /**
295      * What schedule am I on?
296      *
297      * I know this is kinda ugly!  If you can think of a cleaner way
298      * to do this, please jump in!
299      *
300      * @return A number specifying the type of schedule. See
301      * calcRunTime().
302      * @exception TurbineException a generic exception.
303      */
304     private ScheduleType evaluateJobType()
305             throws TurbineException
306     {
307 
308         // First start by checking if it's a day of the month job.
309         if (getDayOfMonth() < 0)
310         {
311             // Not a day of the month job... check weekday.
312             if (getWeekDay() < 0)
313             {
314                 // Not a weekday job...check if by the hour.
315                 if (getHour() < 0)
316                 {
317                     // Not an hourly job...check if it is by the minute
318                     if (getMinute() < 0)
319                     {
320                         // Not a by the minute job so must be by the second
321                         if (getSecond() < 0)
322                         {
323                             throw new TurbineException("Error in JobEntry. Bad Job parameter.");
324                         }
325 
326                         return ScheduleType.SECOND;
327                     }
328                     else
329                     {
330                         // Must be a job run by the minute so we need minutes and
331                         // seconds.
332                         if (getMinute() < 0 || getSecond() < 0)
333                         {
334                             throw new TurbineException("Error in JobEntry. Bad Job parameter.");
335                         }
336 
337                         return ScheduleType.MINUTE;
338                     }
339                 }
340                 else
341                 {
342                     // Must be a daily job by hours minutes, and seconds.  In
343                     // this case, we need the minute, second, and hour params.
344                     if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
345                     {
346                         throw new TurbineException("Error in JobEntry. Bad Job parameter.");
347                     }
348 
349                     return ScheduleType.DAILY;
350                 }
351             }
352             else
353             {
354                 // Must be a weekday job.  In this case, we need
355                 // minute, second, and hour params
356                 if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
357                 {
358                     throw new TurbineException("Error in JobEntry. Bad Job parameter.");
359                 }
360 
361                 return ScheduleType.WEEK_DAY;
362             }
363         }
364         else
365         {
366             // Must be a day of the month job.  In this case, we need
367             // minute, second, and hour params
368             if (getMinute() < 0 || getHour() < 0)
369             {
370                 throw new TurbineException("Error in JobEntry. Bad Job parameter.");
371             }
372 
373             return ScheduleType.DAY_OF_MONTH;
374         }
375     }
376 
377     /**
378      * Get the value of jobId.
379      *
380      * @return int
381      */
382     @Override
383     public abstract int getJobId();
384 
385     /**
386      * Set the value of jobId.
387      *
388      * @param v new value
389      */
390     @Override
391     public abstract void setJobId(int v);
392 
393     /**
394      * Get the value of second.
395      *
396      * @return int
397      */
398     public abstract int getSecond();
399 
400     /**
401      * Set the value of second.
402      *
403      * @param v new value
404      */
405     public abstract void setSecond(int v);
406 
407     /**
408      * Get the value of minute.
409      *
410      * @return int
411      */
412     public abstract int getMinute();
413 
414     /**
415      * Set the value of minute.
416      *
417      * @param v new value
418      */
419     public abstract void setMinute(int v);
420 
421     /**
422      * Get the value of hour.
423      *
424      * @return int
425      */
426     public abstract int getHour();
427 
428     /**
429      * Set the value of hour.
430      *
431      * @param v new value
432      */
433     public abstract void setHour(int v);
434 
435     /**
436      * Get the value of weekDay.
437      *
438      * @return int
439      */
440     public abstract int getWeekDay();
441 
442     /**
443      * Set the value of weekDay.
444      *
445      * @param v new value
446      */
447     public abstract void setWeekDay(int v);
448 
449     /**
450      * Get the value of dayOfMonth.
451      *
452      * @return int
453      */
454     public abstract int getDayOfMonth();
455 
456     /**
457      * Set the value of dayOfMonth.
458      *
459      * @param v new value
460      */
461     public abstract void setDayOfMonth(int v);
462 
463     /**
464      * Get the value of task.
465      *
466      * @return String
467      */
468     @Override
469     public abstract String getTask();
470 
471     /**
472      * Set the value of task.
473      *
474      * @param v new value
475      */
476     @Override
477     public abstract void setTask(String v);
478 }