KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > cowsultants > itracker > web > scheduler > Scheduler


1 /*
2  * This software was designed and created by Jason Carroll.
3  * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4  * The author can be reached at jcarroll@cowsultants.com
5  * ITracker website: http://www.cowsultants.com
6  * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it only under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  */

18
19 package cowsultants.itracker.web.scheduler;
20
21 import java.io.*;
22 import java.text.*;
23 import java.util.*;
24 import java.lang.reflect.*;
25 import javax.servlet.*;
26 import javax.servlet.http.*;
27
28 import cowsultants.itracker.ejb.client.models.*;
29 import cowsultants.itracker.ejb.client.util.*;
30
31 /**
32   * This class represents a currently running task in the scheduler.
33   */

34 class WorkerThread extends Thread JavaDoc {
35     private ScheduledTaskModel task = null;
36
37     public WorkerThread(ScheduledTaskModel task) {
38         this.task = task;
39     }
40
41     public void run() {
42             try {
43             if(task == null || task.getClassName() == null) {
44                 throw new Exception JavaDoc("Scheduled task, class, or method is null.");
45             }
46
47             Class JavaDoc taskClass = Class.forName(task.getClassName());
48             SchedulableTask workTask = (SchedulableTask) taskClass.newInstance();
49             workTask.performTask(task.getArgs());
50           } catch (Exception JavaDoc e) {
51             Logger.logError("Unable to run scheduled task " + task.toString() + ". " + e.getMessage());
52           }
53     }
54 }
55
56
57 /**
58   * This class is used by the SchedulerEngine to process tasks at specific times.
59   * It is spawned every minute and sent a copy of the current tasks list. This
60   * thread then determines if any of the tasks need to be run. This prevents a single
61   * run from stopping the scheduler altogether and preventing future tasks from being
62   * spawned.
63   */

