KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > nava > informa > utils > toolkit > Scheduler


1 //
2
// Informa -- RSS Library for Java
3
// Copyright (c) 2002 by Niko Schmuck
4
//
5
// Niko Schmuck
6
// http://sourceforge.net/projects/informa
7
// mailto:niko_schmuck@users.sourceforge.net
8
//
9
// This library is free software.
10
//
11
// You may redistribute it and/or modify it under the terms of the GNU
12
// Lesser General Public License as published by the Free Software Foundation.
13
//
14
// Version 2.1 of the license should be included with this distribution in
15
// the file LICENSE. If the license is not included with this distribution,
16
// you may find a copy at the FSF web site at 'www.gnu.org' or 'www.fsf.org',
17
// or you may write to the Free Software Foundation, 675 Mass Ave, Cambridge,
18
// MA 02139 USA.
19
//
20
// This library is distributed in the hope that it will be useful,
21
// but WITHOUT ANY WARRANTY; without even the implied waranty of
22
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
// Lesser General Public License for more details.
24
//
25
// $Id: Scheduler.java,v 1.3 2004/09/30 17:28:03 spyromus Exp $
26
//
27

28 package de.nava.informa.utils.toolkit;
29
30 import de.nava.informa.core.ChannelIF;
31
32 import java.util.IdentityHashMap JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Timer JavaDoc;
35 import java.util.TimerTask JavaDoc;
36
37 /**
38  * Scheduler of channel-related events. It uses <code>Timer</code> object to build events
39  * firing plan. Using this class it is possible to scheduler big number of events related
40  * to different channels with individual period and priority settings. It is also possible
41  * to unsechedule processing of channels, reschedule to another period and request
42  * immediate firing of processing event with consequent rebuilding of events plan.
43  *
44  * @author Aleksey Gureev (spyromus@noizeramp.com)
45  */

46 public class Scheduler {
47   private Timer JavaDoc timer;
48   private SchedulerCallbackIF callback;
49   private Map JavaDoc timers = new IdentityHashMap JavaDoc();
50
51   /**
52    * Creates scheduler object.
53    *
54    * @param callback callback object.
55    */

56   public Scheduler(SchedulerCallbackIF callback) {
57     this.callback = callback;
58
59     timer = new Timer JavaDoc(true);
60   }
61
62   /**
63    * Schedule single channel for poller.
64    *
65    * @param channel channel to schedule for poller.
66    * @param period period of poller.
67    * @param priority priority of the task.
68    */

69   public final void schedule(ChannelIF channel, long period, int priority) {
70     // create record
71
ChannelRecord record = new ChannelRecord(channel, period, priority);
72
73     resched(record, period);
74   }
75
76   /**
77    * Stop poller the channel.
78    *
79    * @param channel channel to poll no more.
80    */

81   public final void unschedule(ChannelIF channel) {
82     ChannelRecord record = null;
83     synchronized (timers) {
84       SchedulerTask tt = (SchedulerTask) timers.get(channel);
85       if (tt != null) {
86         timers.remove(channel);
87         tt.cancel();
88         record = tt.getRecord();
89         record.setCanceled(true);
90       }
91     }
92   }
93
94   /**
95    * Triggers channel event immediately (if it is registered) and reschedules consequent events.
96    *
97    * @param channel channel.
98    */

99   public final void triggerNow(ChannelIF channel) {
100     final SchedulerTask task;
101     synchronized (timers) {
102       task = (SchedulerTask) timers.get(channel);
103     }
104     if (task != null) {
105       final ChannelRecord record = task.getRecord();
106       resched(record, record.getPeriod());
107     }
108   }
109
110   /**
111    * Reschedules all of the tasks with new period setting.
112    *
113    * @param period period in millis.
114    */

115   public final synchronized void rescheduleAll(long period) {
116     final ChannelIF[] channels;
117
118     // Quickly get the list of current timers.
119
synchronized (timers) {
120       channels = (ChannelIF[]) timers.keySet().toArray(new ChannelIF[0]);
121     }
122
123     // Reschedule all registered channels.
124
for (int i = 0; i < channels.length; i++) {
125       final ChannelIF channel = channels[i];
126       rescheduleChannel(channel, period);
127     }
128   }
129
130   /**
131    * Reschedules single channel. If channel isn't registered yet it will be registered with
132    * normal priority.
133    *
134    * @param channel channel.
135    * @param period new period.
136    */

137   public final void rescheduleChannel(final ChannelIF channel, long period) {
138     final SchedulerTask task = (SchedulerTask) timers.get(channel);
139
140     if (task == null) {
141       schedule(channel, period, ChannelRecord.PRIO_NORMAL);
142     } else {
143       final ChannelRecord record = task.getRecord();
144
145       // Cancel current task.
146
synchronized (timers) {
147         timers.remove(channel);
148       }
149
150       task.cancel();
151
152       // Create new task.
153
// The way we compute delay we make user see next channel poll according to new schedule.
154
// If, for example, old period is 2 mins, new period is 1 minute and 1.5 minutes already
155
// passed since last poll delay will be equal to 0, which will result in immediate poll.
156
// If, old period is 1 minute, new one is 2 minutes and 1.5 minutes passed already then
157
// delay will be 0.5 to compensate the difference.
158
long timePassed = System.currentTimeMillis() - task.scheduledExecutionTime();
159       long delay = 0;
160       if (timePassed >= 0) {
161         delay = period - timePassed;
162         if (delay < 0) {
163           delay = 0;
164         }
165       }
166
167       sched(record, delay, period);
168     }
169   }
170
171   /**
172    * Reschedule single record.
173    *
174    * @param record record.
175    * @param period period.
176    */

177   private void resched(ChannelRecord record, long period) {
178     ChannelIF channel = record.getChannel();
179
180     // remove existing task
181
unschedule(channel);
182
183     // schedule new task
184
sched(record, 0, period);
185   }
186
187   /**
188    * Unconditional scheduling of single record.
189    *
190    * @param record record.
191    * @param delay delay before the first run.
192    * @param period period in millis.
193    */

194   private void sched(ChannelRecord record, long delay, long period) {
195     record.setCanceled(false);
196
197     ChannelIF channel = record.getChannel();
198     SchedulerTask tt = new SchedulerTask(record);
199
200     synchronized (timers) {
201       timers.put(channel, tt);
202     }
203
204     timer.schedule(tt, delay, period);
205   }
206
207   /**
208    * Periodical task which checks given channel from time to time.
209    */

210   private class SchedulerTask extends TimerTask JavaDoc {
211     private ChannelRecord record;
212
213     /**
214      * Creates scheduler task for given channel record.
215      *
216      * @param record record.
217      */

218     public SchedulerTask(ChannelRecord record) {
219       this.record = record;
220     }
221
222     /**
223      * The action to be performed by this timer task.
224      */

225     public void run() {
226       callback.process(record);
227     }
228
229     /**
230      * Returns channel record.
231      *
232      * @return record.
233      */

234     public ChannelRecord getRecord() {
235       return record;
236     }
237   }
238 }
239
Popular Tags