View Javadoc

    1   package org.apache.turbine.services.schedule;
    2
    3   /*
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *   http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21
    22  import java.util.Calendar;
    23  import java.util.Date;
    24
    25  import org.apache.commons.lang.StringUtils;
    26  import org.apache.commons.logging.Log;
    27  import org.apache.commons.logging.LogFactory;
    28  import org.apache.turbine.util.TurbineException;
    29
    30  /**
    31   * This class provides the basic implementation of common features for a scheduled job entry.
    32   *
    33   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
    34   */
    35  public abstract class AbstractJobEntry implements JobEntry
    36  {
    37      /** Logging */
    38      protected static Log log = LogFactory.getLog(ScheduleService.LOGGER_NAME);
    39
    40      /** indicates if job is currently running */
    41      private boolean jobIsActive = false;
    42
    43      /** Next runtime. **/
    44      private long runtime = 0;
    45
    46      /** schedule types **/
    47      protected enum ScheduleType {
    48          SECOND,
    49          MINUTE,
    50          WEEK_DAY,
    51          DAY_OF_MONTH,
    52          DAILY
    53      }
    54
    55      /**
    56       * Default constructor
    57       */
    58      public AbstractJobEntry()
    59      {
    60          super();
    61      }
    62
    63      /**
    64       * Constructor.
    65       *
    66       * Schedule a job to run on a certain point of time.<br>
    67       *
    68       * Example 1: Run the DefaultScheduledJob at 8:00am every 15th of
    69       * the month - <br>
    70       *
    71       * JobEntry je = new JobEntry(0,0,8,-1,15,"DefaultScheduledJob");<br>
    72       *
    73       * Example 2: Run the DefaultScheduledJob at 8:00am every day -
    74       * <br>
    75       *
    76       * JobEntry je = new JobEntry(0,0,8,-1,-1,"DefaultScheduledJob");<br>
    77       *
    78       * Example 3: Run the DefaultScheduledJob every 2 hours. - <br>
    79       *
    80       * JobEntry je = new JobEntry(0,120,-1,-1,-1,"DefaultScheduledJob");<br>
    81       *
    82       * Example 4: Run the DefaultScheduledJob every 30 seconds. - <br>
    83       *
    84       * JobEntry je = new JobEntry(30,-1,-1,-1,-1,"DefaultScheduledJob");<br>
    85       *
    86       * @param sec Value for entry "seconds".
    87       * @param min Value for entry "minutes".
    88       * @param hour Value for entry "hours".
    89       * @param wd Value for entry "week days".
    90       * @param day_mo Value for entry "month days".
    91       * @param task Task to execute.
    92       * @throws TurbineException a generic exception.
    93       */
    94      public AbstractJobEntry(int sec,
    95                      int min,
    96                      int hour,
    97                      int wd,
    98                      int day_mo,
    99                      String task)
    100             throws TurbineException
    101     {
    102         this();
    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     @Override
    129     public int compareTo(JobEntry je)
    130     {
    131         return getJobId() - je.getJobId();
    132     }
    133
    134     /**
    135      * Sets whether the job is running.
    136      *
    137      * @param isActive Whether the job is running.
    138      */
    139     @Override
    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 queuing run by the
    149      *  worker thread, otherwise false
    150      */
    151     @Override
    152     public boolean isActive()
    153     {
    154         return jobIsActive;
    155     }
    156
    157     /**
    158      * Get the next runtime for this job as a long.
    159      *
    160      * @return The next run time as a long.
    161      */
    162     @Override
    163     public long getNextRuntime()
    164     {
    165         return runtime;
    166     }
    167
    168     /**
    169      * Gets the next runtime as a date
    170      *
    171      * @return Next run date
    172      */
    173     @Override
    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     @Override
    185     public String getNextRunAsString()
    186     {
    187         return getNextRunDate().toString();
    188     }
    189
    190     /**
    191      * Calculate how long before the next runtime.<br>
    192      *
    193      * The runtime determines it's position in the job queue.
    194      * Here's the logic:<br>
    195      *
    196      * 1. Create a date the represents when this job is to run.<br>
    197      *
    198      * 2. If this date has expired, them "roll" appropriate date
    199      * fields forward to the next date.<br>
    200      *
    201      * 3. Calculate the diff in time between the current time and the
    202      * next run time.<br>
    203      *
    204      * @throws TurbineException a generic exception.
    205      */
    206     @Override
    207     public void calcRunTime()
    208             throws TurbineException
    209     {
    210         Calendar schedrun = Calendar.getInstance();
    211         Calendar now = Calendar.getInstance();
    212
    213         switch (evaluateJobType())
    214         {
    215             case SECOND:
    216                 // SECOND (every so many seconds...)
    217                 schedrun.add(Calendar.SECOND, getSecond());
    218                 runtime = schedrun.getTime().getTime();
    219                 break;
    220
    221             case MINUTE:
    222                 // MINUTE (every so many minutes...)
    223                 schedrun.add(Calendar.SECOND, getSecond());
    224                 schedrun.add(Calendar.MINUTE, getMinute());
    225                 runtime = schedrun.getTime().getTime();
    226                 break;
    227
    228             case WEEK_DAY:
    229                 // WEEKDAY (day of the week)
    230                 schedrun.set(Calendar.SECOND, getSecond());
    231                 schedrun.set(Calendar.MINUTE, getMinute());
    232                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
    233                 schedrun.set(Calendar.DAY_OF_WEEK, getWeekDay());
    234
    235                 if (now.before(schedrun))
    236                 {
    237                     // Scheduled time has NOT expired.
    238                     runtime = schedrun.getTime().getTime();
    239                 }
    240                 else
    241                 {
    242                     // Scheduled time has expired; roll to the next week.
    243                     schedrun.add(Calendar.DAY_OF_WEEK, 7);
    244                     runtime = schedrun.getTime().getTime();
    245                 }
    246                 break;
    247
    248             case DAY_OF_MONTH:
    249                 // DAY_OF_MONTH (date of the month)
    250                 schedrun.set(Calendar.SECOND, getSecond());
    251                 schedrun.set(Calendar.MINUTE, getMinute());
    252                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
    253                 schedrun.set(Calendar.DAY_OF_MONTH, getDayOfMonth());
    254
    255                 if (now.before(schedrun))
    256                 {
    257                     // Scheduled time has NOT expired.
    258                     runtime = schedrun.getTime().getTime();
    259                 }
    260                 else
    261                 {
    262                     // Scheduled time has expired; roll to the next month.
    263                     schedrun.add(Calendar.MONTH, 1);
    264                     runtime = schedrun.getTime().getTime();
    265                 }
    266                 break;
    267
    268             case DAILY:
    269                 // DAILY (certain hour:minutes of the day)
    270                 schedrun.set(Calendar.SECOND, getSecond());
    271                 schedrun.set(Calendar.MINUTE, getMinute());
    272                 schedrun.set(Calendar.HOUR_OF_DAY, getHour());
    273
    274                 // Scheduled time has NOT expired.
    275                 if (now.before(schedrun))
    276                 {
    277                     runtime = schedrun.getTime().getTime();
    278                 }
    279                 else
    280                 {
    281                     // Scheduled time has expired; roll forward 24 hours.
    282                     schedrun.add(Calendar.HOUR_OF_DAY, 24);
    283                     runtime = schedrun.getTime().getTime();
    284                 }
    285                 break;
    286
    287             default:
    288                 // Do nothing.
    289         }
    290
    291         log.info("Next runtime for task " + this.getTask() + " is " + this.getNextRunDate());
    292     }
    293
    294     /**
    295      * What schedule am I on?
    296      *
    297      * I know this is kinda ugly!  If you can think of a cleaner way
    298      * to do this, please jump in!
    299      *
    300      * @return A number specifying the type of schedule. See
    301      * calcRunTime().
    302      * @throws TurbineException a generic exception.
    303      */
    304     private ScheduleType evaluateJobType()
    305             throws TurbineException
    306     {
    307
    308         // First start by checking if it's a day of the month job.
    309         if (getDayOfMonth() < 0)
    310         {
    311             // Not a day of the month job... check weekday.
    312             if (getWeekDay() < 0)
    313             {
    314                 // Not a weekday job...check if by the hour.
    315                 if (getHour() < 0)
    316                 {
    317                     // Not an hourly job...check if it is by the minute
    318                     if (getMinute() < 0)
    319                     {
    320                         // Not a by the minute job so must be by the second
    321                         if (getSecond() < 0)
    322                         {
    323                             throw new TurbineException("Error in JobEntry. Bad Job parameter.");
    324                         }
    325
    326                         return ScheduleType.SECOND;
    327                     }
    328                     else
    329                     {
    330                         // Must be a job run by the minute so we need minutes and
    331                         // seconds.
    332                         if (getMinute() < 0 || getSecond() < 0)
    333                         {
    334                             throw new TurbineException("Error in JobEntry. Bad Job parameter.");
    335                         }
    336
    337                         return ScheduleType.MINUTE;
    338                     }
    339                 }
    340                 else
    341                 {
    342                     // Must be a daily job by hours minutes, and seconds.  In
    343                     // this case, we need the minute, second, and hour params.
    344                     if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
    345                     {
    346                         throw new TurbineException("Error in JobEntry. Bad Job parameter.");
    347                     }
    348
    349                     return ScheduleType.DAILY;
    350                 }
    351             }
    352             else
    353             {
    354                 // Must be a weekday job.  In this case, we need
    355                 // minute, second, and hour params
    356                 if (getMinute() < 0 || getHour() < 0 || getSecond() < 0)
    357                 {
    358                     throw new TurbineException("Error in JobEntry. Bad Job parameter.");
    359                 }
    360
    361                 return ScheduleType.WEEK_DAY;
    362             }
    363         }
    364         else
    365         {
    366             // Must be a day of the month job.  In this case, we need
    367             // minute, second, and hour params
    368             if (getMinute() < 0 || getHour() < 0)
    369             {
    370                 throw new TurbineException("Error in JobEntry. Bad Job parameter.");
    371             }
    372
    373             return ScheduleType.DAY_OF_MONTH;
    374         }
    375     }
    376
    377     /**
    378      * Get the value of jobId.
    379      *
    380      * @return int
    381      */
    382     @Override
    383     public abstract int getJobId();
    384
    385     /**
    386      * Set the value of jobId.
    387      *
    388      * @param v new value
    389      */
    390     @Override
    391     public abstract void setJobId(int v);
    392
    393     /**
    394      * Get the value of second.
    395      *
    396      * @return int
    397      */
    398     public abstract int getSecond();
    399
    400     /**
    401      * Set the value of second.
    402      *
    403      * @param v new value
    404      */
    405     public abstract void setSecond(int v);
    406
    407     /**
    408      * Get the value of minute.
    409      *
    410      * @return int
    411      */
    412     public abstract int getMinute();
    413
    414     /**
    415      * Set the value of minute.
    416      *
    417      * @param v new value
    418      */
    419     public abstract void setMinute(int v);
    420
    421     /**
    422      * Get the value of hour.
    423      *
    424      * @return int
    425      */
    426     public abstract int getHour();
    427
    428     /**
    429      * Set the value of hour.
    430      *
    431      * @param v new value
    432      */
    433     public abstract void setHour(int v);
    434
    435     /**
    436      * Get the value of weekDay.
    437      *
    438      * @return int
    439      */
    440     public abstract int getWeekDay();
    441
    442     /**
    443      * Set the value of weekDay.
    444      *
    445      * @param v new value
    446      */
    447     public abstract void setWeekDay(int v);
    448
    449     /**
    450      * Get the value of dayOfMonth.
    451      *
    452      * @return int
    453      */
    454     public abstract int getDayOfMonth();
    455
    456     /**
    457      * Set the value of dayOfMonth.
    458      *
    459      * @param v new value
    460      */
    461     public abstract void setDayOfMonth(int v);
    462
    463     /**
    464      * Get the value of task.
    465      *
    466      * @return String
    467      */
    468     @Override
    469     public abstract String getTask();
    470
    471     /**
    472      * Set the value of task.
    473      *
    474      * @param v new value
    475      */
    476     @Override
    477     public abstract void setTask(String v);
    478 }