1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package uk.ac.rdg.resc.jstyx.server;
30
31 import org.apache.log4j.Logger;
32
33 import java.io.File;
34
35 import uk.ac.rdg.resc.jstyx.StyxException;
36 import uk.ac.rdg.resc.jstyx.types.ULong;
37 import uk.ac.rdg.resc.jstyx.server.StyxDirectory;
38
39 /***
40 * A file on disk that is continuously monitored. This is basically an
41 * AsyncStyxFile that wraps a FileOnDisk, with a separate thread that monitors
42 * the underlying file (checks for changes to the last modified time and length
43 * of the file). Note that the underlying file does not have to exist at the
44 * time the MonitoredFileOnDisk object is constructed or at the time the monitor
45 * is started.
46 *
47 * @todo Start monitoring when the first client opens this file? Stop monitoring
48 * when the last client closes the file?
49 *
50 * @todo Link refresh() with notifications to clients?
51 *
52 * @author Jon Blower
53 * $Revision: 223 $
54 * $Date: 2005-05-11 16:15:35 +0100 (Wed, 11 May 2005) $
55 * $Log$
56 * Revision 1.5 2005/05/11 15:15:35 jonblower
57 * Added new constructor
58 *
59 * Revision 1.4 2005/05/11 10:33:50 jonblower
60 * Implemented MonitoredFileOnDisk.java
61 *
62 *
63 * Revision 1.1 2005/05/09 13:22:43 jonblower
64 * Initial import
65 *
66 */
67 public class MonitoredFileOnDisk extends AsyncStyxFile implements Runnable
68 {
69
70 private static final Logger log = Logger.getLogger(MonitoredFileOnDisk.class);
71
72 private File file;
73 private long monitorInterval;
74
75 private boolean fileExists;
76 private long length;
77
78 private boolean monitoring;
79 private Thread monitor;
80
81 /***
82 * Creates a new instance of MonitoredFileOnDisk. Call startMonitoring() to
83 * start monitoring the underlying file.
84 * @param filename The name of the underlying file to monitor. Note that this
85 * file does not need to exist yet
86 * @param monitorInterval The time in milliseconds between each check to see
87 * if the file has changed
88 * @throws StyxException if the file name is illegal
89 */
90 public MonitoredFileOnDisk(String filename, long monitorInterval) throws StyxException
91 {
92 this(new File(filename), monitorInterval);
93 }
94
95 /***
96 * Creates a new instance of MonitoredFileOnDisk that monitors the underlying
97 * file every 2 seconds. Call startMonitoring() to start monitoring the
98 * underlying file.
99 * @param filename The name of the underlying file to monitor. Note that this
100 * file does not need to exist yet
101 * @throws StyxException if the file name is illegal
102 */
103 public MonitoredFileOnDisk(String filename) throws StyxException
104 {
105 this(new File(filename));
106 }
107
108 /***
109 * Creates a new instance of MonitoredFileOnDisk. Call startMonitoring() to
110 * start monitoring the underlying file.
111 * @param name The name of the file as it will appear in the Styx namespace
112 * @param file The underlying file to monitor. Note that this file does not
113 * need to exist yet
114 * @param monitorInterval The time in milliseconds between each check to see
115 * if the file has changed
116 * @throws StyxException if the file name is illegal
117 */
118 public MonitoredFileOnDisk(String name, File file, long monitorInterval) throws StyxException
119 {
120
121
122
123 super(new FileOnDisk(name, file, 0444, false));
124 this.file = file;
125 this.monitorInterval = monitorInterval;
126 this.fileExists = file.exists();
127 this.lastModifiedTime = file.lastModified() / 1000;
128 this.length = file.length();
129
130 this.monitor = new Thread(this);
131 }
132
133 /***
134 * Creates a new instance of MonitoredFileOnDisk. Call startMonitoring() to
135 * start monitoring the underlying file.
136 * @param file The underlying file to monitor. Note that this file does not
137 * need to exist yet
138 * @param monitorInterval The time in milliseconds between each check to see
139 * if the file has changed
140 * @throws StyxException if the file name is illegal
141 */
142 public MonitoredFileOnDisk(File file, long monitorInterval) throws StyxException
143 {
144 this(file.getName(), file, monitorInterval);
145 }
146
147 /***
148 * Creates a new instance of MonitoredFileOnDisk that monitors the underlying
149 * file every 2 seconds. Call startMonitoring() to start monitoring the
150 * underlying file.
151 * @param file The underlying file to monitor. Note that this file does not
152 * need to exist yet
153 * @throws StyxException if the file name is illegal
154 */
155 public MonitoredFileOnDisk(File file) throws StyxException
156 {
157 this(file, 2000);
158 }
159
160 public void run()
161 {
162 try
163 {
164 while(this.monitoring)
165 {
166
167 long start = System.currentTimeMillis();
168 if (this.file.exists())
169 {
170 if (this.fileExists)
171 {
172
173
174 long newLastMod = this.file.lastModified() / 1000;
175 if (newLastMod != this.lastModifiedTime)
176 {
177 this.lastModifiedTime = newLastMod;
178
179 this.contentsChanged();
180 }
181
182
183
184 else
185 {
186 long newLength = this.file.length();
187 if (newLength != this.length)
188 {
189 this.length = newLength;
190 this.contentsChanged();
191 }
192 }
193 }
194 else
195 {
196
197 this.fileExists = true;
198 this.length = this.file.length();
199 this.lastModifiedTime = this.file.lastModified() / 1000;
200 this.contentsChanged();
201 }
202 }
203 else
204 {
205
206 if (this.fileExists)
207 {
208
209 this.length = 0L;
210 this.lastModifiedTime = 0L;
211 this.contentsChanged();
212 }
213 }
214
215
216
217 long timeTaken = System.currentTimeMillis() - start;
218 long timeToWait = this.monitorInterval - timeTaken;
219 if (timeToWait > 0)
220 {
221 Thread.sleep(timeToWait);
222 }
223
224 }
225 }
226 catch (InterruptedException ie)
227 {
228 if (log.isDebugEnabled())
229 {
230 log.debug("MonitoredFileOnDisk " + this.name +
231 " interrupted while sleeping");
232 }
233 }
234 }
235
236 public ULong getLength()
237 {
238 return new ULong(this.length);
239 }
240
241 /***
242 * Starts monitoring the file
243 */
244 public void startMonitoring()
245 {
246 log.debug("Starting to monitor " + this.file.getPath());
247 this.monitoring = true;
248 this.monitor.start();
249 }
250
251 /***
252 * Stops monitoring the file
253 */
254 public void stopMonitoring()
255 {
256 log.debug("Stopping monitoring of " + this.file.getPath());
257 this.monitoring = false;
258 this.monitor.interrupt();
259 }
260
261 /***
262 * Simple test program
263 */
264 public static void main (String[] args) throws Exception
265 {
266 MonitoredFileOnDisk monFile = new MonitoredFileOnDisk("C://monitorme.txt");
267 monFile.startMonitoring();
268 StyxDirectory root = new StyxDirectory("/").addChild(monFile);
269 new StyxServer(9996, root).start();
270 }
271
272 }