VamsasArchive tested. Locked IO routines to be implemented in ArchiveFile
[vamsas.git] / src / org / vamsas / client / simpleclient / FileWatcher.java
1 /**
2  * 
3  */
4 package org.vamsas.client.simpleclient;
5
6 import java.io.File;
7
8
9 /**
10  * @author jim Watches a particular file for its creation, deletion, or
11  *         modification.
12  */
13 public class FileWatcher {
14
15   private File subject = null;
16
17   private long lastStat[];
18   boolean waslocked=false;
19   boolean exists = false;
20   /**
21    * transient lock on subject - can be passed back to calling class
22    * to preserve new state of file for immediate reading.
23    */
24   private Lock subjectLock = null;
25   /**
26    * clear local locks on subject.
27    *
28    */
29   private void clearLock() {
30     if (subjectLock!=null)
31       subjectLock.release();
32     subjectLock=null;
33   }
34   /**
35    * 
36    * @return true if subject exists and is locked by another process.
37    */
38   private boolean checkLock() {
39     if (subject!=null && subject.exists()) {
40       if (subjectLock!=null) {
41         subjectLock.release();
42       }
43       subjectLock = new Lock(subject);
44       if (subjectLock.isLocked()) {
45         // subjectLock.release();
46         return false;
47       }
48       clearLock();
49       return true;
50     }
51     return false;
52   }
53   
54   private long[] getStat(File subject) {
55     return new long[] { subject.lastModified(), subject.length() };
56   }
57   private boolean compStat(long[] stat, long[] newstat) {
58     if (stat[0]!=newstat[0] || stat[1]!=newstat[1])
59       return false;
60     return true;
61   }
62   /**
63    * Detect changes in file state and release of any
64    * lock in place during change.
65    * @return true if file state has changed. Leaves lock in subjectLock (ready to be passed to caller)
66    */
67   private boolean check() {
68     if (subject != null) {
69       if (!subject.exists()) {
70         if (exists) {
71           if (!waslocked) {
72             // !checkLock()) {
73           
74             exists = false;
75             // waslocked=false;
76             return true;
77           }
78         }
79         // locked - state change registered after lock is released
80         return false;
81       } else {
82         long[] newStat = getStat(subject); // subject.lastModified();
83         if (!checkLock()) {
84           // file is free to access, return state change
85           if (!exists || !compStat(lastStat, newStat)) {
86             waslocked=false;
87             exists=true;
88             lastStat=newStat;
89             return true;
90           }
91           // no change
92           return false;
93         } else {
94           waslocked=true;
95           return false;
96         }
97       }
98     }
99     return false;
100   }
101   /**
102    * updates internal record of file state when caller has intentionally
103    * modified subject. (ignores locked-state of subject)
104    */
105   public void setState() {
106     if (subject!=null) {
107       if (exists = subject.exists()) {
108         lastStat = getStat(subject);
109         waslocked = false;
110       }
111     }
112   }
113   
114   /**
115    * Make a watcher for a particular file. If the file doesn't exist, the
116    * watcher will watch for its creation (and indicate a change of state) 
117    * For locked files, the removal of a lock constitutes a change of 
118    * state if the file was modified.
119    * 
120    * @param subject
121    */
122   
123   public FileWatcher(File subject) {
124     // TODO Auto-generated constructor stub
125     this.subject = subject;
126     setState();
127   }
128   /**
129    * Test for change in file state. Only indicates a change 
130    * after any lock on a file has been released.
131    * @return true if file has been modified.
132    */
133   public boolean hasChanged() {
134     boolean res = check();
135     clearLock();
136     return res;
137   }
138   /**
139    * passes lock back to caller if hasChanged returned true.
140    * @return
141    */
142   public Lock getChangedState() {
143     boolean res = check();
144     if (res)
145       return subjectLock;
146     else {
147       clearLock();
148       return null;
149     }
150   }
151 }