Clover coverage report - JFox Service-Oriented Application Framework - 1.0-RC2
Coverage timestamp: 星期四 十二月 15 2005 11:58:01 CST
file stats: LOC: 324   Methods: 13
NCLOC: 87   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
Task.java 0% 0% 0% 0%
coverage
 1   
 /**
 2   
  * @(#)Task.java
 3   
  * 
 4   
  * JFoxSOAF, Service-Oriented Application Framework
 5   
  * 
 6   
  * Copyright(c) JFoxSOAF Team
 7   
  * 
 8   
  * Licensed under the GNU LGPL, Version 2.1 (the "License"); 
 9   
  * you may not use this file except in compliance with the License. 
 10   
  * You may obtain a copy of the License at  
 11   
  * 
 12   
  * http://www.gnu.org/copyleft/lesser.html
 13   
  * 
 14   
  * Unless required by applicable law or agreed to in writing, software
 15   
  * distributed under the License is distributed on an "AS IS" BASIS, 
 16   
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 17   
  * See the License for the specific language governing permissions and 
 18   
  * limitations under the License. 
 19   
  * 
 20   
  * For more information, please visit:
 21   
  * http://www.jfox.cn/confluence/display/JFoxSOAF/Home
 22   
  * http://www.huihoo.org/jfox/jfoxsoaf
 23   
  */
 24   
 
 25   
 package org.huihoo.jfox.soaf.services.timer;
 26   
 
 27   
 import java.io.Externalizable;
 28   
 import java.io.ObjectOutput;
 29   
 import java.io.ObjectInput;
 30   
 import java.io.IOException;
 31   
 
 32   
 /**
 33   
  * <p>
 34   
  * A task which can be scheduled to run at specified times by the TaskScheduler
 35   
  * <br>
 36   
  * </p>
 37   
  * <p>
 38   
  * The user should extend this class and override the required methods (e.g.
 39   
  * run() method).
 40   
  * </p>
 41   
  * 
 42   
  * @author <a href="mailto:founder_chen@yahoo.com.cn">Peter Cheng </a>
 43   
  * @author <a href="mailto:berkovichnyc@hotmail.com">Efraim Berkovich </a>
 44   
  * @version $Revision: 1.1 $ $Date: 2005/05/22 06:52:07 $
 45   
  * @version Revision: 1.0
 46   
  */
 47   
 
 48   
 public abstract class Task implements Runnable, Externalizable {
 49   
 
 50   
     // instance variables
 51   
     /** has the cancel() method been called? */
 52   
     protected boolean isCancelled = false;
 53   
 
 54   
     /** The name of the task (for display purposes) */
 55   
     protected String name = null;
 56   
 
 57   
     private transient long ID;
 58   
 
 59   
     private boolean hasBeenScheduled = false;
 60   
 
 61   
     private long scheduledInitialTime = 0;
 62   
 
 63   
     private long scheduledInterval = 0; // if <=0 -- means one-time execution
 64   
 
 65   
     private long lastRunTime = 0;
 66   
 
 67   
     // package view -- the task scheduler sets this when the task is scheduled
 68   
     // with it
 69   
     SimpleTimerServiceImpl scheduler = null;
 70   
 
 71   
     // static variables
 72   
     private static Boolean mutex = new Boolean(true);
 73   
 
 74   
     private static long nextID = 0;
 75   
 
 76   
     /**
 77   
      * Creates a new task and assigns it a unique ID.
 78   
      */
 79  0
     protected Task() {
 80  0
         synchronized (mutex) {
 81  0
             this.ID = nextID;
 82  0
             nextID++;
 83  0
             if (nextID == Long.MAX_VALUE)
 84  0
                 nextID = 0;
 85   
         }
 86   
 
 87   
     }
 88   
 
 89   
     /**
 90   
      * Schedules the specified task for execution at the specified time. If the
 91   
      * time is in the past, the task is scheduled for immediate execution.
 92   
      * <p>
 93   
      * There are two types of scheduling: one time and periodic.
 94   
      * <p>
 95   
      * <b>One time </b> <br>
 96   
      * The task will execute exactly once.
 97   
      * <p>
 98   
      * <b>Periodic </b> <br>
 99   
      * The task is scheduled for repeated periodic execution, beginning at the
 100   
      * specified time. Once a task starts running, the next occurrence of the
 101   
      * task will start running <i>interval </i> time later. It is possible for
 102   
      * one event-firing of the task (if it runs too long) will overlap another
 103   
      * event-firing of that same task. If this is not desired, then the task
 104   
      * should synchronize within its run() method.
 105   
      * <p>
 106   
      * This method can only be called once. Calling it more than once will cause
 107   
      * an exception.
 108   
      * <p>
 109   
      * 
 110   
      * @param firstTime long system time at which to run the task.
 111   
      * @param interval long number of millis between executions of the task,
 112   
      *            passing <=0 will cause the task to be executed once.
 113   
      * @exception IllegalStateException On calling this method more than once.
 114   
      */
 115  0
     public synchronized final void setSchedule(long firstTime, long interval)
 116   
             throws IllegalStateException {
 117  0
         if (hasBeenScheduled)
 118  0
             throw new IllegalStateException(
 119   
                     "Cannot set schedule for the task more than once.");
 120   
 
 121  0
         hasBeenScheduled = true;
 122  0
         this.scheduledInitialTime = firstTime;
 123  0
         this.scheduledInterval = interval;
 124   
     }
 125   
 
 126   
     /**
 127   
      * Get the task ID.
 128   
      * 
 129   
      * @return unique Task ID.
 130   
      */
 131  0
     public long getID() {
 132  0
         return ID;
 133   
     }
 134   
 
 135   
     /**
 136   
      * Get the first scheduled time for the task.
 137   
      * 
 138   
      * @return the time the task was first scheduled to run (as long, millis)
 139   
      */
 140  0
     public long getScheduledFirstTime() {
 141  0
         return scheduledInitialTime;
 142   
     }
 143   
 
 144   
     /**
 145   
      * Get the interval scheduled for the task.
 146   
      * 
 147   
      * @return the interval scheduled for the task. (as long, millis)
 148   
      */
 149  0
     public long getScheduledInterval() {
 150  0
         return scheduledInterval;
 151   
     }
 152   
 
 153   
     /**
 154   
      * Was the cancel method called for this task?
 155   
      * 
 156   
      * @return true if cancel was called, false if not
 157   
      */
 158  0
     public boolean isCancelled() {
 159  0
         return isCancelled;
 160   
     }
 161   
 
 162   
     /**
 163   
      * Get the name for the task
 164   
      * 
 165   
      * @return the task name
 166   
      */
 167  0
     public String getName() {
 168  0
         if (name == null)
 169  0
             return this.getClass().toString();
 170   
 
 171  0
         return name;
 172   
     }
 173   
 
 174   
     /**
 175   
      * Calling this method notifies the TaskScheduler (if the task has been
 176   
      * scheduled) and forces it to persist this task's data.
 177   
      * <p>
 178   
      * 
 179   
      * @exception various possible depending on persist strategy of the
 180   
      *                scheduler
 181   
      */
 182  0
     public void persist() throws Exception {
 183  0
         if (scheduler != null)
 184  0
             scheduler.persist(this);
 185   
     }
 186   
 
 187   
     /**
 188   
      * Cancels this timer task. If the task has been scheduled for one-time
 189   
      * execution and has not yet run, or has not yet been scheduled, it will
 190   
      * never run. If the task has been scheduled for repeated execution, it will
 191   
      * never run again. (If the task is running when this call occurs, the task
 192   
      * will run to completion, but will never run again.)
 193   
      * <p>
 194   
      * Note that calling this method from within the run method of a repeating
 195   
      * timer task absolutely guarantees that the timer task will not run again.
 196   
      * <p>
 197   
      * This method may be called repeatedly; the second and subsequent calls
 198   
      * have no effect.
 199   
      */
 200  0
     public void cancel() {
 201  0
         isCancelled = true;
 202  0
         if (scheduler != null) {
 203  0
             scheduler.cleanup(this);
 204   
         }
 205   
     }
 206   
 
 207   
     /**
 208   
      * Returns the scheduled execution time of the most recent actual execution
 209   
      * of this task. (If this method is invoked while task execution is in
 210   
      * progress, the return value is the scheduled execution time of the ongoing
 211   
      * task execution.)
 212   
      * <p>
 213   
      * This method is typically invoked from within a task's run method, to
 214   
      * determine whether the current execution of the task is sufficiently
 215   
      * timely to warrant performing the scheduled activity:
 216   
      * <p>
 217   
      * 
 218   
      * <pre>
 219   
      * public void run() {
 220   
      *     if (System.currentTimeMillis() - lastExecutionTime() &gt;= MAX_TARDINESS)
 221   
      *         return; // Too late; skip this execution.
 222   
      *     // Perform the task
 223   
      * }
 224   
      * </pre>
 225   
      * 
 226   
      * <p>
 227   
      * 
 228   
      * @return the time at which the most recent execution of this task was
 229   
      *         scheduled to occur, in the format returned by Date.getTime(). The
 230   
      *         return value is undefined if the task has yet to commence its
 231   
      *         first execution.
 232   
      */
 233  0
     public long lastExecutionTime() {
 234  0
         return lastRunTime;
 235   
     }
 236   
 
 237   
     /**
 238   
      * Set the last run time. This is only called by the TaskScheduler
 239   
      * 
 240   
      * @param lastRunTime. The last run time
 241   
      */
 242  0
     void setLastRunTime(long lastRunTime) {
 243  0
         this.lastRunTime = lastRunTime;
 244   
     }
 245   
 
 246   
     /**
 247   
      * This method persists the task. Tasks should override this method if they
 248   
      * carry instance data. (Make sure to call super.writeExternal() if you
 249   
      * override).
 250   
      * 
 251   
      * @param ObjectOutput The stream to write the object to
 252   
      * @exception IOException On write problems
 253   
      */
 254  0
     public void writeExternal(ObjectOutput out) throws IOException {
 255  0
         out.writeLong(this.scheduledInitialTime);
 256  0
         out.writeLong(this.scheduledInterval);
 257  0
         out.writeLong(this.lastRunTime);
 258  0
         out.writeObject(this.name);
 259   
     }
 260   
 
 261   
     /**
 262   
      * This method instantiates the task from persistent storage. Tasks should
 263   
      * override this method if they carry instance data. (Make sure to call
 264   
      * super.writeExternal() if you override).
 265   
      * <p>
 266   
      * When a Task is instantiated from deserialization, the
 267   
      * scheduledInitialTime is set according to the following rules:
 268   
      * <ul>
 269   
      * <li>If the scheduledInitialTime is in the future, that time is kept.
 270   
      * <li>If the scheduledInitialTime is in the past and the Task is a
 271   
      * repeating task, then the scheduledInitialTime is set to the next time the
 272   
      * task would run had the Task not been serialized. For example, if a Task
 273   
      * runs once a day at 1pm, then the scheduledInitialTime will be set to the
 274   
      * next 1pm running time. (The logic does not distinguish between fixed-rate
 275   
      * vs. fixed-delay Tasks).
 276   
      * </ul>
 277   
      * 
 278   
      * @param ObjectInput The stream to write the object to
 279   
      * @exception IOException On write problems
 280   
      * @exception ClassNotFoundException On the class not being in the stream.
 281   
      */
 282  0
     public void readExternal(ObjectInput in) throws IOException,
 283   
             java.lang.ClassNotFoundException {
 284  0
         this.scheduledInitialTime = in.readLong();
 285  0
         this.scheduledInterval = in.readLong();
 286  0
         this.lastRunTime = in.readLong();
 287  0
         this.name = (String) in.readObject();
 288   
 
 289   
         // set scheduledInitialTime to make it in the future
 290  0
         if (scheduledInitialTime < System.currentTimeMillis()) {
 291  0
             long n = System.currentTimeMillis() - scheduledInitialTime;
 292  0
             n = n % scheduledInterval;
 293  0
             this.scheduledInitialTime = System.currentTimeMillis() + n;
 294   
         }
 295   
 
 296   
         // assume all deserialized tasks had setSchedule() called
 297  0
         hasBeenScheduled = true;
 298   
     }
 299   
 
 300   
     /**
 301   
      * This method is the action to be performed. This method should be
 302   
      * overriden. It will be called once at every time the task runs.
 303   
      * <p>
 304   
      * If a task encounters an error during run, it may call the cancel() method
 305   
      * to prevent the task from running again.
 306   
      * <p>
 307   
      * If the task modifies its instance data during execution, then it should
 308   
      * call the Task persist() method. This will notify the TaskScheduler to
 309   
      * write the task to persistent storage by calling the writeExternal()
 310   
      * method.
 311   
      */
 312   
     public abstract void run();
 313   
 
 314   
     /**
 315   
      * This method should provide a status message regarding the task. Care
 316   
      * should be taken to make sure the method is thread-safe, as code in the
 317   
      * run() method and the caller of getStatus() will likely be in different
 318   
      * threads.
 319   
      * 
 320   
      * @return a task-specific status message
 321   
      */
 322   
     public abstract String getStatus();
 323   
 
 324   
 }