/*
* $Id: FileConfigurationMonitor.java,v 1.10 2009/08/19 15:04:54 vtschopp Exp $
*
* Created on Aug 25, 2006 by Valery Tschopp <tschopp@switch.ch>
*
* Copyright (c) Members of the EGEE Collaboration. 2004.
* See http://eu-egee.org/partners/ for details on the copyright holders.
* For license conditions see the license file or http://eu-egee.org/license.html
*/
package org.glite.slcs.config;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* FileConfigurationMonitor checks if the monitored file have been modified, and
* if so sends a {@link FileConfigurationEvent} to all the registered
* {@link FileConfigurationListener}.
*
* @author Valery Tschopp <tschopp@switch.ch>
* @version $Revision: 1.10 $
*/
public class FileConfigurationMonitor extends Timer {
/** Default sleep time between 2 check (300000 millis = 300 sec = 5 min) */
public static long DEFAULT_MONITORING_INTERVAL = 300000;
/** Logging */
private static Log LOG = LogFactory.getLog(FileConfigurationMonitor.class);
/** List of FileConfigurationListener */
private List<FileConfigurationListener> listeners_ = null;
/** the monitored File used by the FileConfiguration */
private File file_ = null;
/** last modified timestamp of monitored file */
private long lastModified_ = 0;
/** pause between to check (millis) */
private long monitoringInterval_ = DEFAULT_MONITORING_INTERVAL;
/**
* Creates a FileConfigurationMonitor for the given FileConfiguration.
*
* @param file
* The file associated with the file to monitor.
* @param monitoringInterval
* The time (in seconds) between 2 checks.
* @param listener
* The FileConfigurationListener (this).
* @return The new FileConfigurationMonitor object.
*/
public static FileConfigurationMonitor createFileConfigurationMonitor(
File file, String monitoringInterval,
FileConfigurationListener listener) {
// parse GroupsFileMonitoringInterval parameter
long interval = FileConfigurationMonitor.DEFAULT_MONITORING_INTERVAL;
try {
// interval is in seconds
interval = Integer.parseInt(monitoringInterval);
interval *= 1000;
} catch (NumberFormatException e) {
LOG.warn("FileMonitoringInterval does not contain a valid interval time (second). Using default: "
+ interval);
}
if (LOG.isDebugEnabled()) {
LOG.debug("file: " + file.getName() + " interval: " + interval
+ ")");
}
// create the FileConfigurationMontitor
FileConfigurationMonitor fileConfigurationMonitor = new FileConfigurationMonitor(
file, interval);
fileConfigurationMonitor.addFileConfigurationListener(listener);
return fileConfigurationMonitor;
}
/**
* Constr. Monitor the file associated with the given FileConfiguration and
* check for change every DEFAULT_MONITORING_INTERVAL (5 min).
*
* @param file
* The file to monitor
*/
public FileConfigurationMonitor(File file) {
this(file, DEFAULT_MONITORING_INTERVAL);
}
/**
* Const. Monitor the file associated with the given FileConfiguration and
* check for change every given <code>monitoringInterval</code>.
*
* @param file
* The file to monitor.
* @param monitoringInterval
* The pause between 2 check in millis.
*/
public FileConfigurationMonitor(File file, long monitoringInterval) {
// daemonize
super(true);
this.listeners_ = new Vector<FileConfigurationListener>();
this.file_ = file;
this.lastModified_ = file_.lastModified();
this.monitoringInterval_ = monitoringInterval;
}
/**
* FileConfigurationMonitorTask scheduled by the FileConfigurationMonitor to
* checks last modification timestamp of the monitored file and dispatch
* event to the listeners.
*/
private class FileConfigurationMonitorTask extends TimerTask {
/**
* Checks the file for modification and send event to listeners.
*/
public void run() {
if (LOG.isDebugEnabled()) {
LOG.debug("checking last modified for: "
+ file_.getAbsolutePath());
}
long currentLastModified = file_.lastModified();
if (currentLastModified > lastModified_) {
lastModified_ = currentLastModified;
// dipatch the event to listener
LOG.info("File " + file_.getAbsolutePath() + " changed");
dispatchFileConfigurationEvent(FileConfigurationEvent.FILE_MODIFIED);
}
}
}
/**
* Starts the FileConfigurationMonitorTask to monitor the file.
*/
public void start() {
LOG.info("schedule the FileConfigurationMonitorTask ("
+ monitoringInterval_ + " ms) for file: "
+ file_.getAbsolutePath());
scheduleAtFixedRate(new FileConfigurationMonitorTask(), 0,
monitoringInterval_);
}
/**
* Stops to monitor the file.
*/
public void shutdown() {
LOG.info("cancel the FileConfigurationMonitorTask");
this.cancel();
// empty the listeners list
this.listeners_.clear();
}
/**
* Adds the listener to the FileConfigurationListener list.
*
* @param listener
* The listener to add.
* @see FileConfigurationListener
*/
public void addFileConfigurationListener(FileConfigurationListener listener) {
listeners_.add(listener);
}
/**
* Removes the listener from the FileConfigurationListener list.
*
* @param listener
* The listener to remove.
* @return <code>true</code> if the listener was in the list,
* <code>false</code> otherwise.
* @see FileConfigurationListener
*/
public boolean removeFileConfigurationListener(
FileConfigurationListener listener) {
return listeners_.remove(listener);
}
/**
* Disptaches the FileConfigurationEvent type to all
* FileConfigurationListener registered.
*
* @param eventType
* The FileConfigurationEvent type.
*/
protected void dispatchFileConfigurationEvent(int eventType) {
if (LOG.isDebugEnabled()) {
LOG.debug("eventType=" + eventType);
}
if (!listeners_.isEmpty()) {
FileConfigurationEvent event = new FileConfigurationEvent(this,
eventType);
Iterator<FileConfigurationListener> listeners = listeners_.iterator();
while (listeners.hasNext()) {
FileConfigurationListener listener = (FileConfigurationListener) listeners.next();
listener.fileConfigurationChanged(event);
}
}
}
}