001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.util;
020:
021: import java.util.Enumeration;
022: import java.util.Vector;
023:
024: /**
025: * Generalization of <code>ExecuteWatchdog</code>
026: *
027: * @since Ant 1.5
028: *
029: * @see org.apache.tools.ant.taskdefs.ExecuteWatchdog
030: *
031: */
032: public class Watchdog implements Runnable {
033:
034: private Vector observers = new Vector(1);
035: private long timeout = -1;
036: /**
037: * marked as volatile to stop the compiler caching values or (in java1.5+,
038: * reordering access)
039: */
040: private volatile boolean stopped = false;
041: /**
042: * Error string.
043: * {@value}
044: */
045: public static final String ERROR_INVALID_TIMEOUT = "timeout less than 1.";
046:
047: /**
048: * Constructor for Watchdog.
049: * @param timeout the timeout to use in milliseconds (must be >= 1).
050: */
051: public Watchdog(long timeout) {
052: if (timeout < 1) {
053: throw new IllegalArgumentException(ERROR_INVALID_TIMEOUT);
054: }
055: this .timeout = timeout;
056: }
057:
058: /**
059: * Add a timeout observer.
060: * @param to the timeout observer to add.
061: */
062: public void addTimeoutObserver(TimeoutObserver to) {
063: //no need to synchronize, as Vector is always synchronized
064: observers.addElement(to);
065: }
066:
067: /**
068: * Remove a timeout observer.
069: * @param to the timeout observer to remove.
070: */
071: public void removeTimeoutObserver(TimeoutObserver to) {
072: //no need to synchronize, as Vector is always synchronized
073: observers.removeElement(to);
074: }
075:
076: /**
077: * Inform the observers that a timeout has occurred.
078: * This happens in the watchdog thread.
079: */
080: protected final void fireTimeoutOccured() {
081: Enumeration e = observers.elements();
082: while (e.hasMoreElements()) {
083: ((TimeoutObserver) e.nextElement()).timeoutOccured(this );
084: }
085: }
086:
087: /**
088: * Start the watch dog.
089: */
090: public synchronized void start() {
091: stopped = false;
092: Thread t = new Thread(this , "WATCHDOG");
093: t.setDaemon(true);
094: t.start();
095: }
096:
097: /**
098: * Stop the watch dog.
099: */
100: public synchronized void stop() {
101: stopped = true;
102: notifyAll();
103: }
104:
105: /**
106: * The run method of the watch dog thread.
107: * This simply does a wait for the timeout time, and
108: * if the stop flag has not been set when the wait has returned or
109: * has been interrupted, the watch dog listeners are informed.
110: */
111: public synchronized void run() {
112: final long until = System.currentTimeMillis() + timeout;
113: long now;
114: while (!stopped && until > (now = System.currentTimeMillis())) {
115: try {
116: wait(until - now);
117: } catch (InterruptedException e) {
118: // Ignore exception
119: }
120: }
121: if (!stopped) {
122: fireTimeoutOccured();
123: }
124: }
125:
126: }
|