package edu.washington.cs.oneswarm.watchdir; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.logging.Logger; import org.gudy.azureus2.core3.util.FileUtil; import edu.uw.cse.netlab.reputation.GloballyAwareOneHopUnchoker; import edu.washington.cs.oneswarm.ui.gwt.BackendErrorLog; import edu.washington.cs.oneswarm.ui.gwt.client.newui.settings.MagicPath; import edu.washington.cs.oneswarm.ui.gwt.client.newui.settings.MagicWatchType; public class DirectoryWatcher extends Thread implements UpdatingFileTreeListener { private static Logger logger = Logger.getLogger(DirectoryWatcher.class.getName()); String mPath = null; UpdatingFileTree mTree = null; List<DirectoryWatcherListener> mListeners = Collections .synchronizedList(new LinkedList<DirectoryWatcherListener>()); private int mPollWaitSecs = 60; private boolean mDone; MagicPath mMagicPath = null; private File watchFile; public DirectoryWatcher(MagicPath inMagicPath, int inPollWaitSecs) throws IOException { watchFile = new File(inMagicPath.getPath()); if (watchFile.exists() == false) { throw new IOException("Watch directory doesn't exist!"); } if (watchFile.isDirectory() == false) { throw new IOException("Watch directory needs to be a _directory_!"); } mMagicPath = inMagicPath; mPath = inMagicPath.getPath(); mPollWaitSecs = inPollWaitSecs; long start = System.currentTimeMillis(); logger.fine("initial scan of: " + mPath); mTree = new UpdatingFileTree(watchFile, this, mMagicPath.getMaxDepth()); logger.fine("initial creation took: " + (System.currentTimeMillis() - start) + " ms"); setDaemon(true); setName("DirectoryWatcher: " + inMagicPath); } public String getPath() { return mPath; } public MagicWatchType getWatchType() { return mMagicPath.getType(); } public void setDone() { mDone = true; } public void addListener(DirectoryWatcherListener inListener) { mListeners.add(inListener); } public void removeListener(DirectoryWatcherListener inListener) { mListeners.remove(inListener); } public void broadcastChange(UpdatingFileTree path, boolean isDelete) { synchronized (mListeners) { for (DirectoryWatcherListener listener : mListeners) { if (isDelete) { listener.deleteFileObserved(this, path); } else { listener.newFileObserved(this, path); } } } } /** * TODO: would be nice to use filesystem notifications here. should be * around in java7 (when will this reach macs? 2020?) */ public void run() { long start = System.currentTimeMillis(); while (!mDone) { try { File watchFile = new File(mPath); // deleted? if (watchFile.exists() == false) { FileUtil.mkdirs(watchFile); break; } start = System.currentTimeMillis(); mTree.update(); long refreshTime = (System.currentTimeMillis() - start); logger.fine("refresh took: " + refreshTime + " (" + mTree.thisFile.getAbsolutePath() + ")"); // no less than 10 seconds but not more than 5 minutes long waitTime = Math.min(Math.max(10 * 1000, 60 * refreshTime), 300 * 1000); logger.fine("wait time: " + waitTime); Thread.sleep(waitTime); } catch (Exception e) { e.printStackTrace(); BackendErrorLog.get().logException(e); try { Thread.sleep(1 * 1000); } catch (Exception e2) { } } } } public static void main(String[] args) throws Exception { DirectoryWatcher w = new DirectoryWatcher(new MagicPath("/Volumes/x/watch_test"), 1); w.addListener(new DirectoryWatcherListener() { public void deleteFileObserved(DirectoryWatcher watcher, UpdatingFileTree inAbsolutePath) { logger.finer("deleted: " + inAbsolutePath.thisFile.getAbsolutePath()); } public void newFileObserved(DirectoryWatcher watcher, UpdatingFileTree inAbsolutePath) { logger.finer("created: " + inAbsolutePath.thisFile.getAbsolutePath()); } }); w.run(); } }