/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * 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. * !# */ package net.ontopia.utils; import java.io.File; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * INTERNAL: Check every now and then that a certain file has not * changed. If it has, then call the {@link #doOnChange} method. * * @since 1.4 */ public abstract class FileWatchdog extends Thread { // initialization of logging facility static Logger log = LoggerFactory.getLogger(FileWatchdog.class.getName()); /** * The default delay between every file modification check, set to 6 * seconds. */ static final public long DEFAULT_DELAY = 6000; /** * The name of the file to observe for changes. */ protected String filename; /** * The delay to observe between every check. By default set {@link * #DEFAULT_DELAY}. */ protected long delay = DEFAULT_DELAY; File file; long lastModified = 0; boolean warnedAlready = false; boolean interrupted = false; protected FileWatchdog() { super(); } protected FileWatchdog(String filename) { initialize(filename); } protected void initialize(String filename) { this.filename = filename; file = new File(filename); setDaemon(true); try { log.debug("Doing initial check"); checkAndConfigure(); } catch (Exception e) { log.warn("Error checking file", e); } } /** * Sets the delay to observe between each check of the file changes. * * @param delay - The delay in milliseconds, in the case of a * negative value the further execution is interrupted. */ public void setDelay(long delay) { this.delay = delay; if (delay < 0) this.interrupted = true; } abstract protected void doOnChange(); protected void checkAndConfigure() { boolean fileExists; try { fileExists = file.exists(); } catch (SecurityException e) { log.warn("Was not allowed to check existence of file: {}", filename); // there is no point in continuing interrupted = true; return; } if (fileExists) { long l = file.lastModified(); log.debug("{} last modified: {}; previously: {}", new Object[] {filename, Long.toString(l), Long.toString(lastModified)} ); if (l > lastModified) { log.debug("loading file {}", filename); lastModified = l; doOnChange(); warnedAlready = false; } } else { if (!warnedAlready) { log.debug("[{}] does not exist.", filename); warnedAlready = true; } } } public void run() { while (!interrupted) { try { Thread.currentThread().sleep(delay); } catch (InterruptedException e) { // no interruption expected } try { log.debug("Checking and configuring"); checkAndConfigure(); } catch (Exception e) { log.warn("Error checking file", e); } } } }