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