/** * */ package org.vamsas.client.simpleclient; import java.io.File; import org.vamsas.client.SimpleClient; /** * @author jim Watches a particular file for its creation, deletion, or * modification. */ public class FileWatcher { private File subject = null; private long lastStat[]; boolean waslocked=false; boolean exists = false; /** * transient lock on subject - can be passed back to calling class * to preserve new state of file for immediate reading. */ private Lock subjectLock = null; private void clearLock() { if (subjectLock!=null) subjectLock.release(); subjectLock=null; } private boolean checkLock() { if (subject!=null && subject.exists()) { if (subjectLock!=null) { subjectLock.release(); } subjectLock = new Lock(subject); if (subjectLock.isLocked()) { // subjectLock.release(); return false; } clearLock(); return true; } return false; } private long[] getStat(File subject) { return new long[] { subject.lastModified(), subject.length() }; } private boolean compStat(long[] stat, long[] newstat) { if (stat[0]!=newstat[0] || stat[1]!=newstat[1]) return false; return true; } /** * Detect changes in file state and release of any * lock in place during change. * @return true if file state has changed. Leaves lock in subjectLock (ready to be passed to caller) */ private boolean check() { if (subject != null) { if (!subject.exists()) { if (exists) { if (!waslocked) { // !checkLock()) { exists = false; // waslocked=false; return true; } } // locked - state change registered after lock is released return false; } else { long[] newStat = getStat(subject); // subject.lastModified(); if (!checkLock()) { // file is free to access, return state change if (!exists || !compStat(lastStat, newStat)) { waslocked=false; exists=true; lastStat=newStat; return true; } // no change return false; } else { waslocked=true; return false; } } } return false; } public void setState() { if (subject!=null) { lastStat = getStat(subject); exists = subject.exists(); waslocked = checkLock(); } } /** * Make a watcher for a particular file. If the file doesn't exist, the * watcher will watch for its creation (and indicate a change of state) * For locked files, the removal of a lock constitutes a change of * state if the file was modified. * * @param subject */ public FileWatcher(File subject) { // TODO Auto-generated constructor stub this.subject = subject; setState(); } /** * Test for change in file state. Only indicates a change * after any lock on a file has been released. * @return true if file has been modified. */ public boolean hasChanged() { boolean res = check(); clearLock(); return res; } /** * passes lock back to caller if hasChanged returned true. * @return */ public Lock getChangedState() { boolean res = check(); if (res) return subjectLock; else { clearLock(); return null; } } }