/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.admin; import java.io.File; import java.io.FileFilter; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Observable; import java.util.Observer; import java.util.Timer; import java.util.TimerTask; import com.scooterframework.common.logging.LogUtil; /** * <p> * DirChangeMonitor class monitors directory file changes and also notifies the * changes to associated observers. * </p> * * <p> * The default monitor interval is 2000 milliseconds. This can be changed by * System property <tt>property.load.interval</tt>. * </p> * * @author (Fei) John Chen */ public class DirChangeMonitor { private LogUtil log = LogUtil.getLogger(this.getClass().getName()); private Map<String, Observable> observables = new HashMap<String, Observable>(); private static long oneHundredDays = 8640000; private boolean periodicReading = false; private Date oldDate = null; private Timer timer = null; /** * Time interval in milliseconds between successive task executions */ private long loadInterval = 2000L; private static final DirChangeMonitor fcm = new DirChangeMonitor(); private DirChangeMonitor() { String loadDelay = System.getProperty("property.load.interval"); if (loadDelay != null) { try { loadInterval = (new Integer(loadDelay)).intValue(); } catch(NumberFormatException ex) { log.warn("System property property.load.interval has wrong integer format. Use default value " + loadInterval + " milliseconds."); } } if (ApplicationConfig.getInstance().isWebApp() && ApplicationConfig.getInstance().isInDevelopmentEnvironment() && loadInterval > 0) { periodicReading = true; } } public static DirChangeMonitor getInstance() { return fcm; } public void start() { if (periodicReading) { oldDate = new Date(); oldDate.setTime(oldDate.getTime()-oneHundredDays); timer = new Timer(); DirChangeMonitorTimerTask task = new DirChangeMonitorTimerTask(); schedule(task, loadInterval); } } public void stop() { if (timer != null) { timer.cancel(); log.debug("Dir files change monitor stopped."); } } /** * Register an observer for a file of a directory path. * * @param observer * @param path directory path * @param fileName the file to watch */ public void registerObserverForFileName(Observer observer, String path, String fileName) { FileFilter filter = new FileFilterSameName(fileName); registerObserver(observer, path, filter); } /** * Register an observer for all files of the same prefix of a directory path. * * @param observer * @param path directory path * @param filePrefix the file prefix to watch */ public void registerObserverForFilePrefix(Observer observer, String path, String filePrefix) { FileFilter filter = new FileFilterSamePrefix(filePrefix); registerObserver(observer, path, filter); } /** * Register an observer for all files of the same suffix of a directory path. * * @param observer * @param path directory path * @param fileSuffix the file prefix to watch */ public void registerObserverForFileSuffix(Observer observer, String path, String fileSuffix) { FileFilter filter = new FileFilterSameSuffix(fileSuffix); registerObserver(observer, path, filter); } /** * Register an observer of a directory path. * * @param observer * @param path directory path */ public void registerObserverForDir(Observer observer, String path) { registerObserver(observer, path, null); } /** * Register an observer of a directory path with a file filter. * * @param observer * @param path directory path * @param filter file filter */ public void registerObserver(Observer observer, String path, FileFilter filter) { if (!(ApplicationConfig.getInstance().isWebApp() && ApplicationConfig.getInstance().isInDevelopmentEnvironment())) return; if (path == null) { log.error("Can not watch the directory, because the input path is null."); return; } File dir = new File(path); if (!dir.isDirectory()) { log.error("Can not watch the directory " + path + ", because it does not exist."); return; } if (filter == null) { log.debug("monitoring dirctory: " + path); } else { log.debug("monitoring dirctory: " + path + " with filter " + filter.toString()); } String observableKey = getObservableKey(path, filter); Observable observable = observables.get(observableKey); if (observable == null) { observable = new DirObservable(path, filter); observables.put(observableKey, observable); } observable.addObserver(observer); } private String getObservableKey(String path, FileFilter filter) { return (filter != null)?(path + "_" + filter.toString()):path; } private void schedule(TimerTask task, long period) { if (period > 0) { timer.schedule(task, oldDate, period); } else { timer.schedule(task, oldDate); } } /** * DirChangeMonitorTimerTask is responsible for scanning files in the directory. */ public class DirChangeMonitorTimerTask extends TimerTask { public DirChangeMonitorTimerTask() { super(); } public void run() { for (Map.Entry<String, Observable> entry : observables.entrySet()) { DirObservable observable = (DirObservable)observables.get(entry.getKey()); observable.checkChange(); } } } }