KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > services > scheduler > FixedRateTask


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.services.scheduler;
19
20 import java.util.Calendar JavaDoc;
21 import java.util.Date JavaDoc;
22 import java.util.GregorianCalendar JavaDoc;
23 import java.util.Timer JavaDoc;
24
25 import org.sape.carbon.core.config.InvalidConfigurationException;
26 import org.sape.carbon.core.util.calendar.DayOfWeekEnum;
27 import org.sape.carbon.core.util.calendar.MonthEnum;
28
29 import org.sape.carbon.services.threadpool.ThreadPool;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34 /**
35  * Utility class used to interperet FixedRateTaskConfiguration and
36  * schedule fixed rate tasks.
37  *
38  * Copyright 2002 Sapient
39  * @since carbon 1.0
40  * @author Douglas Voet, June 2002
41  * @version $Revision: 1.16 $($Author: dvoet $ / $Date: 2003/11/20 21:46:15 $)
42  */

43 class FixedRateTask extends AbstractTask {
44
45     /**
46      * Provides a handle to Apache-commons logger
47      */

48     private Log log = LogFactory.getLog(this.getClass());
49
50     // constants specifying the range of valid configuration values
51
/** Mininum valid minute value. */
52     private static final int MIN_MINUTE = 0;
53     /** Maximum valid minute value. */
54     private static final int MAX_MINUTE = 59;
55
56     /** Mininum valid hour value. */
57     private static final int MIN_HOUR = 0;
58     /** Maximum valid hour value. */
59     private static final int MAX_HOUR = 23;
60
61     /** Mininum valid day of month value. */
62     private static final int MIN_DAY_OF_MONTH = 1;
63     /** Maximum valid day of month value. */
64     private static final int MAX_DAY_OF_MONTH = 31;
65
66     // constants used to set the appropriate period for task execution
67
/** Milliseconds for one minute. */
68     private static final long EVERY_MINUTE = 1000 * 60;
69     /** Milliseconds for one hour. */
70     private static final long EVERY_HOUR = EVERY_MINUTE * 60;
71     /** Milliseconds for one day. */
72     private static final long EVERY_DAY = EVERY_HOUR * 24;
73     /** Milliseconds for one week. */
74     private static final long EVERY_WEEK = EVERY_DAY * 7;
75     /** Milliseconds for one month. */
76     private static final long EVERY_MONTH = EVERY_DAY * 30;
77     /** Milliseconds for one year. */
78     private static final long EVERY_YEAR = EVERY_DAY * 365;
79
80     /** Holds the period of how often the task will execute. */
81     private long period;
82
83     /** Holds the first run time of the task. */
84     private Date JavaDoc time;
85
86     /**
87      * This constructor determines the starting time and date and the repeat
88      * period of the task. See the class javadoc for FixedRateTaskConfiguration
89      * for valid configuration and related behavior.
90      *
91      * @see org.sape.carbon.services.scheduler.FixedRateTaskConfiguration
92      *
93      * @param taskConfiguration
94      */

95     protected FixedRateTask(
96         FixedRateTaskConfiguration taskConfiguration,
97         ThreadPool threadPool) {
98             
99         super(taskConfiguration, threadPool);
100
101         Integer JavaDoc minute = taskConfiguration.getMinute();
102         Integer JavaDoc hour = taskConfiguration.getHour();
103         Integer JavaDoc dayOfMonth = taskConfiguration.getDayOfMonth();
104         MonthEnum month = taskConfiguration.getMonth();
105         DayOfWeekEnum dayOfWeek = taskConfiguration.getDayOfWeek();
106
107         //validate configuration information is in the right range
108
validate(
109             taskConfiguration.getConfigurationName(),
110             "Minute",
111             minute,
112             MIN_MINUTE,
113             MAX_MINUTE);
114         validate(
115             taskConfiguration.getConfigurationName(),
116             "Hour",
117             hour,
118             MIN_HOUR,
119             MAX_HOUR);
120         validate(
121             taskConfiguration.getConfigurationName(),
122             "DayOfMonth",
123             dayOfMonth,
124             MIN_DAY_OF_MONTH,
125             MAX_DAY_OF_MONTH);
126
127         Calendar JavaDoc firstRunTime = new GregorianCalendar JavaDoc();
128         firstRunTime.set(Calendar.MILLISECOND, 0);
129         firstRunTime.set(Calendar.SECOND, 0);
130
131         // this section of if statements determines when the task should
132
// execute first and how often it should execute after that
133
if (minute == null) {
134             // task runs every minute starting at the next minute
135

136             // make sure there is not extra configuration specified
137
if (!(hour == null && dayOfMonth == null
138                     && month == null && dayOfWeek == null)) {
139
140                 throw new InvalidConfigurationException(
141                     this.getClass(),
142                     taskConfiguration.getConfigurationName(),
143                     "Minute",
144                     "Minute was not specifed, but other configuration "
145                         + "information exists. Either specify Minute "
146                         + "or remove all other configuration information");
147             }
148
149             // run task every minute starting with the next minute
150
this.period = EVERY_MINUTE;
151
152             // start running at the next minute
153
firstRunTime.add(Calendar.MINUTE, 1);
154
155         } else if (hour == null) {
156             // task runs every hour starting at the next occurence of the
157
// specified minute
158

159             // make sure there is not extra configuration specified
160
if (!(dayOfMonth == null && month == null && dayOfWeek == null)) {
161                 throw new InvalidConfigurationException(
162                     this.getClass(),
163                     taskConfiguration.getConfigurationName(),
164                     "Hour",
165                     "Hour was not specifed, but day and/or month "
166                         + "configuration information exists. Either "
167                         + "specify Hour or remove day and month "
168                         + "configuration information");
169             }
170
171             // run task every hour starting with the next hour
172
this.period = EVERY_HOUR;
173
174             firstRunTime.set(Calendar.MINUTE, minute.intValue());
175
176             Date JavaDoc now = new Date JavaDoc();
177             if (firstRunTime.getTime().compareTo(now) <= 0) {
178                 firstRunTime.add(Calendar.HOUR_OF_DAY, 1);
179             }
180
181         } else if (dayOfMonth == null && dayOfWeek == null) {
182             // task runs every day starting at the next occurence
183
// of the specified hour and minute
184

185             // make sure there is not extra configuration specified
186
if (month != null) {
187                 throw new InvalidConfigurationException(
188                     this.getClass(),
189                     taskConfiguration.getConfigurationName(),
190                     "Month",
191                     "Month was supplied without DayOfMonth, either remove "
192                         + "Month or add DayOfMonth");
193             }
194
195             this.period = EVERY_DAY;
196
197             firstRunTime.set(Calendar.MINUTE, minute.intValue());
198             firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
199
200             Date JavaDoc now = new Date JavaDoc();
201             if (firstRunTime.getTime().compareTo(now) <= 0) {
202                 // starting tomorrow if the scheduled
203
// time of day has passed today
204
firstRunTime.add(Calendar.DAY_OF_MONTH, 1);
205             }
206
207         } else if (dayOfMonth != null) {
208             // make sure there is not extra configuration specified
209
if (dayOfWeek != null) {
210                 throw new InvalidConfigurationException(
211                     this.getClass(),
212                     taskConfiguration.getConfigurationName(),
213                     "DayOfWeek",
214                     "Both DayOfWeek and DayOfMonth were specified, only one "
215                         + "can be used");
216             }
217
218             if (month == null) {
219                 // run task every month starting next month if the scheduled
220
// date and time has passed this month
221

222                 this.period = EVERY_MONTH;
223
224                 firstRunTime.set(Calendar.MINUTE, minute.intValue());
225                 firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
226                 firstRunTime.set(Calendar.DAY_OF_MONTH, dayOfMonth.intValue());
227
228                 Date JavaDoc now = new Date JavaDoc();
229                 if (firstRunTime.getTime().compareTo(now) <= 0) {
230                     firstRunTime.add(Calendar.MONTH, 1);
231                 }
232
233             } else {
234                 // run task every year starting next year if the scheduled
235
// date and time has passed this year
236

237                 this.period = EVERY_YEAR;
238
239                 firstRunTime.set(Calendar.MINUTE, minute.intValue());
240                 firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
241                 firstRunTime.set(Calendar.DAY_OF_MONTH, dayOfMonth.intValue());
242                 firstRunTime.set(Calendar.MONTH, month.getOrdinal());
243
244                 Date JavaDoc now = new Date JavaDoc();
245                 if (firstRunTime.getTime().compareTo(now) <= 0) {
246                     firstRunTime.add(Calendar.YEAR, 1);
247                 }
248             }
249
250         } else if (dayOfWeek != null) {
251             // run task every week starting next week if the scheduled
252
// day and time has passed this week
253

254             // make sure there is not extra configuration specified
255
if (month != null) {
256                 throw new InvalidConfigurationException(
257                     this.getClass(),
258                     taskConfiguration.getConfigurationName(),
259                     "Month",
260                     "Month cannot be used with DayOfWeek, "
261                         + "it can only be used in conjunction with "
262                         + "DayOfMonth");
263             }
264
265             this.period = EVERY_WEEK;
266
267             firstRunTime.set(Calendar.MINUTE, minute.intValue());
268             firstRunTime.set(Calendar.HOUR_OF_DAY, hour.intValue());
269             firstRunTime.set(Calendar.DAY_OF_WEEK, dayOfWeek.getOrdinal());
270
271             Date JavaDoc now = new Date JavaDoc();
272             if (firstRunTime.getTime().compareTo(now) <= 0) {
273                 firstRunTime.add(Calendar.WEEK_OF_MONTH, 1);
274             }
275
276         } else {
277             // I don't think this can ever happen
278
throw new InvalidConfigurationException(
279                 this.getClass(),
280                 taskConfiguration.getConfigurationName(),
281                 "all attributes",
282                 "Could not determine first run time or repeat period");
283         }
284
285         this.time = firstRunTime.getTime();
286
287         if (log.isTraceEnabled()) {
288             log.trace("Creating task defined by configuration ["
289                 + taskConfiguration.getConfigurationName()
290                 + "] to run starting at ["
291                 + this.time
292                 + "] with period ["
293                 + this.period
294                 + "] ms");
295         }
296
297     }
298
299     /**
300      * @see AbstractTask#schedule(Timer)
301      */

302     public void schedule(Timer JavaDoc timer) {
303         timer.scheduleAtFixedRate(getTask(), this.time, this.period);
304     }
305
306     /**
307      * Checks to make sure that value is within min and max values
308      *
309      * @param configName configuration the value being validated comes from
310      * @param attributeName name of attribute being validated
311      * @param value the value of the attribute
312      * @param minValue the minimum valid value
313      * @param maxValue the maximum valid value
314      */

315     private void validate(String JavaDoc configName,
316         String JavaDoc attributeName,
317         Integer JavaDoc value,
318         int minValue,
319         int maxValue) {
320
321         if (value != null
322                 && !isWithinRange(value.intValue(), minValue, maxValue)) {
323
324             throw new InvalidConfigurationException(
325                 this.getClass(),
326                 configName,
327                 attributeName,
328                 "Value ["
329                     + value
330                     + "] out of range: min ["
331                     + minValue
332                     + "], max ["
333                     + maxValue
334                     + "] inclusive");
335         }
336     }
337
338     /**
339      * Checks if a value is in given range.
340      *
341      * @param value the value to check
342      * @param min the mininum the value should be
343      * @param max the maximum the value should be
344      * @return if the value is with the range
345      */

346     private boolean isWithinRange(int value, int min, int max) {
347         if (value < min || value > max) {
348             return false;
349         } else {
350             return true;
351         }
352     }
353 }
354
Popular Tags