View Javadoc

1   /*
2    * Copyright (C) The Apache Software Foundation. All rights reserved.
3    *
4    * This software is published under the terms of the Apache Software License
5    * version 1.1, a copy of which has been included  with this distribution in
6    * the LICENSE file.
7    */
8   
9   // Contributors:  Mathias Bogaert
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          //Do not call doOnChange initialy
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; // there is no point in continuing
109             return;
110         }
111 
112         if (fileExists) {
113             /*
114              * this can also throw a SecurityException
115              * however, if we reached this point this
116              * is very unlikely.
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                 //log.debug("File is the same");
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                 // no interruption expected
149                 log.info("no interruption expected", e);
150             }
151             checkAndConfigure(true);
152         }
153         watchdogs.remove(this.filename);
154     }
155 }