Java Tutorial/File/File Monitor
Monitor files for changes
// Copyright (C) 2007 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import java.io.File;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
/**
* Monitor files for changes. This singleton class maintains a map of files to
* monitor and objects to notify when something they change.
*/
public class FileMonitor {
private static final FileMonitor SINGLETON = new FileMonitor();
private Timer timer;
private Hashtable<String, TimerTask> timerTasks;
private FileMonitor() {
timer = new Timer(true);
timerTasks = new Hashtable<String, TimerTask>();
}
/**
* Returns the singleton instance of this class.
* @return the singleton instance
*/
public static FileMonitor getInstance() {
return SINGLETON;
}
/**
* Start monitoring a file.
*
* @param listener listener to notify when the file changed.
* @param fileName name of the file to monitor.
* @param period polling period in milliseconds.
*/
public void addFileChangeListener(FileChangeListener listener,
String fileName, long period) {
removeFileChangeListener(listener, fileName);
FileMonitorTask task = new FileMonitorTask(listener, fileName);
timerTasks.put(fileName + listener.hashCode(), task);
timer.schedule(task, period, period);
}
/**
* Remove the listener from the notification list.
*
* @param listener the listener to be removed.
*/
public void removeFileChangeListener(FileChangeListener listener,
String fileName) {
FileMonitorTask task = (FileMonitorTask) timerTasks.remove(fileName
+ listener.hashCode());
if (task != null) {
task.cancel();
}
}
protected void fireFileChangeEvent(FileChangeListener listener,
String fileName) {
listener.fileChanged(fileName);
}
class FileMonitorTask extends TimerTask {
FileChangeListener listener;
String fileName;
File monitoredFile;
long lastModified;
public FileMonitorTask(FileChangeListener listener, String fileName) {
this.listener = listener;
this.fileName = fileName;
this.lastModified = 0;
monitoredFile = new File(fileName);
this.lastModified = getLastModified();
}
private long getLastModified() {
if (monitoredFile.exists()) {
return monitoredFile.lastModified();
} else {
return -1;
}
}
@Override
public void run() {
long lastModified = getLastModified();
if (lastModified != this.lastModified) {
this.lastModified = lastModified;
fireFileChangeEvent(this.listener, this.fileName);
}
}
}
public interface FileChangeListener {
public void fileChanged(String fileName);
}
}
Monitoring a File for changes.
/*******************************************************************************
* Copyright (c) 2007 Pascal Essiembre.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pascal Essiembre - initial API and implementation
******************************************************************************/
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
/**
* Class monitoring a {@link File} for changes.
*
* @author Pascal Essiembre
*/
public class FileMonitor {
private static final FileMonitor instance = new FileMonitor();
private Timer timer;
private Hashtable<String, FileMonitorTask> timerEntries;
/**
* Gets the file monitor instance.
*
* @return file monitor instance
*/
public static FileMonitor getInstance() {
return instance;
}
/**
* Constructor.
*/
private FileMonitor() {
// Create timer, run timer thread as daemon.
timer = new Timer(true);
timerEntries = new Hashtable<String, FileMonitorTask>();
}
/**
* Adds a monitored file with a {@link FileChangeListener}.
*
* @param listener
* listener to notify when the file changed.
* @param fileName
* name of the file to monitor.
* @param period
* polling period in milliseconds.
*/
public void addFileChangeListener(FileChangeListener listener, String fileName, long period)
throws FileNotFoundException {
addFileChangeListener(listener, new File(fileName), period);
}
/**
* Adds a monitored file with a FileChangeListener.
*
* @param listener
* listener to notify when the file changed.
* @param fileName
* name of the file to monitor.
* @param period
* polling period in milliseconds.
*/
public void addFileChangeListener(FileChangeListener listener, File file, long period)
throws FileNotFoundException {
removeFileChangeListener(listener, file);
FileMonitorTask task = new FileMonitorTask(listener, file);
timerEntries.put(file.toString() + listener.hashCode(), task);
timer.schedule(task, period, period);
}
/**
* Remove the listener from the notification list.
*
* @param listener
* the listener to be removed.
*/
public void removeFileChangeListener(FileChangeListener listener, String fileName) {
removeFileChangeListener(listener, new File(fileName));
}
/**
* Remove the listener from the notification list.
*
* @param listener
* the listener to be removed.
*/
public void removeFileChangeListener(FileChangeListener listener, File file) {
FileMonitorTask task = timerEntries.remove(file.toString() + listener.hashCode());
if (task != null) {
task.cancel();
}
}
/**
* Fires notification that a file changed.
*
* @param listener
* file change listener
* @param file
* the file that changed
*/
protected void fireFileChangeEvent(FileChangeListener listener, File file) {
listener.fileChanged(file);
}
/**
* File monitoring task.
*/
class FileMonitorTask extends TimerTask {
FileChangeListener listener;
File monitoredFile;
long lastModified;
public FileMonitorTask(FileChangeListener listener, File file) throws FileNotFoundException {
this.listener = listener;
this.lastModified = 0;
monitoredFile = file;
if (!monitoredFile.exists()) { // but is it on CLASSPATH?
URL fileURL = listener.getClass().getClassLoader().getResource(file.toString());
if (fileURL != null) {
monitoredFile = new File(fileURL.getFile());
} else {
throw new FileNotFoundException("File Not Found: " + file);
}
}
this.lastModified = monitoredFile.lastModified();
}
public void run() {
long lastModified = monitoredFile.lastModified();
if (lastModified != this.lastModified) {
this.lastModified = lastModified;
fireFileChangeEvent(this.listener, monitoredFile);
}
}
}
}
/*******************************************************************************
* Copyright (c) 2007 Pascal Essiembre. All rights reserved. This program and
* the accompanying materials are made available under the terms of the Eclipse
* Public License v1.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Pascal Essiembre - initial API and implementation
******************************************************************************/
/**
* Listener interested in {@link File} changes.
*
* @author Pascal Essiembre
*/
interface FileChangeListener {
/**
* Invoked when a file changes.
*
* @param fileName
* name of changed file.
*/
public void fileChanged(File file);
}