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  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  import org.apache.turbine.util.TurbineException;
31  
32  /***
33   * This is a wrapper for a scheduled job.  It is modeled after the
34   * Unix scheduler cron.  Note: BaseJobEntry is generated by Torque
35   * at compile time, and is therefore NOT in CVS.
36   *
37   * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
38   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
39   * @version $Id: JobEntry.java 534527 2007-05-02 16:10:59Z tv $
40   */
41  public class JobEntry
42          extends BaseJobEntry
43          implements Comparable
44  {
45      /*** Logging */
46      private static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME);
47  
48      /*** indicates if job is currently running */
49      private boolean jobIsActive = false;
50  
51      /*** Next runtime. **/
52      private long runtime = 0;
53  
54      /*** schedule types **/
55      private static final int SECOND = 0;
56      private static final int MINUTE = 1;
57      private static final int WEEK_DAY = 2;
58      private static final int DAY_OF_MONTH = 3;
59      private static final int DAILY = 4;
60  
61      /***
62       * default constructor
63       */
64      public JobEntry()
65      {
66      }
67  
68      /***
69       * Constuctor.
70       *
71       * Schedule a job to run on a certain point of time.<br>
72       *
73       * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
74       * the month - <br>
75       *
76       * JobEntry je = new JobEntry(0,0,8,15,"DefaultScheduledJob");<br>
77       *
78       * Example 2: Run the DefaultScheduledJob at 8:00am every day -
79       * <br>
80       *
81       * JobEntry je = new JobEntry(0,0,8,-1,"DefaultScheduledJob");<br>
82       *
83       * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
84       *
85       * JobEntry je = new JobEntry(0,120,-1,-1,"DefaultScheduledJob");<br>
86       *
87       * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
88       *
89       * JobEntry je = new JobEntry(30,-1,-1,-1,"DefaultScheduledJob");<br>
90       *
91       * @param sec Value for entry "seconds".
92       * @param min Value for entry "minutes".
93       * @param hour Value for entry "hours".
94       * @param wd Value for entry "week days".
95       * @param day_mo Value for entry "month days".
96       * @param task Task to execute.
97       * @exception TurbineException a generic exception.
98       */
99      public JobEntry(int sec,
100                     int min,
101                     int hour,
102                     int wd,
103                     int day_mo,
104                     String task)
105             throws TurbineException
106     {
107         if (StringUtils.isEmpty(task))
108         {
109             throw new TurbineException("Error in JobEntry. " +
110                     "Bad Job parameter. Task not set.");
111         }
112 
113         setSecond(sec);
114         setMinute(min);
115         setHour(hour);
116         setWeekDay(wd);
117         setDayOfMonth(day_mo);
118         setTask(task);
119 
120         calcRunTime();
121     }
122 
123     /***
124      * Used for ordering Jobentries
125      * Note: this comparator imposes orderings that are inconsistent with
126      * equals.
127      *
128      * @param je The first <code>JobEntry</code> object.
129      * @return An <code>int</code> indicating the result of the comparison.
130      */
131     public int compareTo(Object je)
132     {
133         int result = -1;
134         if (je instanceof JobEntry)
135         {
136             result = getJobId() - ((JobEntry) je).getJobId();
137         }
138         return result;
139     }
140 
141     /***
142      * Sets whether the job is running.
143      *
144      * @param isActive Whether the job is running.
145      */
146     public void setActive(boolean isActive)
147     {
148         jobIsActive = isActive;
149     }
150 
151     /***
152      * Check to see if job is currently active/running
153      *
154      * @return true if job is currently geing run by the
155      *  workerthread, otherwise false
156      */
157     public boolean isActive()
158     {
159         return jobIsActive;
160     }
161 
162     /***
163      * Get the next runtime for this job as a long.
164      *
165      * @return The next run time as a long.
166      */
167     public long getNextRuntime()
168     {
169         return runtime;
170     }
171 
172     /***
173      * Gets the next runtime as a date
174      *
175      * @return Next run date
176      */
177     public Date getNextRunDate()
178     {
179         return new Date(runtime);
180     }
181 
182     /***
183      * Get the next runtime for this job as a String.
184      *
185      * @return The next run time as a String.
186      */
187     public String getNextRunAsString()
188     {
189         return getNextRunDate().toString();
190     }
191 
192     /***
193      * Calculate how long before the next runtime.<br>
194      *
195      * The runtime determines it's position in the job queue.
196      * Here's the logic:<br>
197      *
198      * 1. Create a date the represents when this job is to run.<br>
199      *
200      * 2. If this date has expired, them "roll" appropriate date
201      * fields forward to the next date.<br>
202      *
203      * 3. Calculate the diff in time between the current time and the
204      * next run time.<br>
205      *
206      * @exception TurbineException a generic exception.
207      */
208     public void calcRunTime()
209             throws TurbineException
210     {
211         Calendar schedrun = Calendar.getInstance();
212         Calendar now = Calendar.getInstance();
213 
214         switch (evaluateJobType())
215         {
216             case SECOND:
217                 // SECOND (every so many seconds...)
218                 schedrun.add(Calendar.SECOND, getSecond());
219                 runtime = schedrun.getTime().getTime();
220                 break;
221 
222             case MINUTE:
223                 // MINUTE (every so many minutes...)
224                 schedrun.add(Calendar.SECOND, getSecond());
225                 schedrun.add(Calendar.MINUTE, getMinute());
226                 runtime = schedrun.getTime().getTime();
227                 break;
228 
229             case WEEK_DAY:
230                 // WEEKDAY (day of the week)
231                 schedrun.set(Calendar.SECOND, getSecond());
232                 schedrun.set(Calendar.MINUTE, getMinute());
233                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
234                 schedrun.set(Calendar.DAY_OF_WEEK, getWeekDay());
235 
236                 if (now.before(schedrun))
237                 {
238                     // Scheduled time has NOT expired.
239                     runtime = schedrun.getTime().getTime();
240                 }
241                 else
242                 {
243                     // Scheduled time has expired; roll to the next week.
244                     schedrun.add(Calendar.DAY_OF_WEEK, 7);
245                     runtime = schedrun.getTime().getTime();
246                 }
247                 break;
248 
249             case DAY_OF_MONTH:
250                 // DAY_OF_MONTH (date of the month)
251                 schedrun.set(Calendar.SECOND, getSecond());
252                 schedrun.set(Calendar.MINUTE, getMinute());
253                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
254                 schedrun.set(Calendar.DAY_OF_MONTH, getDayOfMonth());
255 
256                 if (now.before(schedrun))
257                 {
258                     // Scheduled time has NOT expired.
259                     runtime = schedrun.getTime().getTime();
260                 }
261                 else
262                 {
263                     // Scheduled time has expired; roll to the next month.
264                     schedrun.add(Calendar.MONTH, 1);
265                     runtime = schedrun.getTime().getTime();
266                 }
267                 break;
268 
269             case DAILY:
270                 // DAILY (certain hour:minutes of the day)
271                 schedrun.set(Calendar.SECOND, getSecond());
272                 schedrun.set(Calendar.MINUTE, getMinute());
273                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
274 
275                 // Scheduled time has NOT expired.
276                 if (now.before(schedrun))
277                 {
278                     runtime = schedrun.getTime().getTime();
279                 }
280                 else
281                 {
282                     // Scheduled time has expired; roll forward 24 hours.
283                     schedrun.add(Calendar.HOUR_OF_DAY, 24);
284                     runtime = schedrun.getTime().getTime();
285                 }
286                 break;
287 
288             default:
289                 // Do nothing.
290         }
291 
292         log.info("Next runtime for task " + this.getTask() + " is " + this.getNextRunDate());
293     }
294 
295     /***
296      * What schedule am I on?
297      *
298      * I know this is kinda ugly!  If you can think of a cleaner way
299      * to do this, please jump in!
300      *
301      * @return A number specifying the type of schedule. See
302      * calcRunTime().
303      * @exception TurbineException a generic exception.
304      */
305     private int evaluateJobType()
306             throws TurbineException
307     {
308 
309         // First start by checking if it's a day of the month job.
310         if (getDayOfMonth() < 0)
311         {
312             // Not a day of the month job... check weekday.
313             if (getWeekDay() < 0)
314             {
315                 // Not a weekday job...check if by the hour.
316                 if (getHour() < 0)
317                 {
318                     // Not an hourly job...check if it is by the minute
319                     if (getMinute() < 0)
320                     {
321                         // Not a by the minute job so must be by the second
322                         if (getSecond() < 0)
323                             throw new TurbineException("Error in JobEntry. Bad Job parameter.");
324 
325                         return SECOND;
326                     }
327                     else
328                     {
329                         // Must be a job run by the minute so we need minutes and
330                         // seconds.
331                         if (getMinute() < 0 || getSecond() < 0)
332                             throw new TurbineException("Error in JobEntry. Bad Job parameter.");
333 
334                         return MINUTE;
335                     }
336                 }
337                 else
338                 {
339                     // Must be a daily job by hours minutes, and seconds.  In
340                     // this case, we need the minute, second, and hour params.
341                     if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
342                         throw new TurbineException("Error in JobEntry. Bad Job parameter.");
343 
344                     return DAILY;
345                 }
346             }
347             else
348             {
349                 // Must be a weekday job.  In this case, we need
350                 // minute, second, and hour params
351                 if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
352                     throw new TurbineException("Error in JobEntry. Bad Job parameter.");
353 
354                 return WEEK_DAY;
355             }
356         }
357         else
358         {
359             // Must be a day of the month job.  In this case, we need
360             // minute, second, and hour params
361             if (getMinute() < 0 || getHour() < 0)
362                 throw new TurbineException("Error in JobEntry. Bad Job parameter.");
363 
364             return DAY_OF_MONTH;
365         }
366     }
367 
368 }