001: package org.apache.turbine.services.schedule;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.util.Calendar;
023: import java.util.Date;
024:
025: import org.apache.commons.lang.StringUtils;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029:
030: import org.apache.turbine.util.TurbineException;
031:
032: /**
033: * This is a wrapper for a scheduled job. It is modeled after the
034: * Unix scheduler cron. Note: BaseJobEntry is generated by Torque
035: * at compile time, and is therefore NOT in CVS.
036: *
037: * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
038: * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
039: * @version $Id: JobEntry.java 534527 2007-05-02 16:10:59Z tv $
040: */
041: public class JobEntry extends BaseJobEntry implements Comparable {
042: /** Logging */
043: private static Log log = LogFactory
044: .getLog(ScheduleService.LOGGER_NAME);
045:
046: /** indicates if job is currently running */
047: private boolean jobIsActive = false;
048:
049: /** Next runtime. **/
050: private long runtime = 0;
051:
052: /** schedule types **/
053: private static final int SECOND = 0;
054: private static final int MINUTE = 1;
055: private static final int WEEK_DAY = 2;
056: private static final int DAY_OF_MONTH = 3;
057: private static final int DAILY = 4;
058:
059: /**
060: * default constructor
061: */
062: public JobEntry() {
063: }
064:
065: /**
066: * Constuctor.
067: *
068: * Schedule a job to run on a certain point of time.<br>
069: *
070: * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
071: * the month - <br>
072: *
073: * JobEntry je = new JobEntry(0,0,8,15,"DefaultScheduledJob");<br>
074: *
075: * Example 2: Run the DefaultScheduledJob at 8:00am every day -
076: * <br>
077: *
078: * JobEntry je = new JobEntry(0,0,8,-1,"DefaultScheduledJob");<br>
079: *
080: * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
081: *
082: * JobEntry je = new JobEntry(0,120,-1,-1,"DefaultScheduledJob");<br>
083: *
084: * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
085: *
086: * JobEntry je = new JobEntry(30,-1,-1,-1,"DefaultScheduledJob");<br>
087: *
088: * @param sec Value for entry "seconds".
089: * @param min Value for entry "minutes".
090: * @param hour Value for entry "hours".
091: * @param wd Value for entry "week days".
092: * @param day_mo Value for entry "month days".
093: * @param task Task to execute.
094: * @exception TurbineException a generic exception.
095: */
096: public JobEntry(int sec, int min, int hour, int wd, int day_mo,
097: String task) throws TurbineException {
098: if (StringUtils.isEmpty(task)) {
099: throw new TurbineException("Error in JobEntry. "
100: + "Bad Job parameter. Task not set.");
101: }
102:
103: setSecond(sec);
104: setMinute(min);
105: setHour(hour);
106: setWeekDay(wd);
107: setDayOfMonth(day_mo);
108: setTask(task);
109:
110: calcRunTime();
111: }
112:
113: /**
114: * Used for ordering Jobentries
115: * Note: this comparator imposes orderings that are inconsistent with
116: * equals.
117: *
118: * @param je The first <code>JobEntry</code> object.
119: * @return An <code>int</code> indicating the result of the comparison.
120: */
121: public int compareTo(Object je) {
122: int result = -1;
123: if (je instanceof JobEntry) {
124: result = getJobId() - ((JobEntry) je).getJobId();
125: }
126: return result;
127: }
128:
129: /**
130: * Sets whether the job is running.
131: *
132: * @param isActive Whether the job is running.
133: */
134: public void setActive(boolean isActive) {
135: jobIsActive = isActive;
136: }
137:
138: /**
139: * Check to see if job is currently active/running
140: *
141: * @return true if job is currently geing run by the
142: * workerthread, otherwise false
143: */
144: public boolean isActive() {
145: return jobIsActive;
146: }
147:
148: /**
149: * Get the next runtime for this job as a long.
150: *
151: * @return The next run time as a long.
152: */
153: public long getNextRuntime() {
154: return runtime;
155: }
156:
157: /**
158: * Gets the next runtime as a date
159: *
160: * @return Next run date
161: */
162: public Date getNextRunDate() {
163: return new Date(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: return getNextRunDate().toString();
173: }
174:
175: /**
176: * Calculate how long before the next runtime.<br>
177: *
178: * The runtime determines it's position in the job queue.
179: * Here's the logic:<br>
180: *
181: * 1. Create a date the represents when this job is to run.<br>
182: *
183: * 2. If this date has expired, them "roll" appropriate date
184: * fields forward to the next date.<br>
185: *
186: * 3. Calculate the diff in time between the current time and the
187: * next run time.<br>
188: *
189: * @exception TurbineException a generic exception.
190: */
191: public void calcRunTime() throws TurbineException {
192: Calendar schedrun = Calendar.getInstance();
193: Calendar now = Calendar.getInstance();
194:
195: switch (evaluateJobType()) {
196: case SECOND:
197: // SECOND (every so many seconds...)
198: schedrun.add(Calendar.SECOND, getSecond());
199: runtime = schedrun.getTime().getTime();
200: break;
201:
202: case MINUTE:
203: // MINUTE (every so many minutes...)
204: schedrun.add(Calendar.SECOND, getSecond());
205: schedrun.add(Calendar.MINUTE, getMinute());
206: runtime = schedrun.getTime().getTime();
207: break;
208:
209: case WEEK_DAY:
210: // WEEKDAY (day of the week)
211: schedrun.set(Calendar.SECOND, getSecond());
212: schedrun.set(Calendar.MINUTE, getMinute());
213: schedrun.set(Calendar.HOUR_OF_DAY, getHour());
214: schedrun.set(Calendar.DAY_OF_WEEK, getWeekDay());
215:
216: if (now.before(schedrun)) {
217: // Scheduled time has NOT expired.
218: runtime = schedrun.getTime().getTime();
219: } else {
220: // Scheduled time has expired; roll to the next week.
221: schedrun.add(Calendar.DAY_OF_WEEK, 7);
222: runtime = schedrun.getTime().getTime();
223: }
224: break;
225:
226: case DAY_OF_MONTH:
227: // DAY_OF_MONTH (date of the month)
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_MONTH, getDayOfMonth());
232:
233: if (now.before(schedrun)) {
234: // Scheduled time has NOT expired.
235: runtime = schedrun.getTime().getTime();
236: } else {
237: // Scheduled time has expired; roll to the next month.
238: schedrun.add(Calendar.MONTH, 1);
239: runtime = schedrun.getTime().getTime();
240: }
241: break;
242:
243: case DAILY:
244: // DAILY (certain hour:minutes of the day)
245: schedrun.set(Calendar.SECOND, getSecond());
246: schedrun.set(Calendar.MINUTE, getMinute());
247: schedrun.set(Calendar.HOUR_OF_DAY, getHour());
248:
249: // Scheduled time has NOT expired.
250: if (now.before(schedrun)) {
251: runtime = schedrun.getTime().getTime();
252: } else {
253: // Scheduled time has expired; roll forward 24 hours.
254: schedrun.add(Calendar.HOUR_OF_DAY, 24);
255: runtime = schedrun.getTime().getTime();
256: }
257: break;
258:
259: default:
260: // Do nothing.
261: }
262:
263: log.info("Next runtime for task " + this .getTask() + " is "
264: + this .getNextRunDate());
265: }
266:
267: /**
268: * What schedule am I on?
269: *
270: * I know this is kinda ugly! If you can think of a cleaner way
271: * to do this, please jump in!
272: *
273: * @return A number specifying the type of schedule. See
274: * calcRunTime().
275: * @exception TurbineException a generic exception.
276: */
277: private int evaluateJobType() throws TurbineException {
278:
279: // First start by checking if it's a day of the month job.
280: if (getDayOfMonth() < 0) {
281: // Not a day of the month job... check weekday.
282: if (getWeekDay() < 0) {
283: // Not a weekday job...check if by the hour.
284: if (getHour() < 0) {
285: // Not an hourly job...check if it is by the minute
286: if (getMinute() < 0) {
287: // Not a by the minute job so must be by the second
288: if (getSecond() < 0)
289: throw new TurbineException(
290: "Error in JobEntry. Bad Job parameter.");
291:
292: return SECOND;
293: } else {
294: // Must be a job run by the minute so we need minutes and
295: // seconds.
296: if (getMinute() < 0 || getSecond() < 0)
297: throw new TurbineException(
298: "Error in JobEntry. Bad Job parameter.");
299:
300: return MINUTE;
301: }
302: } else {
303: // Must be a daily job by hours minutes, and seconds. In
304: // this case, we need the minute, second, and hour params.
305: if (getMinute() < 0 || getHour() < 0
306: || getSecond() < 0)
307: throw new TurbineException(
308: "Error in JobEntry. Bad Job parameter.");
309:
310: return DAILY;
311: }
312: } else {
313: // Must be a weekday job. In this case, we need
314: // minute, second, and hour params
315: if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
316: throw new TurbineException(
317: "Error in JobEntry. Bad Job parameter.");
318:
319: return WEEK_DAY;
320: }
321: } else {
322: // Must be a day of the month job. In this case, we need
323: // minute, second, and hour params
324: if (getMinute() < 0 || getHour() < 0)
325: throw new TurbineException(
326: "Error in JobEntry. Bad Job parameter.");
327:
328: return DAY_OF_MONTH;
329: }
330: }
331:
332: }
|