Author: ggregory
Date: Mon Jun 11 01:09:58 2012
New Revision: 1348698

URL: http://svn.apache.org/viewvc?rev=1348698&view=rev
Log:
[IO-269] Tailer locks file from deletion/rename on Windows.

Modified:
    commons/proper/io/trunk/src/changes/changes.xml
    
commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java
    
commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java

Modified: commons/proper/io/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1348698&r1=1348697&r2=1348698&view=diff
==============================================================================
--- commons/proper/io/trunk/src/changes/changes.xml (original)
+++ commons/proper/io/trunk/src/changes/changes.xml Mon Jun 11 01:09:58 2012
@@ -47,6 +47,9 @@ The <action> type attribute can be add,u
   <body>
     <!-- The release date is the date RC is cut -->
     <release version="2.4" date="2012-TDB-TDB" description="">
+      <action issue="IO-269" dev="ggregory" type="add" due-to="sebb">
+        Tailer locks file from deletion/rename on Windows.
+      </action>            
       <action issue="IO-279" dev="sebb" type="fix" due-to="Sergio Bossa, Chris 
Baron">
         Tailer erroneously considers file as new.
       </action>            

Modified: 
commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java
URL: 
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java?rev=1348698&r1=1348697&r2=1348698&view=diff
==============================================================================
--- 
commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java 
(original)
+++ 
commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java 
Mon Jun 11 01:09:58 2012
@@ -138,6 +138,11 @@ public class Tailer implements Runnable 
     private final TailerListener listener;
 
     /**
+     * Whether to close and reopen the file whilst waiting for more input.
+     */
+    private final boolean reOpen;
+    
+    /**
      * The tailer will run as long as this value is true.
      */
     private volatile boolean run = true;
@@ -173,6 +178,18 @@ public class Tailer implements Runnable 
     }
     
     /**
+     * Creates a Tailer for the given file, with a delay other than the 
default 1.0s.
+     * @param file the file to follow.
+     * @param listener the TailerListener to use.
+     * @param delayMillis the delay between checks of the file for new content 
in milliseconds.
+     * @param end Set to true to tail from the end of the file, false to tail 
from the beginning of the file.
+     * @param reOpen if true, close and reopen the file between reading chunks 
+     */
+    public Tailer(File file, TailerListener listener, long delayMillis, 
boolean end, boolean reOpen) {
+        this(file, listener, delayMillis, end, reOpen, DEFAULT_BUFSIZE);
+    }
+    
+    /**
      * Creates a Tailer for the given file, with a specified buffer size.
      * @param file the file to follow.
      * @param listener the TailerListener to use.
@@ -181,7 +198,19 @@ public class Tailer implements Runnable 
      * @param bufSize Buffer size
      */
     public Tailer(File file, TailerListener listener, long delayMillis, 
boolean end, int bufSize) {
-
+        this(file, listener, delayMillis, end, false, bufSize);
+    }
+    
+    /**
+     * Creates a Tailer for the given file, with a specified buffer size.
+     * @param file the file to follow.
+     * @param listener the TailerListener to use.
+     * @param delayMillis the delay between checks of the file for new content 
in milliseconds.
+     * @param end Set to true to tail from the end of the file, false to tail 
from the beginning of the file.
+     * @param reOpen if true, close and reopen the file between reading chunks 
+     * @param bufSize Buffer size
+     */
+    public Tailer(File file, TailerListener listener, long delayMillis, 
boolean end, boolean reOpen, int bufSize) {
         this.file = file;
         this.delayMillis = delayMillis;
         this.end = end;
@@ -191,6 +220,7 @@ public class Tailer implements Runnable 
         // Save and prepare the listener
         this.listener = listener;
         listener.init(this);
+        this.reOpen = reOpen;
     }
     
     /**
@@ -212,6 +242,26 @@ public class Tailer implements Runnable 
     }
 
     /**
+     * Creates and starts a Tailer for the given file.
+     * 
+     * @param file the file to follow.
+     * @param listener the TailerListener to use.
+     * @param delayMillis the delay between checks of the file for new content 
in milliseconds.
+     * @param end Set to true to tail from the end of the file, false to tail 
from the beginning of the file.
+     * @param reOpen whether to close/reopen the file between chunks
+     * @param bufSize buffer size.
+     * @return The new tailer
+     */
+    public static Tailer create(File file, TailerListener listener, long 
delayMillis, boolean end, boolean reOpen, 
+            int bufSize) {
+        Tailer tailer = new Tailer(file, listener, delayMillis, end, reOpen, 
bufSize);
+        Thread thread = new Thread(tailer);
+        thread.setDaemon(true);
+        thread.start();
+        return tailer;
+    }
+
+    /**
      * Creates and starts a Tailer for the given file with default buffer size.
      * 
      * @param file the file to follow.
@@ -225,6 +275,20 @@ public class Tailer implements Runnable 
     }
 
     /**
+     * Creates and starts a Tailer for the given file with default buffer size.
+     * 
+     * @param file the file to follow.
+     * @param listener the TailerListener to use.
+     * @param delayMillis the delay between checks of the file for new content 
in milliseconds.
+     * @param end Set to true to tail from the end of the file, false to tail 
from the beginning of the file.
+     * @param reOpen whether to close/reopen the file between chunks
+     * @return The new tailer
+     */
+    public static Tailer create(File file, TailerListener listener, long 
delayMillis, boolean end, boolean reOpen) {
+        return create(file, listener, delayMillis, end, reOpen, 
DEFAULT_BUFSIZE);
+    }
+
+    /**
      * Creates and starts a Tailer for the given file, starting at the 
beginning of the file
      * 
      * @param file the file to follow.
@@ -345,10 +409,17 @@ public class Tailer implements Runnable 
                         last = System.currentTimeMillis();
                     }
                 }
+                if (reOpen) {
+                    IOUtils.closeQuietly(reader);
+                }
                 try {
                     Thread.sleep(delayMillis);
                 } catch (InterruptedException e) {
                 }
+                if (run && reOpen) {
+                    reader = new RandomAccessFile(file, RAF_MODE);
+                    reader.seek(position);
+                }
             }
 
         } catch (Exception e) {

Modified: 
commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java?rev=1348698&r1=1348697&r2=1348698&view=diff
==============================================================================
--- 
commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java
 (original)
+++ 
commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java
 Mon Jun 11 01:09:58 2012
@@ -146,7 +146,9 @@ public class TailerTest extends FileBase
         final File file = new File(getTestDirectory(), "tailer1-test.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener();
-        tailer = new Tailer(file, listener, delayMillis, false);
+        String osname = System.getProperty("os.name");
+        boolean isWindows = osname.startsWith("Windows");
+        tailer = new Tailer(file, listener, delayMillis, false, isWindows);
         final Thread thread = new Thread(tailer);
         thread.start();
 
@@ -178,9 +180,7 @@ public class TailerTest extends FileBase
         // Delete & re-create
         file.delete();
         boolean exists = file.exists();
-        String osname = System.getProperty("os.name");
-        boolean isWindows = osname.startsWith("Windows");
-        assertFalse("File should not exist (except on Windows)", exists && 
!isWindows);
+        assertFalse("File should not exist", exists);
         createFile(file, 0);
         Thread.sleep(testDelayMillis);
 


Reply via email to