/* * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */package no.geosoft.cc.io;
import java.util.*;
import java.io.File;
import java.lang.ref.WeakReference;
/** * Class for monitoring changes in disk files. * Usage: * * 1. Implement the FileListener interface. * 2. Create a FileMonitor instance. * 3. Add the file(s)/directory(ies) to listen for. * * fileChanged() will be called when a monitored file is created, * deleted or its modified time changes. * * @author <a href="mailto:info@geosoft.no">GeoSoft</a> */publicclass FileMonitor
{
private Timer timer_;
private HashMap files_; // File -> Longprivate Collection listeners_; // of WeakReference(FileListener)/** * Create a file monitor instance with specified polling interval. * * @param pollingInterval Polling interval in milli seconds. */public FileMonitor (long pollingInterval)
{
files_ = new HashMap();
listeners_ = new ArrayList();
timer_ = new Timer (true);
timer_.schedule (new FileMonitorNotifier(), 0, pollingInterval);
}
/** * Stop the file monitor polling. */public void stop()
{
timer_.cancel();
}
/** * Add file to listen for. File may be any java.io.File (including a * directory) and may well be a non-existing file in the case where the * creating of the file is to be trepped. * <p> * More than one file can be listened for. When the specified file is * created, modified or deleted, listeners are notified. * * @param file File to listen for. */public void addFile (File file)
{
if (!files_.containsKey (file)) {
long modifiedTime = file.exists() ? file.lastModified() : -1;
files_.put (file, new Long (modifiedTime));
}
}
/** * Remove specified file for listening. * * @param file File to remove. */public void removeFile (File file)
{
files_.remove (file);
}
/** * Add listener to this file monitor. * * @param fileListener Listener to add. */public void addListener (FileListener fileListener)
{
// Don't add if its already therefor (Iterator i = listeners_.iterator(); i.hasNext(); ) {
WeakReference reference = (WeakReference) i.next();
FileListener listener = (FileListener) reference.get();
if (listener == fileListener)
return;
}
// Use WeakReference to avoid memory leak if this becomes the// sole reference to the object.
listeners_.add (new WeakReference (fileListener));
}
/** * Remove listener from this file monitor. * * @param fileListener Listener to remove. */public void removeListener (FileListener fileListener)
{
for (Iterator i = listeners_.iterator(); i.hasNext(); ) {
WeakReference reference = (WeakReference) i.next();
FileListener listener = (FileListener) reference.get();
if (listener == fileListener) {
i.remove();
break;
}
}
}
/** * This is the timer thread which is executed every n milliseconds * according to the setting of the file monitor. It investigates the * file in question and notify listeners if changed. */privateclass FileMonitorNotifier extends TimerTask
{
public void run()
{
// Loop over the registered files and see which have changed.// Use a copy of the list in case listener wants to alter the// list within its fileChanged method.
Collection files = new ArrayList (files_.keySet());
for (Iterator i = files.iterator(); i.hasNext(); ) {
File file = (File) i.next();
long lastModifiedTime = ((Long) files_.get (file)).longValue();
long newModifiedTime = file.exists() ? file.lastModified() : -1;
// Chek if file has changedif (newModifiedTime != lastModifiedTime) {
// Register new modified time
files_.put (file, new Long (newModifiedTime));
// Notify listenersfor (Iterator j = listeners_.iterator(); j.hasNext(); ) {
WeakReference reference = (WeakReference) j.next();
FileListener listener = (FileListener) reference.get();
// Remove from list if the back-end object has been GC'dif (listener == null)
j.remove();
else
listener.fileChanged (file);
}
}
}
}
}
/** * Test this class. * * @param args Not used. */publicstatic void main (String args[])
{
// Create the monitor
FileMonitor monitor = new FileMonitor (1000);
// Add some files to listen for
monitor.addFile (new File ("/home/jacob/test1.txt"));
monitor.addFile (new File ("/home/jacob/test2.txt"));
monitor.addFile (new File ("/home/jacob/"));
// Add a dummy listener
monitor.addListener (monitor.new TestListener());
// Avoid program exitwhile (!false) ;
}
privateclass TestListener
implements FileListener
{
public void fileChanged (File file)
{
System.out.println ("File changed: " + file);
}
}
}