001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018// Contributors:  Mathias Bogaert
019
020package org.apache.log4j.helpers;
021
022import java.io.File;
023
024/**
025   Check every now and then that a certain file has not changed. If it
026   has, then call the {@link #doOnChange} method.
027
028
029   @author Ceki Gülcü
030   @since version 0.9.1 */
031public abstract class FileWatchdog extends Thread {
032
033  /**
034     The default delay between every file modification check, set to 60
035     seconds.  */
036  static final public long DEFAULT_DELAY = 60000; 
037  /**
038     The name of the file to observe  for changes.
039   */
040  protected String filename;
041  
042  /**
043     The delay to observe between every check. By default set {@link
044     #DEFAULT_DELAY}. */
045  protected long delay = DEFAULT_DELAY; 
046  
047  File file;
048  long lastModif = 0; 
049  boolean warnedAlready = false;
050  boolean interrupted = false;
051
052  protected
053  FileWatchdog(String filename) {
054    super("FileWatchdog");
055    this.filename = filename;
056    file = new File(filename);
057    setDaemon(true);
058    checkAndConfigure();
059  }
060
061  /**
062     Set the delay to observe between each check of the file changes.
063   */
064  public
065  void setDelay(long delay) {
066    this.delay = delay;
067  }
068
069  abstract 
070  protected 
071  void doOnChange();
072
073  protected
074  void checkAndConfigure() {
075    boolean fileExists;
076    try {
077      fileExists = file.exists();
078    } catch(SecurityException  e) {
079      LogLog.warn("Was not allowed to read check file existance, file:["+
080                  filename+"].");
081      interrupted = true; // there is no point in continuing
082      return;
083    }
084
085    if(fileExists) {
086      long l = file.lastModified(); // this can also throw a SecurityException
087      if(l > lastModif) {           // however, if we reached this point this
088        lastModif = l;              // is very unlikely.
089        doOnChange();
090        warnedAlready = false;
091      }
092    } else {
093      if(!warnedAlready) {
094        LogLog.debug("["+filename+"] does not exist.");
095        warnedAlready = true;
096      }
097    }
098  }
099
100  public
101  void run() {    
102    while(!interrupted) {
103      try {
104            Thread.sleep(delay);
105      } catch(InterruptedException e) {
106        // no interruption expected
107      }
108      checkAndConfigure();
109    }
110  }
111}