1
2
3
4
5
6
7
8
9
10 package net.sf.jour.util;
11
12 import java.io.File;
13 import java.util.*;
14
15 import org.apache.log4j.Logger;
16
17 /***
18 * Check every now and then that a certain file has not changed. If it has, then call the
19 * {@link #doOnChange}method.
20 *
21 * This is build base on org.apache.log4j.helpers.FileWatchdog
22 *
23 * @author Ceki Gülcü
24 * @since version 0.9.1
25 */
26 public class FileWatchdog extends Thread {
27
28 protected static final Logger log = Logger.getLogger(FileWatchdog.class);
29
30 /***
31 * The default delay between every file modification check, set to 60 seconds.
32 */
33 static final public long DEFAULT_DELAY = 60000;
34
35 /***
36 * The name of the file to observe for changes.
37 */
38 protected String filename;
39
40 /***
41 * The delay to observe between every check. By default set {@link#DEFAULT_DELAY}.
42 */
43 protected long delay = DEFAULT_DELAY;
44
45 File file;
46
47 long lastModif = 0;
48
49 long fileLength = 0;
50
51 boolean warnedAlready = false;
52
53 boolean interrupted = false;
54
55 List listenerList;
56
57 static Hashtable watchdogs = new Hashtable();
58
59 protected FileWatchdog(String filename) {
60 this.filename = filename;
61 file = new File(filename);
62 setDaemon(true);
63 listenerList = new Vector();
64
65 checkAndConfigure(false);
66 }
67
68 public static FileWatchdog getFileWatchdog(String filename, boolean create) {
69 FileWatchdog dog = (FileWatchdog)watchdogs.get(filename);
70 if ((dog == null) && (create)) {
71 dog = new FileWatchdog(filename);
72 watchdogs.put(filename, dog);
73 dog.start();
74 }
75 return dog;
76 }
77
78 /***
79 * Set the delay to observe between each check of the file changes.
80 */
81 public void setDelay(long delay) {
82 this.delay = delay;
83 }
84
85 public synchronized void addListener(FileChageListener fileChageListener) {
86 if (!listenerList.contains(fileChageListener)) {
87 listenerList.add(fileChageListener);
88 }
89 }
90
91 public synchronized void doOnChange() {
92 for (Iterator i = listenerList.iterator(); i.hasNext(); ) {
93 FileChageListener listener = (FileChageListener) i.next();
94 listener.doOnFileChange(file.getAbsolutePath());
95 }
96 }
97
98 protected boolean fileDetected() {
99 return ((0 != lastModif) && (0 != fileLength));
100 }
101
102 protected void checkAndConfigure(boolean callOnChange) {
103 boolean fileExists;
104 try {
105 fileExists = file.exists();
106 } catch (SecurityException e) {
107 log.warn("Was not allowed to read check file existance, file:[" + filename + "].");
108 interrupted = true;
109 return;
110 }
111
112 if (fileExists) {
113
114
115
116
117
118 long t = file.lastModified();
119 long l = file.length();
120 if ((t != lastModif) || (l != fileLength)) {
121 log.debug("File modification detected " + file.getName());
122 lastModif = t;
123 fileLength = l;
124 if (callOnChange) {
125 doOnChange();
126 }
127 warnedAlready = false;
128 } else {
129
130 }
131 } else {
132 if (!warnedAlready) {
133 log.debug("[" + filename + "] does not exist.");
134 warnedAlready = true;
135 }
136 }
137 }
138
139 public void finish() {
140 interrupted = true;
141 }
142
143 public void run() {
144 while (!interrupted) {
145 try {
146 Thread.sleep(delay);
147 } catch (InterruptedException e) {
148
149 log.info("no interruption expected", e);
150 }
151 checkAndConfigure(true);
152 }
153 watchdogs.remove(this.filename);
154 }
155 }