/*
* @(#)DefaultPTimer.java 1.11 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package com.sun.util;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
/** An implementaion of the PTimer class which uses the java.util.Timer class
to implement scheduling. PTimer is now deprecated and so it is preferrable to
use java.util.Timer instead. We also manage a saving of about 900 bytes in the
process!
*/
final class DefaultPTimer extends PTimer {
public void schedule(PTimerSpec spec) {
// Create a TimerTask to notify the listeners of the
// spec when it is run by the timer
TimerTask timerTask = new SpecTimerTask(spec, this);
synchronized (this) {
// Store a map of specs to tasks so that we can deschedule
// the tasks.
Object tasks = specToTasksMap.get(spec);
if (tasks == null) {
// Haven't scheduled a task before so just store it directly
// in the Map. We don't create a List yet because it is unlikely
// that it will ever be required.
specToTasksMap.put(spec, timerTask);
} else if (tasks instanceof TimerTask) {
// One TimerTask already exists for this spec so we need to create a list
// to store the existing TimerTask and the new one.
List taskList = new LinkedList();
taskList.add(tasks);
taskList.add(timerTask);
specToTasksMap.put(spec, taskList);
} else {
// Already scheduled more than one task for this PTimerSpec
// so add the new task to the list.
synchronized (tasks) {
((List) tasks).add(timerTask);
}
}
}
// Schedule the TimerTask on the Timer.
long time = spec.getTime();
if (spec.isAbsolute())
timer.schedule(timerTask, new Date(time));
else {
if (spec.isRepeat()) {
if (spec.isRegular())
timer.scheduleAtFixedRate(timerTask, time, time);
else timer.schedule(timerTask, time, time);
} else timer.schedule(timerTask, time);
}
}
public PTimerSpec scheduleTimerSpec(PTimerSpec t) {
// It is more efficient to call it this way than from the deprecated method as we
// would have to catch an exception that is never thrown.
schedule(t);
return t;
}
public void deschedule(PTimerSpec t) {
Object tasks = null;
synchronized (this) {
tasks = specToTasksMap.get(t);
// No tasks to cancel
if (tasks == null)
return;
specToTasksMap.remove(t);
}
// A List of tasks to cancel
if (tasks instanceof List) {
Iterator i = ((List) tasks).iterator();
synchronized (tasks) {
while (i.hasNext())
((TimerTask) i.next()).cancel();
}
} // Just one task to cancel
else ((TimerTask) tasks).cancel();
}
public long getMinRepeatInterval() {
return (long) -1;
}
public long getGranularity() {
return (long) -1;
}
/** The Timer used to implement the scheduling for this PTimer. */
private Timer timer = new Timer();
/** A Map which maps PTimerSpecs to the TimerTasks which have been scheduled on the
Timer. The key is a PTimerSpec and the value is either a List of TimerTasks
running for that spec or just a single TimerTask object. This prevents creating
a List when the majority of the time a PTimerSpec is only going to be scheduled
once with a PTimer. */
private Map specToTasksMap = new HashMap();
}
/** TimerTask which will notify the listeners of the corresponding PTimerSpec
when it is run by the Timer. */
class SpecTimerTask extends TimerTask {
/** Creates a new SpecTimerTask which will notify the listeners of the
PTimerSpec. The PTimer supplied will be the source of events fired
to the listeners. */
public SpecTimerTask(PTimerSpec spec, PTimer timer) {
this.spec = spec;
this.timer = timer;
}
public void run() {
spec.notifyListeners(timer);
}
/** The PTimerSpec to notify listeners for. */
private PTimerSpec spec;
/** The PTimer that created this task and is the source for PTimerWentOffEvents. */
private PTimer timer;
}