64 class SchedulerThread extends Thread JavaDoc {
65       private Scheduler engine = null;
66       private GregorianCalendar startDate = null;
67       private Vector tasks = null;
68     private boolean stop = false;
69
70       public SchedulerThread() {
71         tasks = new Vector();
72             startDate = new GregorianCalendar();
73       }
74
75       public SchedulerThread(Scheduler engine, ScheduledTaskModel[] tasks) {
76             this();
77
78             int hour = startDate.get(Calendar.HOUR_OF_DAY);
79             int min = startDate.get(Calendar.MINUTE);
80             int mday = startDate.get(Calendar.DAY_OF_MONTH);
81             int month = startDate.get(Calendar.MONTH) + 1;
82             int wday = startDate.get(Calendar.DAY_OF_WEEK);
83
84         if(engine != null && tasks != null) {
85                 this.engine = engine;
86             for(int i = 0; i < tasks.length; i++) {
87                 if(tasks != null && tasks[i].getId() != null && tasks[i].getId().intValue() > 0) {
88                     ScheduledTaskModel task = (ScheduledTaskModel) tasks[i].clone();
89                     // Now check to see if this is our task.
90
if(processTask(task, hour, min, mday, month, wday)) {
91                         this.tasks.addElement(task);
92                     }
93                 }
94             }
95         }
96     }
97
98     public void run() {
99             for(int i = 0; i < tasks.size(); i++) {
100             if(stop) {
101                 break;
102             }
103             ScheduledTaskModel task = (ScheduledTaskModel) tasks.elementAt(i);
104                 try {
105                         if(task != null && task.getId() != null) {
106                             WorkerThread worker = new WorkerThread(task);
107                             worker.setPriority(5);
108                             worker.start();
109                             engine.setTaskLastRun(task.getId().intValue());
110                         }
111                 } catch(Exception JavaDoc e) {
112                 Logger.logError("Unable to run scheduled task " + task.toString());
113                 }
114             }
115     }
116
117     public void setStop(boolean value) {
118         stop = value;
119     }
120
121     private boolean processTask(ScheduledTaskModel task, int hour, int min, int mday, int month, int wday) {
122         if(hasInt(task.getHours(), hour) && hasInt(task.getMinutes(), min) && hasInt(task.getDaysOfMonth(), mday) &&
123            hasInt(task.getMonths(), month) && hasInt(task.getWeekdays(), wday)) {
124             return true;
125         }
126
127         return false;
128     }
129
130     private boolean hasInt(int[] array, int value) {
131         if(array != null) {
132             for(int i = 0; i < array.length; i++) {
133                 if(array[i] == -1 || value == array[i]) {
134                     return true;
135                 }
136             }
137         }
138         return false;
139     }
140 }
141
142
143
144 public class Scheduler extends Thread JavaDoc {
145     private GregorianCalendar currDate;
146     private static GregorianCalendar lastDate;
147     private static GregorianCalendar startDate;
148       private static Vector threads;
149     private static Vector tasks;
150     private static boolean stop = false;
151
152       public Scheduler() {
153         Logger.logDebug("Scheduler starting.");
154
155             lastDate = new GregorianCalendar();
156             currDate = new GregorianCalendar();
157             threads = new Vector();
158         tasks = new Vector();
159       }
160
161     /**
162       * Main processing method of the scheduler. Every minute it spans a new SchedulerThread
163       * which looks for tasks that need to be run.
164       */

165     public void run() {
166             while(true) {
167             if(stop) {
168                 break;
169             }
170
171                 currDate = new GregorianCalendar();
172                 if(currDate.get(Calendar.MINUTE) == lastDate.get(Calendar.MINUTE)) {
173                         // Not time yet..try again in 20 seconds
174
try {
175                             sleep(20000);
176                             for(int i = 0; i < threads.size(); i++) {
177                                     SchedulerThread minThread = (SchedulerThread) threads.elementAt(i);
178                                     if(! minThread.isAlive()) {
179                                         threads.removeElementAt(i);
180                                     }
181                               }
182                         } catch(Exception JavaDoc e) {
183                     Logger.logError("Error checking on scheduler threads. " + e.getMessage());
184                         }
185                 } else {
186                         lastDate.setTime(currDate.getTime());
187                         if((currDate.get(Calendar.MINUTE) % 10) == 0) {
188                     Logger.logDebug("Scheduler currently running with " + threads.size() + " active threads.");
189                         }
190
191                         SchedulerThread sThread = null;
192                         try {
193                     ScheduledTaskModel[] tasksArray = new ScheduledTaskModel[tasks.size()];
194                     tasks.copyInto(tasksArray);
195                             sThread = new SchedulerThread(this, tasksArray);
196                             sThread.setPriority(7);
197                             sThread.start();
198                             threads.addElement(sThread);
199                         } catch(Exception JavaDoc e) {
200                     Logger.logError("Error while starting new scheduler thread. " + e.getMessage());
201                     e.printStackTrace();
202                         }
203                   }
204             }
205         currDate = null;
206       }
207
208     /**
209       * Returns the current number of SchedulerThreads that are running. Usually there
210       * is one scheduler thread produced each minute. A large number of these could
211       * indecate problems processing tasks.
212       */

213     public static int getNumThreads() {
214             if(threads == null) {
215             threads = new Vector();
216             }
217               return(threads.size());
218     }
219
220     /**
221       * Returns the current number of tasks being checked by the scheduler.
222       */

223     public static int getNumTasks() {
224             if(tasks == null) {
225             tasks = new Vector();
226             }
227             return(tasks.size());
228     }
229
230     /**
231       * Returns the time the scheduler last looked for tasks to process
232       */

233     public static Date getLastRun() {
234         if(lastDate != null) {
235             return lastDate.getTime();
236         }
237         return null;
238     }
239
240     /**
241       * Returns a currently defined scheduler task.
242       * @param taskId the id of the task to return
243       * @return a ScheduledTaskModel of the requested task
244       */

245     public static ScheduledTaskModel getTask(int taskId) {
246         if(tasks != null) {
247             for(int i = 0; i < tasks.size(); i++) {
248                 ScheduledTaskModel task = (ScheduledTaskModel) tasks.elementAt(i);
249                 if(task.getId() != null && taskId == task.getId().intValue()) {
250                     return task;
251                 }
252             }
253         }
254         return null;
255     }
256
257     /**
258       * Returns all currently defined scheduler tasks.
259       * @return an array of ScheduledTaskModels
260       */

261     public static ScheduledTaskModel[] getTasks() {
262         if(tasks == null) {
263             return new ScheduledTaskModel[0];
264         }
265
266         ScheduledTaskModel[] tasksArray = new ScheduledTaskModel[tasks.size()];
267         for(int i = 0; i < tasks.size(); i++) {
268             tasksArray[i] = (ScheduledTaskModel) tasks.elementAt(i);
269         }
270         return tasksArray;
271     }
272
273     /**
274       * Adds a new task into the list.
275       * @param task the task to add
276       */

277     public static void addTask(ScheduledTaskModel task) {
278         if(task != null) {
279             tasks.add(task);
280         }
281     }
282
283     /**
284       * Removes a task for the list of tasks to perform.
285       * @param taskId the id of the task to remove
286       */

287     public static void removeTask(int taskId) {
288         if(tasks != null) {
289             for(int i = 0; i < tasks.size(); i++) {
290                 ScheduledTaskModel task = (ScheduledTaskModel) tasks.elementAt(i);
291                 if(task.getId() != null && taskId == task.getId().intValue()) {
292                     tasks.removeElementAt(i);
293                     return;
294                 }
295             }
296         }
297     }
298
299     /**
300       * This will stop the current scheduler threads, but NOT the worker threads.
301       * This means you might be able to stop new jobs from starting but not currently
302       * running jobs. In general this should never be called.
303       */

304     public static void stopAll() {
305             for(int i = 0; i < threads.size(); i++) {
306                 SchedulerThread thread = (SchedulerThread) threads.elementAt(i);
307                 if(thread.isAlive()) {
308                 thread.setStop(true);
309                   }
310                   threads.removeElementAt(i);
311             }
312       }
313
314     /**
315       * Outputs a task description.
316       * @param taskId the id of the task to print
317       */

318     public static String JavaDoc printTask(int taskId) {
319         ScheduledTaskModel task = getTask(taskId);
320         if(task != null) {
321             return task.toString();
322         }
323         return "Unknown task.";
324     }
325
326     /**
327       * Outputs the full date of the last time the task was run.
328       * @param taskId the id of the task to print
329       */

330       public static String JavaDoc printTaskLastRun(int taskId) {
331         ScheduledTaskModel task = getTask(taskId);
332         if(task != null && task.getLastRun() != null) {
333             SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
334                 return sdf.format(task.getLastRun());
335             }
336         return "Unknown task.";
337       }
338
339     /**
340       * Sets the date a task was last run to the current date/time.
341       * @param taskId the id of the task to set
342       */

343     public static void setTaskLastRun(int taskId) {
344         ScheduledTaskModel task = getTask(taskId);
345         if(task != null) {
346             task.setLastRun(new Date());
347             }
348     }
349
350     /**
351       * Sets a flag to tell the scheduler whether to continue to process tasks.
352       */

353     public static void setStop(boolean value) {
354         stop = value;
355     }
356 }
357
Popular Tags