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
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
218 schedrun.add(Calendar.SECOND, getSecond());
219 runtime = schedrun.getTime().getTime();
220 break;
221
222 case MINUTE:
223
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
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
239 runtime = schedrun.getTime().getTime();
240 }
241 else
242 {
243
244 schedrun.add(Calendar.DAY_OF_WEEK, 7);
245 runtime = schedrun.getTime().getTime();
246 }
247 break;
248
249 case DAY_OF_MONTH:
250
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
259 runtime = schedrun.getTime().getTime();
260 }
261 else
262 {
263
264 schedrun.add(Calendar.MONTH, 1);
265 runtime = schedrun.getTime().getTime();
266 }
267 break;
268
269 case DAILY:
270
271 schedrun.set(Calendar.SECOND, getSecond());
272 schedrun.set(Calendar.MINUTE, getMinute());
273 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
274
275
276 if (now.before(schedrun))
277 {
278 runtime = schedrun.getTime().getTime();
279 }
280 else
281 {
282
283 schedrun.add(Calendar.HOUR_OF_DAY, 24);
284 runtime = schedrun.getTime().getTime();
285 }
286 break;
287
288 default:
289
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
310 if (getDayOfMonth() < 0)
311 {
312
313 if (getWeekDay() < 0)
314 {
315
316 if (getHour() < 0)
317 {
318
319 if (getMinute() < 0)
320 {
321
322 if (getSecond() < 0)
323 throw new TurbineException("Error in JobEntry. Bad Job parameter.");
324
325 return SECOND;
326 }
327 else
328 {
329
330
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
340
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
350
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
360
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 }