/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.platform;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.geoserver.platform.resource.Files;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resource.Type;
/**
* Watches a files last modified date to determine when a file has been changed.
* <p>
* Client code using this class should call {@link #isModified()} to determine if the file
* has changed since the last check, and {@link #read()} to read the contents of the file
* and update the last check timestamp.
* </p>
*
* @author Justin Deoliveira, OpenGeo
*
*/
public class FileWatcher<T> {
protected Resource resource;
private long lastModified = Long.MIN_VALUE;
private long lastCheck;
private boolean stale;
public FileWatcher(Resource resource) {
this.resource = resource;
}
public FileWatcher(File file) {
this.resource = Files.asResource(file);
}
public File getFile() {
return resource.file();
}
public Resource getResource() {
return resource;
}
/**
* Reads the file updating the last check timestamp.
* <p>
* Subclasses can override {@link #parseFileContents(InputStream)} to do something
* when the file is read.
* </p>
* @return parsed file contents
*/
public T read() throws IOException {
T result = null;
if( resource.getType() == Type.RESOURCE ){
InputStream is = null;
try {
is = resource.in();
result = parseFileContents(is);
lastModified = resource.lastmodified();
lastCheck = System.currentTimeMillis();
stale = false;
} finally {
if (is != null) {
is.close();
}
}
}
return result;
}
/**
* Parses the contents of the file being watched.
* <p>
* Subclasses should override.
* </p>
*/
protected T parseFileContents(InputStream in) throws IOException {
return null;
}
/**
* Determines if the underlying file has been modified since the last check.
*/
public boolean isModified() {
long now = System.currentTimeMillis();
if((now - lastCheck) > 1000) {
lastCheck = now;
stale = (resource.getType() != Type.UNDEFINED) && (resource.lastmodified() != lastModified);
}
return stale;
}
/**
* Method to set the last modified time stamp.
* Clients synchronized with the actual file
* content and knowing the last modified time stamp
* can avoid unnecessary reload operations
*
* @param lastModified last modified time
*/
public void setKnownLastModified(long lastModified) {
this.lastModified = lastModified;
}
}