001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.runtime.java.util;
032:
033: import java.util.concurrent.*;
034: import java.util.concurrent.atomic.AtomicInteger;
035: import java.util.Date;
036: import net.sf.retrotranslator.registry.Advanced;
037:
038: /**
039: * @author Taras Puchko
040: */
041: @Advanced("Timer.All")
042: public class Timer_ {
043:
044: private static AtomicInteger counter = new AtomicInteger();
045:
046: private final ScheduledThreadPoolExecutor executor;
047:
048: private final Object finalizer = new Object() {
049: protected void finalize() throws Throwable {
050: executor.shutdown();
051: }
052: };
053:
054: public Timer_() {
055: this (false);
056: }
057:
058: public Timer_(boolean isDaemon) {
059: this ("Timer-" + counter.getAndIncrement(), isDaemon);
060: }
061:
062: public Timer_(String name) {
063: this (name, false);
064: }
065:
066: public Timer_(final String name, final boolean isDaemon) {
067: executor = new ScheduledThreadPoolExecutor(1,
068: new TimerThreadFactory(name, isDaemon));
069: executor
070: .setRejectedExecutionHandler(new TimerRejectedExecutionHandler());
071: executor
072: .setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
073: executor.prestartCoreThread();
074: }
075:
076: public void cancel() {
077: executor
078: .setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
079: executor
080: .setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
081: executor.shutdown();
082: }
083:
084: public int purge() {
085: int count = 0;
086: BlockingQueue queue = executor.getQueue();
087: for (Object object : queue.toArray()) {
088: if (object instanceof Future
089: && ((Future) object).isCancelled()) {
090: if (queue.remove(object)) {
091: count++;
092: }
093: }
094: }
095: return count;
096: }
097:
098: public void schedule(TimerTask_ task, Date time) {
099: long delay = checkDelay(time);
100: task.command.runOnce(executor, delay);
101: }
102:
103: public void schedule(TimerTask_ task, Date firstTime, long period) {
104: checkPeriod(period);
105: long delay = checkDelay(firstTime);
106: task.command.runWithFixedDelay(executor, delay, period);
107: }
108:
109: public void scheduleAtFixedRate(TimerTask_ task, Date firstTime,
110: long period) {
111: checkPeriod(period);
112: long delay = checkDelay(firstTime);
113: task.command.runAtFixedRate(executor, delay, period);
114: }
115:
116: public void schedule(TimerTask_ task, long delay) {
117: checkDelay(delay);
118: task.command.runOnce(executor, delay);
119: }
120:
121: public void schedule(TimerTask_ task, long delay, long period) {
122: checkDelay(delay);
123: checkPeriod(period);
124: task.command.runWithFixedDelay(executor, delay, period);
125: }
126:
127: public void scheduleAtFixedRate(TimerTask_ task, long delay,
128: long period) {
129: checkDelay(delay);
130: checkPeriod(period);
131: task.command.runAtFixedRate(executor, delay, period);
132: }
133:
134: private static long checkDelay(Date date) {
135: long time = date.getTime();
136: if (time < 0) {
137: throw new IllegalArgumentException();
138: }
139: return time - System.currentTimeMillis();
140: }
141:
142: private static void checkDelay(long delay) {
143: if (delay < 0 || delay + System.currentTimeMillis() < 0) {
144: throw new IllegalArgumentException();
145: }
146: }
147:
148: private static void checkPeriod(long period) {
149: if (period <= 0) {
150: throw new IllegalArgumentException();
151: }
152: }
153:
154: private static class TimerThreadFactory implements ThreadFactory {
155: private final String name;
156: private final boolean daemon;
157:
158: public TimerThreadFactory(String name, boolean daemon) {
159: this .name = name;
160: this .daemon = daemon;
161: }
162:
163: public Thread newThread(Runnable runnable) {
164: Thread thread = new Thread(runnable);
165: thread.setName(name);
166: thread.setDaemon(daemon);
167: return thread;
168: }
169: }
170:
171: private static class TimerRejectedExecutionHandler implements
172: RejectedExecutionHandler {
173: public void rejectedExecution(Runnable r,
174: ThreadPoolExecutor executor) {
175: throw new IllegalStateException();
176: }
177: }
178:
179: }
|