--- /dev/null
+package compbio.stat.servlet.util;
+
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * A <code>RefreshIterator</code> returns a sequence of dates on subsequent days
+ * representing the same time each day.
+ */
+public class RefreshIterator implements ScheduleIterator {
+ private final int hourOfDay, minute, second, freq_time;
+ private final Calendar calendar = Calendar.getInstance();
+
+ public RefreshIterator(int hourOfDay, int minute, int second, int freq_time) {
+ this(hourOfDay, minute, second, freq_time, new Date());
+ }
+
+ public RefreshIterator(int hourOfDay, int minute, int second, int freq_time, Date date) {
+ this.hourOfDay = hourOfDay;
+ this.minute = minute;
+ this.second = second;
+ this.freq_time = freq_time;
+ calendar.setTime(date);
+ calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ calendar.set(Calendar.MINUTE, minute);
+ calendar.set(Calendar.SECOND, second);
+ calendar.set(Calendar.MILLISECOND, 0);
+ }
+
+ public Date next() {
+ calendar.add(Calendar.MINUTE, this.freq_time);
+ return calendar.getTime();
+ }
+
+}
--- /dev/null
+package compbio.stat.servlet.util;
+
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+/**
+ * A facility for threads to schedule recurring tasks for future
+ * execution in a background thread.
+ * <p>
+ * This class is thread-safe: multiple threads can share a single
+ * <code>Scheduler</code> object without the need for external synchronization.
+ * <p>
+ * Implementation note: internally <code>Scheduler</code> uses a
+ * <code>java.util.Timer</code> to schedule tasks.
+ */
+public class Scheduler {
+
+ class SchedulerTimerTask extends TimerTask {
+ private SchedulerTask schedulerTask;
+ private ScheduleIterator iterator;
+
+ public SchedulerTimerTask(SchedulerTask schedulerTask,
+ ScheduleIterator iterator) {
+ this.schedulerTask = schedulerTask;
+ this.iterator = iterator;
+ }
+
+ public void run() {
+ schedulerTask.run();
+ reschedule(schedulerTask, iterator);
+ }
+ }
+
+ private final Timer timer = new Timer();
+
+ public Scheduler() {
+ }
+
+ /**
+ * Terminates this <code>Scheduler</code>, discarding any currently scheduled tasks.
+ * Does not interfere with a currently executing task (if it exists). Once a scheduler
+ * has been terminated, its execution thread terminates gracefully, and no more tasks
+ * may be scheduled on it.
+ * <p>
+ * Note that calling this method from within the run method of a scheduler task that was
+ * invoked by this scheduler absolutely guarantees that the ongoing task execution is the
+ * last task execution that will ever be performed by this scheduler.
+ * <p>
+ * This method may be called repeatedly; the second and subsequent calls have no effect.
+ */
+
+ public void cancel() {
+ timer.cancel();
+ }
+
+ /**
+ * Schedules the specified task for execution according to the specified schedule. If times
+ * specified by the <code>ScheduleIterator</code> are in the past they are scheduled for
+ * immediate execution.
+ * <p>
+ *
+ * @param schedulerTask task to be scheduled
+ * @param iterator iterator that describes the schedule
+ * @throws IllegalStateException if task was already scheduled or cancelled, scheduler was
+ * cancelled, or scheduler thread terminated.
+ */
+
+ public void schedule(SchedulerTask schedulerTask,
+ ScheduleIterator iterator) {
+
+ Date time = iterator.next();
+ if (time == null) {
+ schedulerTask.cancel();
+ } else {
+ synchronized (schedulerTask.lock) {
+ if (schedulerTask.state != SchedulerTask.VIRGIN) {
+ throw new IllegalStateException("Task already scheduled " +
+ "or cancelled");
+ }
+ schedulerTask.state = SchedulerTask.SCHEDULED;
+ schedulerTask.timerTask =
+ new SchedulerTimerTask(schedulerTask, iterator);
+ timer.schedule(schedulerTask.timerTask, time);
+ }
+ }
+ }
+
+ private void reschedule(SchedulerTask schedulerTask,
+ ScheduleIterator iterator) {
+
+ Date time = iterator.next();
+ if (time == null) {
+ schedulerTask.cancel();
+ } else {
+ synchronized (schedulerTask.lock) {
+ if (schedulerTask.state != SchedulerTask.CANCELLED) {
+ schedulerTask.timerTask =
+ new SchedulerTimerTask(schedulerTask, iterator);
+ timer.schedule(schedulerTask.timerTask, time);
+ }
+ }
+ }
+ }
+
+}
+
--- /dev/null
+package compbio.stat.servlet.util;
+
+import java.util.TimerTask;
+
+
+/**
+ * A task that can be scheduled for recurring execution by a {@link Scheduler}.
+ */
+public abstract class SchedulerTask implements Runnable {
+
+ final Object lock = new Object();
+
+ int state = VIRGIN;
+ static final int VIRGIN = 0;
+ static final int SCHEDULED = 1;
+ static final int CANCELLED = 2;
+
+ TimerTask timerTask;
+
+ /**
+ * Creates a new scheduler task.
+ */
+
+ protected SchedulerTask() {
+ }
+
+ /**
+ * The action to be performed by this scheduler task.
+ */
+
+ public abstract void run();
+
+ /**
+ * Cancels this scheduler task.
+ * <p>
+ * This method may be called repeatedly; the second and subsequent calls have no effect.
+ *
+ * @return true if this task was already scheduled to run
+ */
+
+ public boolean cancel() {
+ synchronized (lock) {
+ if (timerTask != null) {
+ timerTask.cancel();
+ }
+ boolean result = (state == SCHEDULED);
+ state = CANCELLED;
+ return result;
+ }
+ }
+
+ /**
+ * Returns the <i>scheduled</i> execution time of the most recent actual execution of
+ * this task. (If this method is invoked while task execution is in progress,
+ * the return value is the scheduled execution time of the ongoing task execution.)
+ *
+ * @return the time at which the most recent execution of this task was scheduled
+ * to occur, in the format returned by <code>Date.getTime()</code>. The return value
+ * is undefined if the task has yet to commence its first execution.
+ */
+
+ public long scheduledExecutionTime() {
+ synchronized (lock) {
+ return timerTask == null ? 0 : timerTask.scheduledExecutionTime();
+ }
+ }
+
+}