package org.grails.io.watch;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Backend for {@link DirectoryWatcher}
* @author Craig Andrews
* @since 2.4
* @see WatchServiceDirectoryWatcher
* @see PollingDirectoryWatcher
* @see DirectoryWatcher
*/
abstract class AbstractDirectoryWatcher implements Runnable {
private List<DirectoryWatcher.FileChangeListener> listeners = new ArrayList<DirectoryWatcher.FileChangeListener>();
volatile protected boolean active = true; //must be volatile as it's read by multiple threads and the value should be reflected in all of them
protected long sleepTime = 1000;
/**
* Sets whether to stop the directory watcher
*
* @param active False if you want to stop watching
*/
public void setActive(boolean active) {
this.active = active;
}
/**
* Sets the amount of time to sleep between checks
*
* @param sleepTime The sleep time
*/
public void setSleepTime(long sleepTime) {
this.sleepTime = sleepTime;
}
/**
* Adds a file listener that can react to change events
*
* @param listener The file listener
*/
public void addListener(DirectoryWatcher.FileChangeListener listener) {
listeners.add(listener);
}
/**
* Removes a file listener from the current list
*
* @param listener The file listener
*/
public void removeListener(DirectoryWatcher.FileChangeListener listener) {
listeners.remove(listener);
}
/**
* Adds a file to the watch list
*
* @param fileToWatch The file to watch
*/
public abstract void addWatchFile(File fileToWatch);
/**
* Adds a directory to watch for the given file and extensions.
* No String in the fileExtensions list can start with a dot (DirectoryWatcher guarantees that)
*
* @param dir The directory
* @param fileExtensions The extensions
*/
public abstract void addWatchDirectory(File dir, List<String> fileExtensions);
protected void fireOnChange(File file) {
for (DirectoryWatcher.FileChangeListener listener : listeners) {
listener.onChange(file);
}
}
protected void fireOnNew(File file) {
for (DirectoryWatcher.FileChangeListener listener : listeners) {
listener.onNew(file);
}
}
protected boolean isValidDirectoryToMonitor(File file){
return file.isDirectory() && ! file.isHidden() && !file.getName().startsWith(".");
}
protected boolean isValidFileToMonitor(File file, Collection<String> fileExtensions) {
String name = file.getName();
String path = file.getAbsolutePath();
boolean isSvnFile = path.indexOf(File.separator + DirectoryWatcher.SVN_DIR_NAME + File.separator) > 0;
return !isSvnFile &&
!file.isDirectory() &&
!file.isHidden() &&
!file.getName().startsWith(".") &&
(fileExtensions.contains("*") || fileExtensions.contains(getFilenameExtension(name)));
}
/**
* Extract the filename extension from the given path,
* e.g. "mypath/myfile.txt" -> "txt".
* @param path the file path (may be {@code null})
* @return the extracted filename extension, or {@code null} if none
*/
public static String getFilenameExtension(String path) {
if (path == null) {
return null;
}
int extIndex = path.lastIndexOf(".");
if (extIndex == -1) {
return null;
}
return path.substring(extIndex + 1);
}
}