001: /*
002: * @(#)DefaultPTimer.java 1.11 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package com.sun.util;
029:
030: import java.util.Timer;
031: import java.util.TimerTask;
032: import java.util.Date;
033: import java.util.Map;
034: import java.util.HashMap;
035: import java.util.List;
036: import java.util.LinkedList;
037: import java.util.Iterator;
038:
039: /** An implementaion of the PTimer class which uses the java.util.Timer class
040: to implement scheduling. PTimer is now deprecated and so it is preferrable to
041: use java.util.Timer instead. We also manage a saving of about 900 bytes in the
042: process!
043: */
044:
045: final class DefaultPTimer extends PTimer {
046: public void schedule(PTimerSpec spec) {
047: // Create a TimerTask to notify the listeners of the
048: // spec when it is run by the timer
049:
050: TimerTask timerTask = new SpecTimerTask(spec, this );
051: synchronized (this ) {
052: // Store a map of specs to tasks so that we can deschedule
053: // the tasks.
054:
055: Object tasks = specToTasksMap.get(spec);
056: if (tasks == null) {
057: // Haven't scheduled a task before so just store it directly
058: // in the Map. We don't create a List yet because it is unlikely
059: // that it will ever be required.
060:
061: specToTasksMap.put(spec, timerTask);
062: } else if (tasks instanceof TimerTask) {
063: // One TimerTask already exists for this spec so we need to create a list
064: // to store the existing TimerTask and the new one.
065:
066: List taskList = new LinkedList();
067: taskList.add(tasks);
068: taskList.add(timerTask);
069: specToTasksMap.put(spec, taskList);
070: } else {
071: // Already scheduled more than one task for this PTimerSpec
072: // so add the new task to the list.
073:
074: synchronized (tasks) {
075: ((List) tasks).add(timerTask);
076: }
077: }
078: }
079: // Schedule the TimerTask on the Timer.
080:
081: long time = spec.getTime();
082: if (spec.isAbsolute())
083: timer.schedule(timerTask, new Date(time));
084: else {
085: if (spec.isRepeat()) {
086: if (spec.isRegular())
087: timer.scheduleAtFixedRate(timerTask, time, time);
088: else
089: timer.schedule(timerTask, time, time);
090: } else
091: timer.schedule(timerTask, time);
092: }
093: }
094:
095: public PTimerSpec scheduleTimerSpec(PTimerSpec t) {
096: // It is more efficient to call it this way than from the deprecated method as we
097: // would have to catch an exception that is never thrown.
098:
099: schedule(t);
100: return t;
101: }
102:
103: public void deschedule(PTimerSpec t) {
104: Object tasks = null;
105: synchronized (this ) {
106: tasks = specToTasksMap.get(t);
107: // No tasks to cancel
108:
109: if (tasks == null)
110: return;
111: specToTasksMap.remove(t);
112: }
113: // A List of tasks to cancel
114:
115: if (tasks instanceof List) {
116: Iterator i = ((List) tasks).iterator();
117: synchronized (tasks) {
118: while (i.hasNext())
119: ((TimerTask) i.next()).cancel();
120: }
121: } // Just one task to cancel
122: else
123: ((TimerTask) tasks).cancel();
124: }
125:
126: public long getMinRepeatInterval() {
127: return (long) -1;
128: }
129:
130: public long getGranularity() {
131: return (long) -1;
132: }
133:
134: /** The Timer used to implement the scheduling for this PTimer. */
135:
136: private Timer timer = new Timer();
137: /** A Map which maps PTimerSpecs to the TimerTasks which have been scheduled on the
138: Timer. The key is a PTimerSpec and the value is either a List of TimerTasks
139: running for that spec or just a single TimerTask object. This prevents creating
140: a List when the majority of the time a PTimerSpec is only going to be scheduled
141: once with a PTimer. */
142:
143: private Map specToTasksMap = new HashMap();
144: }
145:
146: /** TimerTask which will notify the listeners of the corresponding PTimerSpec
147: when it is run by the Timer. */
148:
149: class SpecTimerTask extends TimerTask {
150: /** Creates a new SpecTimerTask which will notify the listeners of the
151: PTimerSpec. The PTimer supplied will be the source of events fired
152: to the listeners. */
153:
154: public SpecTimerTask(PTimerSpec spec, PTimer timer) {
155: this .spec = spec;
156: this .timer = timer;
157: }
158:
159: public void run() {
160: spec.notifyListeners(timer);
161: }
162:
163: /** The PTimerSpec to notify listeners for. */
164:
165: private PTimerSpec spec;
166: /** The PTimer that created this task and is the source for PTimerWentOffEvents. */
167:
168: private PTimer timer;
169: }
|