import java.io.File;
-import org.vamsas.client.SimpleClient;
/**
* @author jim Watches a particular file for its creation, deletion, or
private File subject = null;
private long lastStat[];
-
+ boolean waslocked=false;
boolean exists = false;
-
/**
- * 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
+ * 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()) {
- Lock tl = new Lock(subject);
- if (tl.isLocked()) {
- tl.release();
+ if (subjectLock!=null) {
+ subjectLock.release();
+ }
+ subjectLock = new Lock(subject);
+ if (subjectLock.isLocked()) {
+ // subjectLock.release();
return false;
- } else {
- return true;
}
+ 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.hashCode()!=newstat.hashCode())
+ 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) {
- exists = false;
- return true;
+ 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 (exists && ((compStat(lastStat, newStat) || checkLock()))) {
+ 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;
}
- lastStat = newStat;
- exists = true;
- return true;
}
}
return false;
}
-
+ /**
+ * updates internal record of file state when caller has intentionally
+ * modified subject. (ignores locked-state of subject)
+ */
+ public void setState() {
+ if (subject!=null) {
+ if (exists = subject.exists()) {
+ lastStat = getStat(subject);
+ waslocked = false;
+ }
+ }
+ }
+
+ /**
+ * 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;
- check();
+ 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() {
- return check();
+ 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;
+ }
}
}