KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > crontab > Crontab


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.services.crontab;
66
67 import org.apache.log4j.Logger;
68
69 import java.util.Date JavaDoc;
70 import java.util.Iterator JavaDoc;
71 import java.util.LinkedList JavaDoc;
72 import java.util.List JavaDoc;
73 import java.util.SortedSet JavaDoc;
74 import java.util.TreeSet JavaDoc;
75
76 /**
77  * This is the main API controller class that deals with the various crontab
78  * entries.
79  *
80  * @author Mike Dubman
81  */

82 public class Crontab {
83
84     /**
85      * The thread that manages the crontab entries. It does so by simply ringing
86      * this particular class that a cron is ready to run.
87      */

88     protected CronDaemon waiter;
89
90     /**
91      * The queue waiting for execution. Sorting in the set is determined
92      * by the next execution time.
93      */

94     protected SortedSet JavaDoc queue;
95
96     /**
97      * The log4j logger.
98      */

99     private static final Logger log = Logger.getLogger(Crontab.class);
100
101
102     /**
103      * Construct the Crontab thread
104      *
105      * @param isDaemon set to true if the crontab should be a daemon thread
106      * @param threadName the name of the thread
107      */

108     public Crontab(boolean isDaemon, String JavaDoc threadName) {
109         queue = (SortedSet JavaDoc) new TreeSet JavaDoc();
110         waiter = new CronDaemon(this, isDaemon, threadName);
111     }
112
113     /**
114      * Default constructor
115      */

116     public Crontab() {
117         this(true, "Crontab");
118     }
119
120     /**
121      * Add a crontab entry
122      *
123      * @param date the date for the crontab entry to execute
124      * @param listener the listener interface
125      * @return CrontabEntry representing what was just constructed
126      * @throws CronException upon error constructing the CrontabEntry
127      */

128     public synchronized CrontabEntry addCrontabEntry(Date JavaDoc date,
129                                                      CrontabListenerI listener)
130             throws CronException {
131         CrontabEntry entry = new CrontabEntry(date, listener);
132         addCrontabEntry(entry);
133
134         return entry;
135     }
136
137     /**
138      * Add a crontab entry
139      *
140      * @param delay the delay in(?) before executing the crontab
141      * @param isRepetitive true if the crontab is repetitive, ie should it execute
142      * every X many seconds
143      * @param listener the listener to get notified when a crontab executes
144      * @return CrontabEntry
145      * @throws CronException upon error creating the crontab entry
146      */

147     public synchronized CrontabEntry addCrontabEntry(int delay,
148                                                      boolean isRepetitive,
149                                                      CrontabListenerI listener)
150             throws CronException {
151         CrontabEntry entry = new CrontabEntry(delay, isRepetitive, listener);
152         addCrontabEntry(entry);
153
154         return entry;
155     }
156
157     /**
158      * Adds a crontab to execute based upon various Cron-like parameters as
159      * numbers
160      *
161      * @param minute execute every X minutes
162      * @param hour execute every X hours
163      * @param dayOfMonth execute every X days of the month
164      * @param month execute every X days of the month
165      * @param dayOfWeek execute every specified day of the week
166      * @param year execute every X specified years
167      * @param listener the listener to get notified when the crontab's time is
168      * due
169      * @return Crontab Entry
170      * @throws CronException upon construction error
171      */

172     public synchronized CrontabEntry addCrontabEntry(int minute, int hour,
173                                                      int dayOfMonth, int month,
174                                                      int dayOfWeek, int year,
175                                                      CrontabListenerI listener)
176             throws CronException {
177         CrontabEntry entry = new CrontabEntry(minute, hour, dayOfMonth, month,
178                 dayOfWeek, year, listener);
179         addCrontabEntry(entry);
180
181         return entry;
182     }
183
184     /**
185      * Adds a crontab to execute based upon various Cron-like parameters as
186      * numbers
187      *
188      * @param minute execute every X minutes
189      * @param hour execute every X hours
190      * @param dayOfMonth execute every X days of the month
191      * @param month execute every X days of the month
192      * @param dayOfWeek execute every specified day of the week
193      * @param year execute every X specified years
194      * @param label Useful label for possible debugging purposes
195      * @param listener the listener to get notified when the crontab's time is
196      * due
197      * @return Crontab Entry
198      * @throws CronException upon construction error
199      */

200     public synchronized CrontabEntry addCrontabEntry(int minute, int hour,
201                                                      int dayOfMonth, int month,
202                                                      int dayOfWeek, int year, String JavaDoc label,
203                                                      CrontabListenerI listener)
204             throws CronException {
205         CrontabEntry entry = new CrontabEntry(minute, hour, dayOfMonth, month,
206                 dayOfWeek, year, label, listener);
207         addCrontabEntry(entry);
208
209         return entry;
210     }
211
212     /**
213      * Adds a crontab to execute based upon various Cron-like parameters as
214      * numbers
215      *
216      * @param minute execute every X minutes
217      * @param hour execute every X hours
218      * @param dayOfMonth execute every X days of the month
219      * @param month execute every X days of the month
220      * @param dayOfWeek execute every specified day of the week
221      * @param year execute every X specified years
222      * @param label Useful label for possible debugging purposes
223      * @param listener the listener to get notified when the crontab's time is
224      * due
225      * @param jobNumber Job Number for this CrontabEntry's associated JobQueue entry
226      * @return Crontab Entry
227      * @throws CronException upon construction error
228      */

229     public synchronized CrontabEntry addCrontabEntry(int minute, int hour,
230                                                      int dayOfMonth, int month,
231                                                      int dayOfWeek, int year, String JavaDoc label,
232                                                      CrontabListenerI listener, String JavaDoc jobNumber)
233             throws CronException {
234         CrontabEntry entry = new CrontabEntry(minute, hour, dayOfMonth, month,
235                 dayOfWeek, year, label, listener);
236         entry.setJobNumber(jobNumber);
237         addCrontabEntry(entry);
238
239         return entry;
240     }
241
242
243     /**
244      * Add a constructed Crontab entry to the Crontab.
245      *
246      * @param entry the entry to add
247      */

248     public synchronized void addCrontabEntry(CrontabEntry entry)
249             throws CronException {
250         if (log.isDebugEnabled()) {
251             log.debug("Adding Crontab Entry: " + entry.toString());
252         }
253
254         //
255
//First check for any already existing crontab entries We have
256
//to do it the slow iterative way because comparable is ALWAYS unque even
257
//if it's the same crontab. We have to rely on equals
258
//
259
for (Iterator JavaDoc i = queue.iterator(); i.hasNext();) {
260             CrontabEntry test = (CrontabEntry) i.next();
261             if (test.equals(entry)) {
262                 if (log.isInfoEnabled()) {
263                     log.info("Crontab entry: " + entry +
264                             " already exists in crontab. Skipping");
265                 }
266                 return;
267             }
268         }
269
270         queue.add(entry);
271         waiter.update(((CrontabEntry) queue.first()).alarmTime);
272     }
273
274     /**
275      * Remove a given crontab entry from the crontab
276      *
277      * @param entry the entry to remove
278      * @return boolean
279      */

280     public synchronized boolean removeCrontabEntry(CrontabEntry entry) {
281
282
283         //
284
//First check for any already existing crontab entries We have
285
//to do it the slow iterative way because comparable is ALWAYS unque even
286
//if it's the same crontab. We have to rely on equals
287
//
288
for (Iterator JavaDoc i = queue.iterator(); i.hasNext();) {
289             CrontabEntry test = (CrontabEntry) i.next();
290             if (test.equals(entry)) {
291                 if (log.isInfoEnabled()) {
292                     log.info("Crontab entry: " + entry +
293                             " already exists in crontab. Skipping");
294                 }
295                 queue.remove(test);
296                 if (queue.size() > 0) {
297                     waiter.update(((CrontabEntry) queue.first()).alarmTime);
298                 }
299                 return true;
300             }
301         }
302
303         return false;
304     }
305
306     /**
307      * Remove all existing crontabs from the crontab entry.
308      */

309     public synchronized void removeAllCrontabEntries() {
310         if (waiter != null) {
311             waiter.stop();
312         }
313
314         waiter = null;
315         queue.clear();
316     }
317
318     /**
319      * Checks if a given crontab entry is sitting in the queue waiting for execution
320      *
321      * @param oneEntry a given entry.
322      * @return true if the given entry exists in the queue
323      */

324     public synchronized boolean containsCrontabEntry(CrontabEntry oneEntry) {
325         return queue.contains(oneEntry);
326     }
327
328     /**
329      * Retrieve a list of all items that are part of the queue.
330      *
331      * @return a List of CrontabEntry objects
332      */

333     public synchronized List JavaDoc getAllEntries() {
334         final LinkedList JavaDoc result = new LinkedList JavaDoc();
335         Iterator JavaDoc iterator = queue.iterator();
336
337         while (iterator.hasNext()) {
338             result.add(iterator.next());
339         }
340
341         return result;
342     }
343
344     /**
345      * When this is called, we execute the given crontab
346      */

347     protected synchronized void notifyListeners() {
348
349         // if the queue is empty, there's nothing to do
350
if (queue.isEmpty()) {
351             log.debug("Execution queue is empty, exiting notifyListeners()");
352             return;
353         } // if
354

355
356         // Removes this alarm and notifies the listener
357
CrontabEntry entry = (CrontabEntry) queue.first();
358         queue.remove(entry);
359
360         try {
361             if (log.isDebugEnabled()) {
362                 log.debug("Handling crontab entry: " + entry.toString());
363             }
364
365             entry.listener.handleCrontabEntry(entry);
366         } catch (Throwable JavaDoc e) {
367             log.error("Error handling crontab entry", e);
368         }
369         // Reactivates the alarm if it is repetitive
370
if (entry.isRepetitive) {
371             if (log.isDebugEnabled()) {
372                 log.debug("Re-adding repetitive crontab back to queue: " + entry.toString());
373             }
374             entry.updateEntryTime();
375             queue.add(entry);
376         } else {
377             if (log.isDebugEnabled()) {
378                 log.debug("Finished non-repetitive cron: " + entry.toString());
379             }
380         }
381
382         // Notifies the CronDaemon thread for the next alarm
383
if (!queue.isEmpty()) {
384             long alarmTime = ((CrontabEntry) queue.first()).alarmTime;
385
386             if (alarmTime - System.currentTimeMillis() < 1000) {
387                 notifyListeners();
388             } else {
389                 waiter.restart(alarmTime);
390             }
391         }
392
393         if (log.isDebugEnabled()) {
394             log.debug("Execution queue is empty, exiting notifyListeners()");
395
396         }
397     }
398
399     /**
400      * Clearing the cron thread if the crontab is killed
401      */

402     public void finalize() {
403         if (waiter != null) {
404             waiter.stop();
405         }
406     }
407 }
Popular Tags