Home » quartz-1.6.0 » org » quartz » [javadoc | source]

    1   /* 
    2    * Copyright 2004-2005 OpenSymphony 
    3    * 
    4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
    5    * use this file except in compliance with the License. You may obtain a copy 
    6    * of the License at 
    7    * 
    8    *   http://www.apache.org/licenses/LICENSE-2.0 
    9    *   
   10    * Unless required by applicable law or agreed to in writing, software 
   11    * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
   12    * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
   13    * License for the specific language governing permissions and limitations 
   14    * under the License.
   15    * 
   16    */
   17   
   18   /*
   19    * Previously Copyright (c) 2001-2004 James House
   20    */
   21   package org.quartz;
   22   
   23   import java.text.ParseException;
   24   import java.util.Calendar;
   25   import java.util.Date;
   26   import java.util.TimeZone;
   27   
   28   
   29   /**
   30    * <p>
   31    * A concrete <code>{@link Trigger}</code> that is used to fire a <code>{@link org.quartz.JobDetail}</code>
   32    * at given moments in time, defined with Unix 'cron-like' definitions.
   33    * </p>
   34    * 
   35    * <p>
   36    * For those unfamiliar with "cron", this means being able to create a firing
   37    * schedule such as: "At 8:00am every Monday through Friday" or "At 1:30am
   38    * every last Friday of the month".
   39    * </p>
   40    * 
   41    * <p>
   42    * The format of a "Cron-Expression" string is documented on the 
   43    * {@link org.quartz.CronExpression} class.
   44    * </p>
   45    * 
   46    * <p>
   47    * Here are some full examples: <br><table cellspacing="8">
   48    * <tr>
   49    * <th align="left">Expression</th>
   50    * <th align="left">&nbsp;</th>
   51    * <th align="left">Meaning</th>
   52    * </tr>
   53    * <tr>
   54    * <td align="left"><code>"0 0 12 * * ?"</code></td>
   55    * <td align="left">&nbsp;</th>
   56    * <td align="left"><code>Fire at 12pm (noon) every day</code></td>
   57    * </tr>
   58    * <tr>
   59    * <td align="left"><code>"0 15 10 ? * *"</code></td>
   60    * <td align="left">&nbsp;</th>
   61    * <td align="left"><code>Fire at 10:15am every day</code></td>
   62    * </tr>
   63    * <tr>
   64    * <td align="left"><code>"0 15 10 * * ?"</code></td>
   65    * <td align="left">&nbsp;</th>
   66    * <td align="left"><code>Fire at 10:15am every day</code></td>
   67    * </tr>
   68    * <tr>
   69    * <td align="left"><code>"0 15 10 * * ? *"</code></td>
   70    * <td align="left">&nbsp;</th>
   71    * <td align="left"><code>Fire at 10:15am every day</code></td>
   72    * </tr>
   73    * <tr>
   74    * <td align="left"><code>"0 15 10 * * ? 2005"</code></td>
   75    * <td align="left">&nbsp;</th>
   76    * <td align="left"><code>Fire at 10:15am every day during the year 2005</code>
   77    * </td>
   78    * </tr>
   79    * <tr>
   80    * <td align="left"><code>"0 * 14 * * ?"</code></td>
   81    * <td align="left">&nbsp;</th>
   82    * <td align="left"><code>Fire every minute starting at 2pm and ending at 2:59pm, every day</code>
   83    * </td>
   84    * </tr>
   85    * <tr>
   86    * <td align="left"><code>"0 0/5 14 * * ?"</code></td>
   87    * <td align="left">&nbsp;</th>
   88    * <td align="left"><code>Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day</code>
   89    * </td>
   90    * </tr>
   91    * <tr>
   92    * <td align="left"><code>"0 0/5 14,18 * * ?"</code></td>
   93    * <td align="left">&nbsp;</th>
   94    * <td align="left"><code>Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day</code>
   95    * </td>
   96    * </tr>
   97    * <tr>
   98    * <td align="left"><code>"0 0-5 14 * * ?"</code></td>
   99    * <td align="left">&nbsp;</th>
  100    * <td align="left"><code>Fire every minute starting at 2pm and ending at 2:05pm, every day</code>
  101    * </td>
  102    * </tr>
  103    * <tr>
  104    * <td align="left"><code>"0 10,44 14 ? 3 WED"</code></td>
  105    * <td align="left">&nbsp;</th>
  106    * <td align="left"><code>Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.</code>
  107    * </td>
  108    * </tr>
  109    * <tr>
  110    * <td align="left"><code>"0 15 10 ? * MON-FRI"</code></td>
  111    * <td align="left">&nbsp;</th>
  112    * <td align="left"><code>Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday</code>
  113    * </td>
  114    * </tr>
  115    * <tr>
  116    * <td align="left"><code>"0 15 10 15 * ?"</code></td>
  117    * <td align="left">&nbsp;</th>
  118    * <td align="left"><code>Fire at 10:15am on the 15th day of every month</code>
  119    * </td>
  120    * </tr>
  121    * <tr>
  122    * <td align="left"><code>"0 15 10 L * ?"</code></td>
  123    * <td align="left">&nbsp;</th>
  124    * <td align="left"><code>Fire at 10:15am on the last day of every month</code>
  125    * </td>
  126    * </tr>
  127    * <tr>
  128    * <td align="left"><code>"0 15 10 ? * 6L"</code></td>
  129    * <td align="left">&nbsp;</th>
  130    * <td align="left"><code>Fire at 10:15am on the last Friday of every month</code>
  131    * </td>
  132    * </tr>
  133    * <tr>
  134    * <td align="left"><code>"0 15 10 ? * 6L"</code></td>
  135    * <td align="left">&nbsp;</th>
  136    * <td align="left"><code>Fire at 10:15am on the last Friday of every month</code>
  137    * </td>
  138    * </tr>
  139    * <tr>
  140    * <td align="left"><code>"0 15 10 ? * 6L 2002-2005"</code></td>
  141    * <td align="left">&nbsp;</th>
  142    * <td align="left"><code>Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005</code>
  143    * </td>
  144    * </tr>
  145    * <tr>
  146    * <td align="left"><code>"0 15 10 ? * 6#3"</code></td>
  147    * <td align="left">&nbsp;</th>
  148    * <td align="left"><code>Fire at 10:15am on the third Friday of every month</code>
  149    * </td>
  150    * </tr>
  151    * </table>
  152    * </p>
  153    * 
  154    * <p>
  155    * Pay attention to the effects of '?' and '*' in the day-of-week and
  156    * day-of-month fields!
  157    * </p>
  158    * 
  159    * <p>
  160    * <b>NOTES:</b>
  161    * <ul>
  162    * <li>Support for specifying both a day-of-week and a day-of-month value is
  163    * not complete (you'll need to use the '?' character in on of these fields).
  164    * </li>
  165    * <li>Be careful when setting fire times between mid-night and 1:00 AM -
  166    * "daylight savings" can cause a skip or a repeat depending on whether the
  167    * time moves back or jumps forward.</li>
  168    * </ul>
  169    * </p>
  170    * 
  171    * @see Trigger
  172    * @see SimpleTrigger
  173    * @see TriggerUtils
  174    * 
  175    * @author Sharada Jambula, James House
  176    * @author Contributions from Mads Henderson
  177    */
  178   public class CronTrigger extends Trigger {
  179   
  180       /*
  181        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  182        * 
  183        * Constants.
  184        * 
  185        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  186        */
  187   
  188       /**
  189        * <p>
  190        * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
  191        * situation, the <code>{@link CronTrigger}</code> wants to be fired now
  192        * by <code>Scheduler</code>.
  193        * </p>
  194        */
  195       public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
  196   
  197       /**
  198        * <p>
  199        * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
  200        * situation, the <code>{@link CronTrigger}</code> wants to have it's
  201        * next-fire-time updated to the next time in the schedule after the
  202        * current time (taking into account any associated <code>{@link Calendar}</code>,
  203        * but it does not want to be fired now.
  204        * </p>
  205        */
  206       public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2;
  207   
  208       /*
  209        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  210        * 
  211        * Data members.
  212        * 
  213        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  214        */
  215   
  216       private CronExpression cronEx = null;
  217       private Date startTime = null;
  218       private Date endTime = null;
  219       private Date nextFireTime = null;
  220       private Date previousFireTime = null;
  221       private transient TimeZone timeZone = null;
  222   
  223       /*
  224        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  225        * 
  226        * Constructors.
  227        * 
  228        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  229        */
  230   
  231       /**
  232        * <p>
  233        * Create a <code>CronTrigger</code> with no settings.
  234        * </p>
  235        * 
  236        * <p>
  237        * The start-time will also be set to the current time, and the time zone
  238        * will be set the the system's default time zone.
  239        * </p>
  240        */
  241       public CronTrigger() {
  242           super();
  243           setStartTime(new Date());
  244           setTimeZone(TimeZone.getDefault());
  245       }
  246   
  247       /**
  248        * <p>
  249        * Create a <code>CronTrigger</code> with the given name and group.
  250        * </p>
  251        * 
  252        * <p>
  253        * The start-time will also be set to the current time, and the time zone
  254        * will be set the the system's default time zone.
  255        * </p>
  256        */
  257       public CronTrigger(String name, String group) {
  258           super(name, group);
  259           setStartTime(new Date());
  260           setTimeZone(TimeZone.getDefault());
  261       }
  262   
  263       /**
  264        * <p>
  265        * Create a <code>CronTrigger</code> with the given name, group and
  266        * expression.
  267        * </p>
  268        * 
  269        * <p>
  270        * The start-time will also be set to the current time, and the time zone
  271        * will be set the the system's default time zone.
  272        * </p>
  273        */
  274       public CronTrigger(String name, String group, String cronExpression)
  275           throws ParseException {
  276           
  277           super(name, group);
  278   
  279           setCronExpression(cronExpression);
  280   
  281           setStartTime(new Date());
  282           setTimeZone(TimeZone.getDefault());
  283       }
  284   
  285       /**
  286        * <p>
  287        * Create a <code>CronTrigger</code> with the given name and group, and
  288        * associated with the identified <code>{@link org.quartz.JobDetail}</code>.
  289        * </p>
  290        * 
  291        * <p>
  292        * The start-time will also be set to the current time, and the time zone
  293        * will be set the the system's default time zone.
  294        * </p>
  295        */
  296       public CronTrigger(String name, String group, String jobName,
  297               String jobGroup) {
  298           super(name, group, jobName, jobGroup);
  299           setStartTime(new Date());
  300           setTimeZone(TimeZone.getDefault());
  301       }
  302   
  303       /**
  304        * <p>
  305        * Create a <code>CronTrigger</code> with the given name and group,
  306        * associated with the identified <code>{@link org.quartz.JobDetail}</code>,
  307        * and with the given "cron" expression.
  308        * </p>
  309        * 
  310        * <p>
  311        * The start-time will also be set to the current time, and the time zone
  312        * will be set the the system's default time zone.
  313        * </p>
  314        */
  315       public CronTrigger(String name, String group, String jobName,
  316               String jobGroup, String cronExpression) throws ParseException {
  317           this(name, group, jobName, jobGroup, null, null, cronExpression,
  318                   TimeZone.getDefault());
  319       }
  320   
  321       /**
  322        * <p>
  323        * Create a <code>CronTrigger</code> with the given name and group,
  324        * associated with the identified <code>{@link org.quartz.JobDetail}</code>,
  325        * and with the given "cron" expression resolved with respect to the <code>TimeZone</code>.
  326        * </p>
  327        */
  328       public CronTrigger(String name, String group, String jobName,
  329               String jobGroup, String cronExpression, TimeZone timeZone)
  330           throws ParseException {
  331           this(name, group, jobName, jobGroup, null, null, cronExpression,
  332                   timeZone);
  333       }
  334   
  335       /**
  336        * <p>
  337        * Create a <code>CronTrigger</code> that will occur at the given time,
  338        * until the given end time.
  339        * </p>
  340        * 
  341        * <p>
  342        * If null, the start-time will also be set to the current time, the time
  343        * zone will be set the the system's default.
  344        * </p>
  345        * 
  346        * @param startTime
  347        *          A <code>Date</code> set to the time for the <code>Trigger</code>
  348        *          to fire.
  349        * @param endTime
  350        *          A <code>Date</code> set to the time for the <code>Trigger</code>
  351        *          to quit repeat firing.
  352        */
  353       public CronTrigger(String name, String group, String jobName,
  354               String jobGroup, Date startTime, Date endTime, String cronExpression)
  355           throws ParseException {
  356           super(name, group, jobName, jobGroup);
  357   
  358           setCronExpression(cronExpression);
  359   
  360           if (startTime == null) {
  361               startTime = new Date();
  362           }
  363           setStartTime(startTime);
  364           if (endTime != null) {
  365               setEndTime(endTime);
  366           }
  367           setTimeZone(TimeZone.getDefault());
  368   
  369       }
  370   
  371       /**
  372        * <p>
  373        * Create a <code>CronTrigger</code> with fire time dictated by the
  374        * <code>cronExpression</code> resolved with respect to the specified
  375        * <code>timeZone</code> occuring from the <code>startTime</code> until
  376        * the given <code>endTime</code>.
  377        * </p>
  378        * 
  379        * <p>
  380        * If null, the start-time will also be set to the current time. If null,
  381        * the time zone will be set to the system's default.
  382        * </p>
  383        * 
  384        * @param name
  385        *          of the <code>Trigger</code>
  386        * @param group
  387        *          of the <code>Trigger</code>
  388        * @param jobName
  389        *          name of the <code>{@link org.quartz.JobDetail}</code>
  390        *          executed on firetime
  391        * @param jobGroup
  392        *          group of the <code>{@link org.quartz.JobDetail}</code>
  393        *          executed on firetime
  394        * @param startTime
  395        *          A <code>Date</code> set to the earliest time for the <code>Trigger</code>
  396        *          to start firing.
  397        * @param endTime
  398        *          A <code>Date</code> set to the time for the <code>Trigger</code>
  399        *          to quit repeat firing.
  400        * @param cronExpression
  401        *          A cron expression dictating the firing sequence of the <code>Trigger</code>
  402        * @param timeZone
  403        *          Specifies for which time zone the <code>cronExpression</code>
  404        *          should be interprted, i.e. the expression 0 0 10 * * ?, is
  405        *          resolved to 10:00 am in this time zone.
  406        * @throws ParseException
  407        *           if the <code>cronExpression</code> is invalid.
  408        */
  409       public CronTrigger(String name, String group, String jobName,
  410               String jobGroup, Date startTime, Date endTime,
  411               String cronExpression, TimeZone timeZone) throws ParseException {
  412           super(name, group, jobName, jobGroup);
  413   
  414           setCronExpression(cronExpression);
  415   
  416           if (startTime == null) {
  417               startTime = new Date();
  418           }
  419           setStartTime(startTime);
  420           if (endTime != null) {
  421               setEndTime(endTime);
  422           }
  423           if (timeZone == null) {
  424               setTimeZone(TimeZone.getDefault());
  425           } else {
  426               setTimeZone(timeZone);
  427           }
  428       }
  429   
  430       /*
  431        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  432        * 
  433        * Interface.
  434        * 
  435        * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  436        */
  437       
  438       public Object clone() {
  439           CronTrigger copy = (CronTrigger) super.clone();
  440           copy.setCronExpression((CronExpression)cronEx.clone());
  441           return copy;
  442       }
  443   
  444       public void setCronExpression(String cronExpression) throws ParseException {
  445           this.cronEx = new CronExpression(cronExpression);
  446           this.cronEx.setTimeZone(getTimeZone());
  447       }
  448   
  449       public String getCronExpression() {
  450           return cronEx == null ? null : cronEx.getCronExpression();
  451       }
  452   
  453       public void setCronExpression(CronExpression cronExpression) {
  454           this.cronEx = cronExpression;
  455           this.timeZone = cronExpression.getTimeZone();
  456       }
  457       
  458       /**
  459        * <p>
  460        * Get the time at which the <code>CronTrigger</code> should occur.
  461        * </p>
  462        */
  463       public Date getStartTime() {
  464           return this.startTime;
  465       }
  466   
  467       public void setStartTime(Date startTime) {
  468           if (startTime == null) {
  469               throw new IllegalArgumentException("Start time cannot be null");
  470           }
  471   
  472           Date eTime = getEndTime();
  473           if (eTime != null && startTime != null && eTime.before(startTime)) {
  474               throw new IllegalArgumentException(
  475                   "End time cannot be before start time");
  476           }
  477           
  478           // round off millisecond...
  479           // Note timeZone is not needed here as parameter for
  480           // Calendar.getInstance(),
  481           // since time zone is implicit when using a Date in the setTime method.
  482           Calendar cl = Calendar.getInstance();
  483           cl.setTime(startTime);
  484           cl.set(Calendar.MILLISECOND, 0);
  485   
  486           this.startTime = cl.getTime();
  487       }
  488   
  489       /**
  490        * <p>
  491        * Get the time at which the <code>CronTrigger</code> should quit
  492        * repeating - even if repeastCount isn't yet satisfied.
  493        * </p>
  494        * 
  495        * @see #getFinalFireTime()
  496        */
  497       public Date getEndTime() {
  498           return this.endTime;
  499       }
  500   
  501       public void setEndTime(Date endTime) {
  502           Date sTime = getStartTime();
  503           if (sTime != null && endTime != null && sTime.after(endTime)) {
  504               throw new IllegalArgumentException(
  505                       "End time cannot be before start time");
  506           }
  507   
  508           this.endTime = endTime;
  509       }
  510   
  511       /**
  512        * <p>
  513        * Returns the next time at which the <code>CronTrigger</code> will fire.
  514        * If the trigger will not fire again, <code>null</code> will be
  515        * returned. The value returned is not guaranteed to be valid until after
  516        * the <code>Trigger</code> has been added to the scheduler.
  517        * </p>
  518        */
  519       public Date getNextFireTime() {
  520           return this.nextFireTime;
  521       }
  522   
  523       /**
  524        * <p>
  525        * Returns the previous time at which the <code>CronTrigger</code> will
  526        * fire. If the trigger has not yet fired, <code>null</code> will be
  527        * returned.
  528        */
  529       public Date getPreviousFireTime() {
  530           return this.previousFireTime;
  531       }
  532   
  533       /**
  534        * <p>
  535        * Sets the next time at which the <code>CronTrigger</code> will fire.
  536        * <b>This method should not be invoked by client code.</b>
  537        * </p>
  538        */
  539       public void setNextFireTime(Date nextFireTime) {
  540           this.nextFireTime = nextFireTime;
  541       }
  542   
  543       /**
  544        * <p>
  545        * Set the previous time at which the <code>CronTrigger</code> fired.
  546        * </p>
  547        * 
  548        * <p>
  549        * <b>This method should not be invoked by client code.</b>
  550        * </p>
  551        */
  552       public void setPreviousFireTime(Date previousFireTime) {
  553           this.previousFireTime = previousFireTime;
  554       }
  555   
  556       /**
  557        * <p>
  558        * Returns the time zone for which the <code>cronExpression</code> of
  559        * this <code>CronTrigger</code> will be resolved.
  560        * </p>
  561        */
  562       public TimeZone getTimeZone() {
  563           
  564           if(cronEx != null) {
  565               return cronEx.getTimeZone();
  566           }
  567           
  568           if (timeZone == null) {
  569               timeZone = TimeZone.getDefault();
  570           }
  571           return timeZone;
  572       }
  573   
  574       /**
  575        * <p>
  576        * Sets the time zone for which the <code>cronExpression</code> of this
  577        * <code>CronTrigger</code> will be resolved.
  578        * </p>
  579        */
  580       public void setTimeZone(TimeZone timeZone) {
  581           if(cronEx != null) {
  582               cronEx.setTimeZone(timeZone);
  583           }
  584           this.timeZone = timeZone;
  585       }
  586   
  587       /**
  588        * <p>
  589        * Returns the next time at which the <code>CronTrigger</code> will fire,
  590        * after the given time. If the trigger will not fire after the given time,
  591        * <code>null</code> will be returned.
  592        * </p>
  593        * 
  594        * <p>
  595        * Note that the date returned is NOT validated against the related
  596        * org.quartz.Calendar (if any)
  597        * </p>
  598        */
  599       public Date getFireTimeAfter(Date afterTime) {
  600           if (afterTime == null) {
  601               afterTime = new Date();
  602           }
  603   
  604           if (getStartTime().after(afterTime)) {
  605               afterTime = new Date(getStartTime().getTime() - 1000l);
  606           }
  607   
  608           if (getEndTime() != null && (afterTime.compareTo(getEndTime()) >= 0)) {
  609               return null;
  610           }
  611           
  612           Date pot = getTimeAfter(afterTime);
  613           if (getEndTime() != null && pot != null && pot.after(getEndTime())) {
  614               return null;
  615           }
  616   
  617           return pot;
  618       }
  619   
  620       /**
  621        * <p>
  622        * NOT YET IMPLEMENTED: Returns the final time at which the 
  623        * <code>CronTrigger</code> will fire.
  624        * </p>
  625        * 
  626        * <p>
  627        * Note that the return time *may* be in the past. and the date returned is
  628        * not validated against org.quartz.calendar
  629        * </p>
  630        */
  631       public Date getFinalFireTime() {
  632           Date resultTime;
  633           if (getEndTime() != null) {
  634               resultTime = getTimeBefore(new Date(getEndTime().getTime() + 1000l));
  635           } else {
  636               resultTime = (cronEx == null) ? null : cronEx.getFinalFireTime();
  637           }
  638           
  639           if ((resultTime != null) && (getStartTime() != null) && (resultTime.before(getStartTime()))) {
  640               return null;
  641           } 
  642           
  643           return resultTime;
  644       }
  645   
  646       /**
  647        * <p>
  648        * Determines whether or not the <code>CronTrigger</code> will occur
  649        * again.
  650        * </p>
  651        */
  652       public boolean mayFireAgain() {
  653           return (getNextFireTime() != null);
  654       }
  655   
  656       protected boolean validateMisfireInstruction(int misfireInstruction) {
  657           if (misfireInstruction < MISFIRE_INSTRUCTION_SMART_POLICY) {
  658               return false;
  659           }
  660   
  661           if (misfireInstruction > MISFIRE_INSTRUCTION_DO_NOTHING) {
  662               return false;
  663           }
  664   
  665           return true;
  666       }
  667   
  668       /**
  669        * <p>
  670        * Updates the <code>CronTrigger</code>'s state based on the
  671        * MISFIRE_INSTRUCTION_XXX that was selected when the <code>CronTrigger</code>
  672        * was created.
  673        * </p>
  674        * 
  675        * <p>
  676        * If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY,
  677        * then the following scheme will be used: <br>
  678        * <ul>
  679        * <li>The instruction will be interpreted as <code>MISFIRE_INSTRUCTION_FIRE_ONCE_NOW</code>
  680        * </ul>
  681        * </p>
  682        */
  683       public void updateAfterMisfire(org.quartz.Calendar cal) {
  684           int instr = getMisfireInstruction();
  685   
  686           if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) {
  687               instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
  688           }
  689   
  690           if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) {
  691               Date newFireTime = getFireTimeAfter(new Date());
  692               while (newFireTime != null && cal != null
  693                       && !cal.isTimeIncluded(newFireTime.getTime())) {
  694                   newFireTime = getFireTimeAfter(newFireTime);
  695               }
  696               setNextFireTime(newFireTime);
  697           } else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {
  698               setNextFireTime(new Date());
  699           }
  700       }
  701   
  702       /**
  703        * <p>
  704        * Determines whether the date and (optionally) time of the given Calendar 
  705        * instance falls on a scheduled fire-time of this trigger.
  706        * </p>
  707        * 
  708        * <p>
  709        * Equivalent to calling <code>willFireOn(cal, false)</code>.
  710        * </p>
  711        * 
  712        * @param test the date to compare
  713        * 
  714        * @see #willFireOn(Calendar, boolean)
  715        */
  716       public boolean willFireOn(Calendar test) {
  717           return willFireOn(test, false);
  718       }
  719       
  720       /**
  721        * <p>
  722        * Determines whether the date and (optionally) time of the given Calendar 
  723        * instance falls on a scheduled fire-time of this trigger.
  724        * </p>
  725        * 
  726        * <p>
  727        * Note that the value returned is NOT validated against the related
  728        * org.quartz.Calendar (if any)
  729        * </p>
  730        * 
  731        * @param test the date to compare
  732        * @param dayOnly if set to true, the method will only determine if the
  733        * trigger will fire during the day represented by the given Calendar
  734        * (hours, minutes and seconds will be ignored).
  735        * @see #willFireOn(Calendar)
  736        */
  737       public boolean willFireOn(Calendar test, boolean dayOnly) {
  738   
  739           test = (Calendar) test.clone();
  740           
  741           test.set(Calendar.MILLISECOND, 0); // don't compare millis.
  742           
  743           if(dayOnly) {
  744               test.set(Calendar.HOUR, 0); 
  745               test.set(Calendar.MINUTE, 0); 
  746               test.set(Calendar.SECOND, 0); 
  747           }
  748           
  749           Date testTime = test.getTime();
  750           
  751           Date fta = getFireTimeAfter(new Date(test.getTime().getTime() - 1000));
  752   
  753           Calendar p = Calendar.getInstance(test.getTimeZone());
  754           p.setTime(fta);
  755           
  756           int year = p.get(Calendar.YEAR);
  757           int month = p.get(Calendar.MONTH);
  758           int day = p.get(Calendar.DATE);
  759           
  760           if(dayOnly) {
  761               return (year == test.get(Calendar.YEAR) 
  762                       && month == test.get(Calendar.MONTH) 
  763                       && day == test.get(Calendar.DATE));
  764           }
  765           
  766           while(fta.before(testTime)) {
  767               fta = getFireTimeAfter(fta);
  768           }
  769           
  770           if(fta.equals(testTime)) {
  771               return true;
  772           }
  773   
  774           return false;
  775       }
  776   
  777       /**
  778        * <p>
  779        * Called after the <code>{@link Scheduler}</code> has executed the
  780        * <code>{@link org.quartz.JobDetail}</code> associated with the <code>Trigger</code>
  781        * in order to get the final instruction code from the trigger.
  782        * </p>
  783        * 
  784        * @param context
  785        *          is the <code>JobExecutionContext</code> that was used by the
  786        *          <code>Job</code>'s<code>execute(xx)</code> method.
  787        * @param result
  788        *          is the <code>JobExecutionException</code> thrown by the
  789        *          <code>Job</code>, if any (may be null).
  790        * @return one of the Trigger.INSTRUCTION_XXX constants.
  791        * 
  792        * @see #INSTRUCTION_NOOP
  793        * @see #INSTRUCTION_RE_EXECUTE_JOB
  794        * @see #INSTRUCTION_DELETE_TRIGGER
  795        * @see #INSTRUCTION_SET_TRIGGER_COMPLETE
  796        * @see #triggered(Calendar)
  797        */
  798       public int executionComplete(JobExecutionContext context,
  799               JobExecutionException result) {
  800           if (result != null && result.refireImmediately()) {
  801               return INSTRUCTION_RE_EXECUTE_JOB;
  802           }
  803   
  804           if (result != null && result.unscheduleFiringTrigger()) {
  805               return INSTRUCTION_SET_TRIGGER_COMPLETE;
  806           }
  807   
  808           if (result != null && result.unscheduleAllTriggers()) {
  809               return INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE;
  810           }
  811   
  812           if (!mayFireAgain()) {
  813               return INSTRUCTION_DELETE_TRIGGER;
  814           }
  815   
  816           return INSTRUCTION_NOOP;
  817       }
  818   
  819       /**
  820        * <p>
  821        * Called when the <code>{@link Scheduler}</code> has decided to 'fire'
  822        * the trigger (execute the associated <code>Job</code>), in order to
  823        * give the <code>Trigger</code> a chance to update itself for its next
  824        * triggering (if any).
  825        * </p>
  826        * 
  827        * @see #executionComplete(JobExecutionContext, JobExecutionException)
  828        */
  829       public void triggered(org.quartz.Calendar calendar) {
  830           previousFireTime = nextFireTime;
  831           nextFireTime = getFireTimeAfter(nextFireTime);
  832   
  833           while (nextFireTime != null && calendar != null
  834                   && !calendar.isTimeIncluded(nextFireTime.getTime())) {
  835               nextFireTime = getFireTimeAfter(nextFireTime);
  836           }
  837       }
  838   
  839       /**
  840        *  
  841        * @see org.quartz.Trigger#updateWithNewCalendar(org.quartz.Calendar, long)
  842        */
  843       public void updateWithNewCalendar(org.quartz.Calendar calendar, long misfireThreshold)
  844       {
  845           nextFireTime = getFireTimeAfter(previousFireTime);
  846           
  847           Date now = new Date();
  848           do {
  849               while (nextFireTime != null && calendar != null
  850                       && !calendar.isTimeIncluded(nextFireTime.getTime())) {
  851                   nextFireTime = getFireTimeAfter(nextFireTime);
  852               }
  853               
  854               if(nextFireTime != null && nextFireTime.before(now)) {
  855                   long diff = now.getTime() - nextFireTime.getTime();
  856                   if(diff >= misfireThreshold) {
  857                       nextFireTime = getFireTimeAfter(nextFireTime);
  858                       continue;
  859                   }
  860               }
  861           }while(false);
  862       }
  863   
  864       /**
  865        * <p>
  866        * Called by the scheduler at the time a <code>Trigger</code> is first
  867        * added to the scheduler, in order to have the <code>Trigger</code>
  868        * compute its first fire time, based on any associated calendar.
  869        * </p>
  870        * 
  871        * <p>
  872        * After this method has been called, <code>getNextFireTime()</code>
  873        * should return a valid answer.
  874        * </p>
  875        * 
  876        * @return the first time at which the <code>Trigger</code> will be fired
  877        *         by the scheduler, which is also the same value <code>getNextFireTime()</code>
  878        *         will return (until after the first firing of the <code>Trigger</code>).
  879        *         </p>
  880        */
  881       public Date computeFirstFireTime(org.quartz.Calendar calendar) {
  882           nextFireTime = getFireTimeAfter(new Date(getStartTime().getTime() - 1000l));
  883   
  884           while (nextFireTime != null && calendar != null
  885                   && !calendar.isTimeIncluded(nextFireTime.getTime())) {
  886               nextFireTime = getFireTimeAfter(nextFireTime);
  887           }
  888   
  889           return nextFireTime;
  890       }
  891   
  892       public String getExpressionSummary() {
  893           return cronEx == null ? null : cronEx.getExpressionSummary();
  894       }
  895   
  896       ////////////////////////////////////////////////////////////////////////////
  897       //
  898       // Computation Functions
  899       //
  900       ////////////////////////////////////////////////////////////////////////////
  901   
  902       protected Date getTimeAfter(Date afterTime) {
  903           return (cronEx == null) ? null : cronEx.getTimeAfter(afterTime);
  904       }
  905   
  906       /**
  907        * NOT YET IMPLEMENTED: Returns the time before the given time
  908        * that this <code>CronTrigger</code> will fire.
  909        */ 
  910       protected Date getTimeBefore(Date endTime) {
  911           return (cronEx == null) ? null : cronEx.getTimeBefore(endTime);
  912       }
  913   
  914       public static void main(String[] args) // TODO: remove method after good
  915           // unit testing
  916           throws Exception {
  917   
  918           String expr = "15 10 0/4 * * ?";
  919           if(args != null && args.length > 0 && args[0] != null) {
  920               expr = args[0];
  921           }
  922       
  923           CronTrigger ct = new CronTrigger("t", "g", "j", "g", new Date(), null, expr);
  924           ct.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
  925           System.err.println(ct.getExpressionSummary());
  926           System.err.println("tz=" + ct.getTimeZone().getID());
  927           System.err.println();
  928       
  929           java.util.List times = TriggerUtils.computeFireTimes(ct, null, 25);
  930       
  931           for (int i = 0; i < times.size(); i++) {
  932               System.err.println("firetime = " + times.get(i));
  933           }
  934           
  935           Calendar tt = Calendar.getInstance();
  936           tt.set(Calendar.DATE, 17);
  937           tt.set(Calendar.MONTH, 5 - 1);
  938           tt.set(Calendar.HOUR, 11);
  939           tt.set(Calendar.MINUTE, 0);
  940           tt.set(Calendar.SECOND, 7);
  941           
  942           System.err.println("\nWill fire on: " + tt.getTime() + " -- " + ct.willFireOn(tt, false));
  943           
  944         
  945   //            CRON Expression: 0 0 9 * * ?
  946   //
  947   //                    TimeZone.getDefault().getDisplayName() = Central African Time
  948   //                    TimeZone.getDefault().getID() = Africa/Harare            
  949       //
  950   ////        System.err.println();
  951   ////        System.err.println();
  952   ////        System.err.println();
  953   ////        System.err.println("Daylight test:");
  954   ////
  955   ////        CronTrigger trigger = new CronTrigger();
  956   ////
  957   ////        TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
  958   ////        //    TimeZone timeZone = TimeZone.getDefault();
  959   ////
  960   ////        trigger.setTimeZone(timeZone);
  961   ////        trigger.setCronExpression("0 0 1 ? 4 *");
  962   ////
  963   ////        Date start = new Date(1056319200000L);
  964   ////        Date end = new Date(1087682399000L);
  965   ////
  966   ////        trigger.setStartTime(start);
  967   ////        trigger.setEndTime(end);
  968   ////
  969   ////        Date next = new Date(1056232800000L);
  970   ////        while (next != null) {
  971   ////            next = trigger.getFireTimeAfter(next);
  972   ////            if (next != null) {
  973   ////                Calendar cal = Calendar.getInstance();
  974   ////                cal.setTimeZone(timeZone);
  975   ////                cal.setTime(next);
  976   ////                System.err.println(cal.get(Calendar.MONTH) + "/"
  977   ////                        + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR)
  978   ////                        + " - " + cal.get(Calendar.HOUR_OF_DAY) + ":"
  979   ////                        + cal.get(Calendar.MINUTE));
  980   ////            }
  981   ////        }
  982   ////
  983   ////        System.err.println();
  984   ////        System.err.println();
  985   ////        System.err.println();
  986   ////        System.err.println("Midnight test:");
  987   ////
  988   ////        trigger = new CronTrigger();
  989   ////
  990   ////        timeZone = TimeZone.getTimeZone("Asia/Jerusalem");
  991   ////        //    timeZone = TimeZone.getTimeZone("America/Los_Angeles");
  992   ////        //    TimeZone timeZone = TimeZone.getDefault();
  993   ////
  994   ////        trigger.setTimeZone(timeZone);
  995   ////        trigger.setCronExpression("0 /15 * ? 4 *");
  996   ////
  997   ////        start = new Date(1056319200000L);
  998   ////        end = new Date(1087682399000L);
  999   ////
 1000   ////        trigger.setStartTime(start);
 1001   ////        trigger.setEndTime(end);
 1002   ////
 1003   ////        next = new Date(1056232800000L);
 1004   ////        while (next != null) {
 1005   ////            next = trigger.getFireTimeAfter(next);
 1006   ////            if (next != null) {
 1007   ////                Calendar cal = Calendar.getInstance();
 1008   ////                cal.setTimeZone(timeZone);
 1009   ////                cal.setTime(next);
 1010   ////                System.err.println(cal.get(Calendar.MONTH) + "/"
 1011   ////                        + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR)
 1012   ////                        + " - " + cal.get(Calendar.HOUR_OF_DAY) + ":"
 1013   ////                        + cal.get(Calendar.MINUTE));
 1014   ////            }
 1015   ////        }
 1016   
 1017       }
 1018   }
 1019   

Home » quartz-1.6.0 » org » quartz » [javadoc | source]