View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.scheduler;
18  
19  import java.util.Calendar;
20  import java.lang.Comparable;
21  import java.util.Date;
22  
23  /***
24   * This is a wrapper for a scheduled job.  It is modeled after the
25   * Unix scheduler cron.
26   *
27   * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
28   * @version $Id: JobEntry.java 516448 2007-03-09 16:25:47Z ate $
29   */
30  public class JobEntry
31      extends BaseJobEntry
32      implements Comparable
33  {
34  
35      /*** indicates if job is currently running */
36      private boolean jobIsActive = false;
37  
38      /*** Next runtime. **/
39      private long runtime = 0;
40  
41      /*** schedule types **/
42      private static final int SECOND = 0;
43      private static final int MINUTE = 1;
44      private static final int WEEK_DAY = 2;
45      private static final int DAY_OF_MONTH = 3;
46      private static final int DAILY = 4;
47  
48  
49      /***
50       * default constructor
51       */
52      public JobEntry()
53      {
54      }
55  
56      /***
57       * Constuctor.
58       *
59       * Schedule a job to run on a certain point of time.<br>
60       *
61       * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
62       * the month - <br>
63       *
64       * JobEntry je = new JobEntry(0,0,8,15,"DefaultScheduledJob");<br>
65       *
66       * Example 2: Run the DefaultScheduledJob at 8:00am every day -
67       * <br>
68       *
69       * JobEntry je = new JobEntry(0,0,8,-1,"DefaultScheduledJob");<br>
70       *
71       * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
72       *
73       * JobEntry je = new JobEntry(0,120,-1,-1,"DefaultScheduledJob");<br>
74       *
75       * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
76       *
77       * JobEntry je = new JobEntry(30,-1,-1,-1,"DefaultScheduledJob");<br>
78       *
79       * @param sec Value for entry "seconds".
80       * @param min Value for entry "minutes".
81       * @param hour Value for entry "hours".
82       * @param wd Value for entry "week days".
83       * @param day_mo Value for entry "month days".
84       * @param task Task to execute.
85       * @exception Exception, a generic exception.
86       */
87      public JobEntry(int sec,
88                      int min,
89                      int hour,
90                      int wd,
91                      int day_mo,
92                      String task)
93          throws Exception
94      {
95          if ( task == null || task.length() == 0 )
96          {
97              throw new Exception("Error in JobEntry. " + 
98                  "Bad Job parameter. Task not set.");
99          }
100         
101         setSecond(sec);
102         setMinute(min);
103         setHour(hour);
104         setWeekDay(wd);
105         setDayOfMonth(day_mo);
106         setTask(task);
107 
108         calcRunTime();
109     }
110 
111     /***
112      * Compares one JobEntry to another JobEntry based on the JobId
113      */
114     public int compareTo(Object je)
115     {
116         int result = -1;
117         if (je instanceof JobEntry)
118         {
119             if (jobId == ((JobEntry)je).getJobId())
120             {
121                 return 0;
122             }
123             else
124             {
125                 if (jobId > ((JobEntry)je).getJobId())
126                 {
127                     return 1;
128                 }
129             }
130             
131         }
132         return result;
133     }
134 
135     /***
136      * Sets whether the job is running.
137      *
138      * @param isActive Whether the job is running.
139      */
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 geing run by the
149      *  workerthread, otherwise false
150      */
151      public boolean isActive()
152      {
153         return jobIsActive;
154      }
155 
156     /***
157      * Get the next runtime for this job as a long.
158      *
159      * @return The next run time as a long.
160      */
161     public long getNextRuntime()
162     {
163         return runtime;
164     }
165 
166     /***
167      * Get the next runtime for this job as a String.
168      *
169      * @return The next run time as a String.
170      */
171     public String getNextRunAsString()
172     {
173         return new Date(runtime).toString();
174     }
175 
176     /***
177      * Calculate how long before the next runtime.<br>
178      *
179      * The runtime determines it's position in the job queue.
180      * Here's the logic:<br>
181      *
182      * 1. Create a date the represents when this job is to run.<br>
183      *
184      * 2. If this date has expired, them "roll" appropriate date
185      * fields forward to the next date.<br>
186      *
187      * 3. Calculate the diff in time between the current time and the
188      * next run time.<br>
189      *
190      * @exception Exception, a generic exception.
191      */
192     public void calcRunTime()
193         throws Exception
194     {
195         Calendar schedrun = Calendar.getInstance();
196         Calendar now = Calendar.getInstance();
197  
198         switch( evaluateJobType() )
199         {
200         case SECOND:
201             // SECOND (every so many seconds...)
202             schedrun.add(Calendar.SECOND, getSecond());
203             runtime = schedrun.getTime().getTime();
204             break;
205 
206         case MINUTE:
207             // MINUTE (every so many minutes...)
208             schedrun.add(Calendar.SECOND, getSecond());
209             schedrun.add(Calendar.MINUTE, getMinute());
210             runtime = schedrun.getTime().getTime();
211             break;
212 
213         case WEEK_DAY:
214             // WEEKDAY (day of the week)
215             schedrun.set(Calendar.SECOND, getSecond());
216             schedrun.set(Calendar.MINUTE, getMinute());
217             schedrun.set(Calendar.HOUR_OF_DAY, getHour());
218             schedrun.set(Calendar.DAY_OF_WEEK, getWeekDay());
219 
220             if ( now.before(schedrun) )
221             {
222                 // Scheduled time has NOT expired.
223                 runtime = schedrun.getTime().getTime();
224             }
225             else
226             {
227                 // Scheduled time has expired; roll to the next week.
228                 schedrun.add(Calendar.DAY_OF_WEEK,7);
229                 runtime = schedrun.getTime().getTime();
230             }
231             break;
232 
233         case DAY_OF_MONTH:
234             // DAY_OF_MONTH (date of the month)
235             schedrun.set(Calendar.SECOND, getSecond());
236             schedrun.set(Calendar.MINUTE, getMinute());
237             schedrun.set(Calendar.HOUR_OF_DAY, getHour());
238             schedrun.set(Calendar.DAY_OF_MONTH, getDayOfMonth());
239 
240             if ( now.before(schedrun) )
241             {
242                 // Scheduled time has NOT expired.
243                 runtime = schedrun.getTime().getTime();
244             }
245             else
246             {
247                 // Scheduled time has expired; roll to the next month.
248                 schedrun.add(Calendar.MONTH,1);
249                 runtime = schedrun.getTime().getTime();
250             }
251             break;
252 
253         case DAILY:
254             // DAILY (certain hour:minutes of the day)
255             schedrun.set(Calendar.SECOND, getSecond());
256             schedrun.set(Calendar.MINUTE, getMinute());
257             schedrun.set(Calendar.HOUR_OF_DAY, getHour());
258 
259             // Scheduled time has NOT expired.
260             if ( now.before(schedrun) )
261             {
262                 runtime = schedrun.getTime().getTime();
263             }
264             else
265             {
266                 // Scheduled time has expired; roll forward 24 hours.
267                 schedrun.add(Calendar.HOUR_OF_DAY,24);
268                 runtime = schedrun.getTime().getTime();
269             }
270             break;
271 
272         default:
273             // Do nothing.
274         }
275     }
276 
277     /***
278      * What schedule am I on?
279      *
280      * I know this is kinda ugly!  If you can think of a cleaner way
281      * to do this, please jump in!
282      *
283      * @return A number specifying the type of schedule. See
284      * calcRunTime().
285      * @exception Exception, a generic exception.
286      */
287     private int evaluateJobType()
288         throws Exception
289     {
290 
291         // First start by checking if it's a day of the month job.
292         if ( getDayOfMonth() < 0 )
293         {
294             // Not a day of the month job... check weekday.
295             if ( getWeekDay() < 0 )
296             {
297                 // Not a weekday job...check if by the hour.
298                 if ( getHour() < 0 )
299                 {
300                     // Not an hourly job...check if it is by the minute
301                     if ( getMinute() < 0 )
302                     {
303                         // Not a by the minute job so must be by the second
304                         if ( getSecond() < 0)
305                             throw new Exception("Error in JobEntry. Bad Job parameter.");
306 
307                         return SECOND;
308                     }
309                     else
310                     {
311                         // Must be a job run by the minute so we need minutes and
312                         // seconds.
313                         if ( getMinute() < 0 || getSecond() < 0 )
314                             throw new Exception("Error in JobEntry. Bad Job parameter.");
315 
316                         return MINUTE;
317                     }
318                 }
319                 else
320                 {
321                     // Must be a daily job by hours minutes, and seconds.  In
322                     // this case, we need the minute, second, and hour params.
323                     if ( getMinute() < 0 || getHour() < 0 || getSecond() < 0)
324                         throw new Exception("Error in JobEntry. Bad Job parameter.");
325 
326                     return DAILY;
327                 }
328             }
329             else
330             {
331                 // Must be a weekday job.  In this case, we need
332                 // minute, second, and hour params
333                 if ( getMinute() < 0 || getHour() < 0 || getSecond() < 0 )
334                     throw new Exception("Error in JobEntry. Bad Job parameter.");
335 
336                 return WEEK_DAY;
337             }
338         }
339         else
340         {
341             // Must be a day of the month job.  In this case, we need
342             // minute, second, and hour params
343             if ( getMinute() < 0 || getHour() < 0 )
344                 throw new Exception("Error in JobEntry. Bad Job parameter.");
345 
346             return DAY_OF_MONTH;
347         }
348     }
349 
350 }