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