package com.dgrid.util.io; import java.util.*; import java.io.File; import java.lang.ref.WeakReference; public class FileMonitor { private Timer timer_; private HashMap<File, Long> files_; private Collection<WeakReference<FileListener>> listeners_; public FileMonitor(long pollingInterval) { files_ = new HashMap<File, Long>(); listeners_ = new ArrayList<WeakReference<FileListener>>(); timer_ = new Timer(true); timer_.schedule(new FileMonitorNotifier(), 0, pollingInterval); } public void stop() { timer_.cancel(); } public void addFile(File file) { if (!files_.containsKey(file)) { long modifiedTime = file.exists() ? file.lastModified() : -1; files_.put(file, new Long(modifiedTime)); } } public void removeFile(File file) { files_.remove(file); } public void addListener(FileListener fileListener) { // Don't add if its already there for (WeakReference<FileListener> reference : listeners_) { FileListener listener = 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>(fileListener)); } public void removeListener(FileListener fileListener) { for (Iterator<WeakReference<FileListener>> i = listeners_.iterator(); i .hasNext();) { WeakReference<FileListener> reference = i.next(); FileListener listener = reference.get(); if (listener == fileListener) { i.remove(); break; } } } private class 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<File> files = new ArrayList<File>(files_.keySet()); for (Iterator<File> i = files.iterator(); i.hasNext();) { File file = i.next(); long lastModifiedTime = ((Long) files_.get(file)).longValue(); long newModifiedTime = file.exists() ? file.lastModified() : -1; // Check if file has changed if (newModifiedTime != lastModifiedTime) { // Register new modified time files_.put(file, new Long(newModifiedTime)); // Notify listeners for (Iterator<WeakReference<FileListener>> j = listeners_ .iterator(); j.hasNext();) { WeakReference<FileListener> reference = j.next(); FileListener listener = (FileListener) reference.get(); // Remove from list if the back-end object has been GC'd if (listener == null) j.remove(); else listener.fileChanged(file); } } } } } }