001    package org.apache.turbine.services.schedule;
002    
003    
004    import java.sql.Date;
005    import java.util.Calendar;
006    
007    import org.apache.commons.lang.StringUtils;
008    import org.apache.commons.logging.Log;
009    import org.apache.commons.logging.LogFactory;
010    import org.apache.torque.om.Persistent;
011    import org.apache.turbine.util.TurbineException;
012    
013    /**
014     * The skeleton for this class was autogenerated by Torque on:
015     *
016     * [Mon Jan 24 20:11:00 CET 2011]
017     *
018     * You should add additional methods to this class to meet the
019     * application requirements.  This class will only be generated as
020     * long as it does not already exist in the output directory.
021     */
022    public  class JobEntry
023        extends org.apache.turbine.services.schedule.BaseJobEntry
024        implements Persistent
025    {
026        /**
027         *
028         */
029        private static final long serialVersionUID = -5501116588294474363L;
030    
031        /** Logging */
032        private static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME);
033    
034        /** indicates if job is currently running */
035        private boolean jobIsActive = false;
036    
037        /** Next runtime. **/
038        private long runtime = 0;
039    
040        /** schedule types **/
041        private static final int SECOND = 0;
042        private static final int MINUTE = 1;
043        private static final int WEEK_DAY = 2;
044        private static final int DAY_OF_MONTH = 3;
045        private static final int DAILY = 4;
046    
047        /**
048         * default constructor
049         */
050        public JobEntry()
051        {
052            // empty
053        }
054    
055        /**
056         * Constuctor.
057         *
058         * Schedule a job to run on a certain point of time.<br>
059         *
060         * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
061         * the month - <br>
062         *
063         * JobEntry je = new JobEntry(0,0,8,15,"DefaultScheduledJob");<br>
064         *
065         * Example 2: Run the DefaultScheduledJob at 8:00am every day -
066         * <br>
067         *
068         * JobEntry je = new JobEntry(0,0,8,-1,"DefaultScheduledJob");<br>
069         *
070         * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
071         *
072         * JobEntry je = new JobEntry(0,120,-1,-1,"DefaultScheduledJob");<br>
073         *
074         * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
075         *
076         * JobEntry je = new JobEntry(30,-1,-1,-1,"DefaultScheduledJob");<br>
077         *
078         * @param sec Value for entry "seconds".
079         * @param min Value for entry "minutes".
080         * @param hour Value for entry "hours".
081         * @param wd Value for entry "week days".
082         * @param day_mo Value for entry "month days".
083         * @param task Task to execute.
084         * @exception TurbineException a generic exception.
085         */
086        public JobEntry(int sec,
087                        int min,
088                        int hour,
089                        int wd,
090                        int day_mo,
091                        String task)
092                throws TurbineException
093        {
094            if (StringUtils.isEmpty(task))
095            {
096                throw new TurbineException("Error in JobEntry. " +
097                        "Bad Job parameter. Task not set.");
098            }
099    
100            setSecond(sec);
101            setMinute(min);
102            setHour(hour);
103            setWeekDay(wd);
104            setDayOfMonth(day_mo);
105            setTask(task);
106    
107            calcRunTime();
108        }
109    
110        /**
111         * Used for ordering Jobentries
112         * Note: this comparator imposes orderings that are inconsistent with
113         * equals.
114         *
115         * @param je The first <code>JobEntry</code> object.
116         * @return An <code>int</code> indicating the result of the comparison.
117         */
118        public int compareTo(Object je)
119        {
120            int result = -1;
121            if (je instanceof JobEntry)
122            {
123                result = getJobId() - ((JobEntry) je).getJobId();
124            }
125            return result;
126        }
127    
128        /**
129         * Sets whether the job is running.
130         *
131         * @param isActive Whether the job is running.
132         */
133        public void setActive(boolean isActive)
134        {
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        {
146            return jobIsActive;
147        }
148    
149        /**
150         * Get the next runtime for this job as a long.
151         *
152         * @return The next run time as a long.
153         */
154        public long getNextRuntime()
155        {
156            return runtime;
157        }
158    
159        /**
160         * Gets the next runtime as a date
161         *
162         * @return Next run date
163         */
164        public Date getNextRunDate()
165        {
166            return new Date(runtime);
167        }
168    
169        /**
170         * Get the next runtime for this job as a String.
171         *
172         * @return The next run time as a String.
173         */
174        public String getNextRunAsString()
175        {
176            return getNextRunDate().toString();
177        }
178    
179        /**
180         * Calculate how long before the next runtime.<br>
181         *
182         * The runtime determines it's position in the job queue.
183         * Here's the logic:<br>
184         *
185         * 1. Create a date the represents when this job is to run.<br>
186         *
187         * 2. If this date has expired, them "roll" appropriate date
188         * fields forward to the next date.<br>
189         *
190         * 3. Calculate the diff in time between the current time and the
191         * next run time.<br>
192         *
193         * @exception TurbineException a generic exception.
194         */
195        public void calcRunTime()
196                throws TurbineException
197        {
198            Calendar schedrun = Calendar.getInstance();
199            Calendar now = Calendar.getInstance();
200    
201            switch (evaluateJobType())
202            {
203                case SECOND:
204                    // SECOND (every so many seconds...)
205                    schedrun.add(Calendar.SECOND, getSecond());
206                    runtime = schedrun.getTime().getTime();
207                    break;
208    
209                case MINUTE:
210                    // MINUTE (every so many minutes...)
211                    schedrun.add(Calendar.SECOND, getSecond());
212                    schedrun.add(Calendar.MINUTE, getMinute());
213                    runtime = schedrun.getTime().getTime();
214                    break;
215    
216                case WEEK_DAY:
217                    // WEEKDAY (day of the week)
218                    schedrun.set(Calendar.SECOND, getSecond());
219                    schedrun.set(Calendar.MINUTE, getMinute());
220                    schedrun.set(Calendar.HOUR_OF_DAY, getHour());
221                    schedrun.set(Calendar.DAY_OF_WEEK, getWeekDay());
222    
223                    if (now.before(schedrun))
224                    {
225                        // Scheduled time has NOT expired.
226                        runtime = schedrun.getTime().getTime();
227                    }
228                    else
229                    {
230                        // Scheduled time has expired; roll to the next week.
231                        schedrun.add(Calendar.DAY_OF_WEEK, 7);
232                        runtime = schedrun.getTime().getTime();
233                    }
234                    break;
235    
236                case DAY_OF_MONTH:
237                    // DAY_OF_MONTH (date of the month)
238                    schedrun.set(Calendar.SECOND, getSecond());
239                    schedrun.set(Calendar.MINUTE, getMinute());
240                    schedrun.set(Calendar.HOUR_OF_DAY, getHour());
241                    schedrun.set(Calendar.DAY_OF_MONTH, getDayOfMonth());
242    
243                    if (now.before(schedrun))
244                    {
245                        // Scheduled time has NOT expired.
246                        runtime = schedrun.getTime().getTime();
247                    }
248                    else
249                    {
250                        // Scheduled time has expired; roll to the next month.
251                        schedrun.add(Calendar.MONTH, 1);
252                        runtime = schedrun.getTime().getTime();
253                    }
254                    break;
255    
256                case DAILY:
257                    // DAILY (certain hour:minutes of the day)
258                    schedrun.set(Calendar.SECOND, getSecond());
259                    schedrun.set(Calendar.MINUTE, getMinute());
260                    schedrun.set(Calendar.HOUR_OF_DAY, getHour());
261    
262                    // Scheduled time has NOT expired.
263                    if (now.before(schedrun))
264                    {
265                        runtime = schedrun.getTime().getTime();
266                    }
267                    else
268                    {
269                        // Scheduled time has expired; roll forward 24 hours.
270                        schedrun.add(Calendar.HOUR_OF_DAY, 24);
271                        runtime = schedrun.getTime().getTime();
272                    }
273                    break;
274    
275                default:
276                    // Do nothing.
277            }
278    
279            log.info("Next runtime for task " + this.getTask() + " is " + this.getNextRunDate());
280        }
281    
282        /**
283         * What schedule am I on?
284         *
285         * I know this is kinda ugly!  If you can think of a cleaner way
286         * to do this, please jump in!
287         *
288         * @return A number specifying the type of schedule. See
289         * calcRunTime().
290         * @exception TurbineException a generic exception.
291         */
292        private int evaluateJobType()
293                throws TurbineException
294        {
295    
296            // First start by checking if it's a day of the month job.
297            if (getDayOfMonth() < 0)
298            {
299                // Not a day of the month job... check weekday.
300                if (getWeekDay() < 0)
301                {
302                    // Not a weekday job...check if by the hour.
303                    if (getHour() < 0)
304                    {
305                        // Not an hourly job...check if it is by the minute
306                        if (getMinute() < 0)
307                        {
308                            // Not a by the minute job so must be by the second
309                            if (getSecond() < 0)
310                                throw new TurbineException("Error in JobEntry. Bad Job parameter.");
311    
312                            return SECOND;
313                        }
314                        else
315                        {
316                            // Must be a job run by the minute so we need minutes and
317                            // seconds.
318                            if (getMinute() < 0 || getSecond() < 0)
319                                throw new TurbineException("Error in JobEntry. Bad Job parameter.");
320    
321                            return MINUTE;
322                        }
323                    }
324                    else
325                    {
326                        // Must be a daily job by hours minutes, and seconds.  In
327                        // this case, we need the minute, second, and hour params.
328                        if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
329                            throw new TurbineException("Error in JobEntry. Bad Job parameter.");
330    
331                        return DAILY;
332                    }
333                }
334                else
335                {
336                    // Must be a weekday job.  In this case, we need
337                    // minute, second, and hour params
338                    if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
339                        throw new TurbineException("Error in JobEntry. Bad Job parameter.");
340    
341                    return WEEK_DAY;
342                }
343            }
344            else
345            {
346                // Must be a day of the month job.  In this case, we need
347                // minute, second, and hour params
348                if (getMinute() < 0 || getHour() < 0)
349                    throw new TurbineException("Error in JobEntry. Bad Job parameter.");
350    
351                return DAY_OF_MONTH;
352            }
353        }
354    
355    }