View Javadoc

1   /*
2    * #%L
3    * Bitrepository Core
4    * %%
5    * Copyright (C) 2010 - 2012 The State and University Library, The Royal Library and The State Archives, Denmark
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 2.1 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-2.1.html>.
20   * #L%
21   */
22  package org.bitrepository.service.workflow;
23  
24  import org.bitrepository.service.scheduler.JobEventListener;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  import java.util.Date;
29  import java.util.List;
30  import java.util.TimerTask;
31  
32  /**
33   * A timer task encapsulating a workflow.
34   * Used for scheduling workflows to run continuously at a given interval.
35   */
36  public class JobTimerTask extends TimerTask {
37      /** The log.*/
38      private Logger log = LoggerFactory.getLogger(getClass());
39      /** The date for the next run of the workflow.*/
40      private Date nextRun;
41      /** The interval between triggers. */
42      private final long interval;
43      private final SchedulableJob job;
44      private List<JobEventListener> jobListeners;
45  
46      /**
47       * Initialise trigger.
48       * @param interval The interval between triggering events in milliseconds.
49       * @param job:  The job.
50       */
51      public JobTimerTask(long interval, SchedulableJob job, List<JobEventListener> jobListeners) {
52          this.interval = interval;
53          this.job = job;
54          nextRun = new Date();
55          this.jobListeners = jobListeners;
56      }
57  
58      /**
59       * @return The date for the next time the encapsulated workflow should run.
60       */
61      public Date getNextRun() {
62          return new Date(nextRun.getTime());
63      }
64  
65      /**
66       * @return The interval between the runs in millis.
67       */
68      public long getIntervalBetweenRuns() {
69          return interval;
70      }
71  
72      public String getDescription() {
73          return job.getDescription();
74      }
75  
76      /**
77       * Runs the job.
78       * Resets the date for the next run of the job.
79       * @return String
80       */
81      public String runJob() {
82          try {
83              if (job.currentState().equals(SchedulableJob.NOT_RUNNING)) {
84                  log.info("Starting job: " + job.getJobID());
85                  job.start();
86                  if (interval > 0) {
87                      nextRun = new Date(System.currentTimeMillis() + interval);
88                  }
89                  notifyListenersAboutFinishedJob(job);
90                  return "Job '" + job.getJobID() + "' finished";
91              } else {
92                  log.info("Ignoring start request for " + job.getJobID() + " the job is already running");
93                  return "Can not start " + job.getJobID() + ", it is already running in state "
94                          + job.currentState();
95              }
96          } catch (Throwable e) {
97              log.error("Fault barrier for '" + job.getJobID() + "' caught unexpected exception.", e);
98              throw new RuntimeException("Failed to run job" + e.getMessage() + ", see server log for details.");
99          }
100     }
101 
102     private void notifyListenersAboutFinishedJob(SchedulableJob job) {
103         for (JobEventListener listener:jobListeners) {
104             listener.jobFinished(job);
105         }
106     }
107 
108     /**
109      * @return The name of the job.
110      */
111     public String getName() {
112         return job.getJobID().toString();
113     }
114     
115     public JobID getWorkflowID() {
116         return job.getJobID();
117     }
118 
119     @Override
120     public void run() {
121         try {
122             if( nextRun != null &&
123                 getNextRun().getTime() <= System.currentTimeMillis()) {
124                 runJob();
125             }
126         } catch (Exception e) {
127             log.error("Failed to run job", e);
128         }
129     }
130 }