<commit_before>/*
 * $Id$
 */
package org.xins.util.io;

import java.io.File;
import org.apache.log4j.Logger;
import org.xins.util.MandatoryArgumentChecker;

/**
 * File watcher thread. This thread checks if a file changed and if it has, it
 * notifies the listener. The check is performed every <em>n</em> seconds,
 * where <em>n</em> can be configured.
 *
 * @version $Revision$ $Date$
 * @author <NAME> (<a href="mailto:<EMAIL>"><EMAIL></a>)
 *
 * @since XINS 0.121
 */
public final class FileWatcher extends Thread {

   //-------------------------------------------------------------------------
   // Class fields
   //-------------------------------------------------------------------------

   /**
    * Logger for this thread.
    */
   private static final Logger LOG = Logger.getLogger(FileWatcher.class.getName());


   //-------------------------------------------------------------------------
   // Class functions
   //-------------------------------------------------------------------------

   //-------------------------------------------------------------------------
   // Constructors
   //-------------------------------------------------------------------------

   /**
    * Creates a new <code>FileWatcher</code> for the specified file.
    *
    * @param file
    *    the name of the file to watch, cannot be <code>null</code>.
    *
    * @param interval
    *    the interval in seconds, must be greater than or equal to 1.
    *
    * @param listener
    *    the object to notify on events, cannot be <code>null</code>.
    *
    * @throws IllegalArgumentException
    *    if <code>file == null || listener == null || interval &lt; 1</code>
    */
   public FileWatcher(String file, int interval, Listener listener)
   throws IllegalArgumentException {

      // Check preconditions
      MandatoryArgumentChecker.check("file", file, "listener", listener);
      if (interval < 1) {
         throw new IllegalArgumentException("interval (" + interval + ") < 1");
      }

      // Store the information
      _file     = new File(file);
      _interval = 1000L * (long) interval;
      _listener = listener;
      _stopped  = false;

      // Configure thread as daemon
      setDaemon(true);

      // Immediately check if the file exists
      try {
         if (_file.exists()) {
            _lastModified = _file.lastModified();
         }
      } catch (SecurityException exception) {
         // ignore
      }
   }


   //-------------------------------------------------------------------------
   // Fields
   //-------------------------------------------------------------------------

   /**
    * The file to watch. Not <code>null</code>.
    */
   private final File _file;

   /**
    * Delay in seconds, at least 1.
    */
   private long _interval;

   /**
    * The listener. Not <code>null</code>
    */
   private final Listener _listener;

   /**
    * Timestamp of the last modification of the file. Initially this field is
    * <code>0L</code>.
    */
   private long _lastModified;

   /**
    * Flag that indicates if this thread has been stopped.
    */
   private boolean _stopped;


   //-------------------------------------------------------------------------
   // Methods
   //-------------------------------------------------------------------------

   /**
    * Runs this thread. This method should not be called directly, call
    * {@link #start()} instead. That method will call this method.
    *
    * @throws IllegalStateException
    *    if <code>{@link Thread#currentThread()} != this</code>.
    */
   public void run() throws IllegalStateException {

      // Check preconditions
      if (Thread.currentThread() != this) {
         throw new IllegalStateException("Thread.currentThread() != this");
      }

      if (LOG.isDebugEnabled()) {
         LOG.debug("Starting watch thread for file \"" + _file.getPath() + "\".");
      }

      while (! _stopped) {
         try {
            while(! _stopped) {
               // Wait for the designated amount of time
               sleep(_interval);

               // Check if the file changed
               check();
            }
         } catch (InterruptedException exception) {
            // Fall through
         }
      }
   }

