001: /*--
002:
003: Copyright (C) 2000-2003 Anthony Eden.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The name "EdenLib" must not be used to endorse or promote products
019: derived from this software without prior written permission. For
020: written permission, please contact me@anthonyeden.com.
021:
022: 4. Products derived from this software may not be called "EdenLib", nor
023: may "EdenLib" appear in their name, without prior written permission
024: from Anthony Eden (me@anthonyeden.com).
025:
026: In addition, I request (but do not require) that you include in the
027: end-user documentation provided with the redistribution and/or in the
028: software itself an acknowledgement equivalent to the following:
029: "This product includes software developed by
030: Anthony Eden (http://www.anthonyeden.com/)."
031:
032: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
033: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
034: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
035: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
036: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
037: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
038: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
039: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
040: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
041: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
042: POSSIBILITY OF SUCH DAMAGE.
043:
044: For more information on EdenLib, please see <http://edenlib.sf.net/>.
045:
046: */
047:
048: package com.anthonyeden.lib.util;
049:
050: import java.io.File;
051:
052: import com.anthonyeden.lib.Reloadable;
053:
054: import org.apache.commons.logging.Log;
055: import org.apache.commons.logging.LogFactory;
056:
057: /** Class which monitors a file in a thread separate from the main application.
058: If the file changes then the reload() method of the given target will be
059: executed.
060:
061: @author Anthony Eden
062: */
063:
064: public class FileMonitor implements Runnable {
065:
066: /** The default delay value (5 seconds) for checking for modifications. */
067: public static final int DEFAULT_DELAY = 5000;
068:
069: private static final Log log = LogFactory.getLog(FileMonitor.class);
070:
071: private File file;
072: private long delay;
073: private Reloadable target;
074: private long lastModified;
075:
076: private Thread thread;
077: private boolean running = false;
078:
079: /** Construct a new FileMonitor for the given file and target. The default
080: delay time will be used.
081:
082: @param file The file to monitor
083: @param target The target
084: */
085:
086: public FileMonitor(File file, Reloadable target) {
087: this (file, DEFAULT_DELAY, target);
088: }
089:
090: /** Construct a new FileMonitor for the given file and target. The given
091: delay time will be used.
092:
093: @param file The file to monitor
094: @param delay The delay time
095: @param target The target
096: */
097:
098: public FileMonitor(File file, long delay, Reloadable target) {
099: this .file = file;
100: this .delay = delay;
101: this .target = target;
102:
103: lastModified = file.lastModified();
104: }
105:
106: /** Start the monitoring thread. If the thread is already running then
107: this method will not attempt to start a new thread.
108: */
109:
110: public void startMonitor() {
111: if (!running) {
112: log.debug("Starting FileMonitor");
113:
114: running = true;
115: thread = new Thread(this );
116: thread.setDaemon(true);
117: thread.start();
118: }
119: }
120:
121: /** Stop the monitoring thread. If the monitoring thread is not running
122: then this method will do nothing.
123: */
124:
125: public void stopMonitor() {
126: if (thread != null && running) {
127: log.debug("Stopping FileMonitor");
128:
129: running = false;
130: thread.interrupt();
131: }
132: }
133:
134: /** Get the file which is being monitored.
135:
136: @return The monitored file
137: */
138:
139: public File getFile() {
140: return file;
141: }
142:
143: /** Get the delay between file checks.
144:
145: @return The delay in milliseconds
146: */
147:
148: public long getDelay() {
149: return delay;
150: }
151:
152: /** Set the delay between checks. If the thread is already sleeping then
153: this delay will take effect during the next sleep.
154:
155: @param delay The delay in milliseconds
156: */
157:
158: public void setDelay(long delay) {
159: this .delay = delay;
160: }
161:
162: /** The thread's run method. This method should not be executed directly
163: nor should a thread be manually created, rather the <code>startMonitor()</code>
164: and <code>stopMonitor()</code> methods should be used to start and stop
165: the monitor.
166: */
167:
168: public void run() {
169: log.debug("FileMonitor running.");
170: while (running) {
171: try {
172: Thread.sleep(delay);
173: } catch (InterruptedException e) {
174: // do nothing
175: }
176:
177: long currentLastModified = file.lastModified();
178: if (currentLastModified != lastModified) {
179: log.info("Reloading " + file);
180: target.reload();
181: lastModified = currentLastModified;
182: }
183: }
184: log.debug("FileMonitor stopped.");
185: }
186:
187: }
|