   /**
    * Changes the interval. This method can only be called from the listener
    * callback methods. If it is not, an exception is thrown.
    *
    * @param interval
    *    the new interval in seconds, must be greater than or equal to 1.
    *
    * @throws IllegalStateException
    *    if <code>{@link Thread#currentThread()} != this</code>.
    *
    * @throws IllegalArgumentException
    *    if <code>interval &lt; 1</code>
    */
   public void setInterval(int interval)
   throws IllegalStateException, IllegalArgumentException {
      
      // Check preconditions
      if (Thread.currentThread() != this) {
         throw new IllegalStateException("Thread.currentThread() != this");
      }

      // Change the interval
      long newInterval = 1000L * (long) interval;
      if (newInterval != _interval) {
         LOG.debug("Changing the watch interval for file \"" + _file.getPath() + "\" from " + (_interval/1000) + " to " + interval + " seconds.");
         _interval = newInterval;
      }
   }

   /**
    * Stops this thread.
    */
   public void end() {
      _stopped = true;
      
      if (LOG.isDebugEnabled()) {
         LOG.debug("Stopping watch thread for file \"" + _file.getPath() + "\".");
      }

      this.interrupt();
   }

   /**
    * Checks if the file changed. The following algorithm is used:
    *
    * <ul>
    *    <li>if the file does not exist, then {@link Listener#fileNotFound()} is called;
    *    <li>if the file was modified, then {@link Listener#fileModified()} is called;
    *    <li>if {@link File#exists()} or {@link File#lastModified()} throws a {@link SecurityException}, then {@link Listener#securityException(SecurityException)} is called;
    *    <li>if the file was not modified and no {@link SecurityException}, then {@link Listener#fileNotModified()} is called.
    * </ul>
    */
   private void check() {

      long lastModified;
      try {
         // If the file exists, then check when it was last modified...
         if (_file.exists()) {
            lastModified = _file.lastModified();

         // ...otherwise notify the listener and return.
         } else {
            _lastModified = 0;
            _listener.fileNotFound();
            return;
         }
<commit_msg>Changed level of log messages from DEBUG to INFO.<commit_after>/*
 * $Id$
 */
package org.xins.util.io;

import java.io.File;
import org.apache.log4j.Logger;
import org.xins.util.MandatoryArgumentChecker;

/**
 * File watcher thread. This thread checks if a file changed and if it has, it
 * notifies the listener. The check is performed every <em>n</em> seconds,
 * where <em>n</em> can be configured.
 *
 * @version $Revision$ $Date$
 * @author <NAME> (<a href="mailto:<EMAIL>"><EMAIL></a>)
 *
 * @since XINS 0.121
 */
public final class FileWatcher extends Thread {

   //-------------------------------------------------------------------------
   // Class fields
   //-------------------------------------------------------------------------

   /**
    * Logger for this thread.
    */
   private static final Logger LOG = Logger.getLogger(FileWatcher.class.getName());


   //-------------------------------------------------------------------------
   // Class functions
   //-------------------------------------------------------------------------

   //-------------------------------------------------------------------------
   // Constructors
   //-------------------------------------------------------------------------

   /**
    * Creates a new <code>FileWatcher</code> for the specified file.
    *
    * @param file
    *    the name of the file to watch, cannot be <code>null</code>.
    *
    * @param interval
    *    the interval in seconds, must be greater than or equal to 1.
    *
    * @param listener
    *    the object to notify on events, cannot be <code>null</code>.
    *
    * @throws IllegalArgumentException
    *    if <code>file == null || listener == null || interval &lt; 1</code>
    */
   public FileWatcher(String file, int interval, Listener listener)
   throws IllegalArgumentException {

      // Check preconditions
      MandatoryArgumentChecker.check("file", file, "listener", listener);
      if (interval < 1) {
         throw new IllegalArgumentException("interval (" + interval + ") < 1");
      }

      // Store the information
      _file     = new File(file);
      _interval = 1000L * (long) interval;
      _listener = listener;
      _stopped  = false;

      // Configure thread as daemon
      setDaemon(true);

      // Immediately check if the file exists
      try {
         if (_file.exists()) {
            _lastModified = _file.lastModified();
         }
      } catch (SecurityException exception) {
         // ignore
      }
   }


   //-------------------------------------------------------------------------
   // Fields
   //-------------------------------------------------------------------------

   /**
    * The file to watch. Not <code>null</code>.
    */
   private final File _file;

   /**
    * Delay in seconds, at least 1.
    */
   private long _interval;

   /**
    * The listener. Not <code>null</code>
    */
   private final Listener _listener;

   /**
    * Timestamp of the last modification of the file. Initially this field is
    * <code>0L</code>.
    */
   private long _lastModified;

   /**
    * Flag that indicates if this thread has been stopped.
    */
   private boolean _stopped;


   //-------------------------------------------------------------------------
   // Methods
   //-------------------------------------------------------------------------

   /**
    * Runs this thread. This method should not be called directly, call
    * {@link #start()} instead. That method will call this method.
    *
    * @throws IllegalStateException
    *    if <code>{@link Thread#currentThread()} != this</code>.
    */
   public void run() throws IllegalStateException {

      // Check preconditions
      if (Thread.currentThread() != this) {
         throw new IllegalStateException("Thread.currentThread() != this");
      }

      if (LOG.isDebugEnabled()) {
         LOG.info("Starting watch thread for file \"" + _file.getPath() + "\".");
      }

      while (! _stopped) {
         try {
            while(! _stopped) {
               // Wait for the designated amount of time
               sleep(_interval);

               // Check if the file changed
               check();
            }
         } catch (InterruptedException exception) {
            // Fall through
         }
      }
   }

   /**
    * Changes the interval. This method can only be called from the listener
    * callback methods. If it is not, an exception is thrown.
    *
    * @param interval
    *    the new interval in seconds, must be greater than or equal to 1.
    *
    * @throws IllegalStateException
    *    if <code>{@link Thread#currentThread()} != this</code>.
    *
    * @throws IllegalArgumentException
    *    if <code>interval &lt; 1</code>
    */
   public void setInterval(int interval)
   throws IllegalStateException, IllegalArgumentException {
      
      // Check preconditions
      if (Thread.currentThread() != this) {
         throw new IllegalStateException("Thread.currentThread() != this");
      }

      // Change the interval
      long newInterval = 1000L * (long) interval;
      if (newInterval != _interval) {
         LOG.info("Changing the watch interval for file \"" + _file.getPath() + "\" from " + (_interval/1000) + " to " + interval + " seconds.");
         _interval = newInterval;
      }
   }

   /**
    * Stops this thread.
    */
   public void end() {
      _stopped = true;
      
      if (LOG.isDebugEnabled()) {
         LOG.info("Stopping watch thread for file \"" + _file.getPath() + "\".");
      }

      this.interrupt();
   }

   /**
    * Checks if the file changed. The following algorithm is used:
    *
    * <ul>
    *    <li>if the file does not exist, then {@link Listener#fileNotFound()} is called;
    *    <li>if the file was modified, then {@link Listener#fileModified()} is called;
    *    <li>if {@link File#exists()} or {@link File#lastModified()} throws a {@link SecurityException}, then {@link Listener#securityException(SecurityException)} is called;
    *    <li>if the file was not modified and no {@link SecurityException}, then {@link Listener#fileNotModified()} is called.
    * </ul>
    */
   private void check() {

      long lastModified;
      try {
         // If the file exists, then check when it was last modified...
         if (_file.exists()) {
            lastModified = _file.lastModified();

         // ...otherwise notify the listener and return.
         } else {
            _lastModified = 0;
            _listener.fileNotFound();
            return;
         }

{'fraction_non_alphanumeric': 0.21960155713304327, 'fraction_numerical': 0.003969162659338982, 'mean_word_length': 1.5176787086856265, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '523285', 'n_tokens_mistral': 3361, 'n_tokens_neox': 3264, 'n_words': 1040}