src/share/sample/nio/file/WatchDir.java

Print this page




  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 import java.nio.file.*;
  33 import static java.nio.file.StandardWatchEventKind.*;
  34 import static java.nio.file.LinkOption.*;
  35 import java.nio.file.attribute.*;
  36 import java.io.*;
  37 import java.util.*;
  38 
  39 /**
  40  * Example to watch a directory (or tree) for changes to files.
  41  */
  42 
  43 public class WatchDir {
  44 
  45     private final WatchService watcher;
  46     private final Map<WatchKey,Path> keys;
  47     private final boolean recursive;
  48     private boolean trace = false;

  49 
  50     @SuppressWarnings("unchecked")
  51     static <T> WatchEvent<T> cast(WatchEvent<?> event) {
  52         return (WatchEvent<T>)event;
  53     }
  54 
  55     /**
  56      * Register the given directory with the WatchService
  57      */
  58     private void register(Path dir) throws IOException {
  59         WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
  60         if (trace) {
  61             Path prev = keys.get(key);
  62             if (prev == null) {
  63                 System.out.format("register: %s\n", dir);
  64             } else {
  65                 if (!dir.equals(prev)) {
  66                     System.out.format("update: %s -> %s\n", prev, dir);
  67                 }
  68             }
  69         }
  70         keys.put(key, dir);
  71     }
  72 
  73     /**
  74      * Register the given directory, and all its sub-directories, with the
  75      * WatchService.
  76      */
  77     private void registerAll(final Path start) throws IOException {
  78         // register directory and sub-directories
  79         Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
  80             @Override
  81             public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
  82                 throws IOException
  83             {
  84                 register(dir);
  85                 return FileVisitResult.CONTINUE;
  86             }
  87         });
  88     }
  89 
  90     /**
  91      * Creates a WatchService and registers the given directory
  92      */
  93     WatchDir(Path dir, boolean recursive) throws IOException {
  94         this.watcher = FileSystems.getDefault().newWatchService();
  95         this.keys = new HashMap<WatchKey,Path>();
  96         this.recursive = recursive;
  97 
  98         if (recursive) {
  99             System.out.format("Scanning %s ...\n", dir);
 100             registerAll(dir);
 101             System.out.println("Done.");
 102         } else {
 103             register(dir);
 104         }
 105 
 106         // enable trace after initial registration
 107         this.trace = true;
 108     }
 109 
 110     /**
 111      * Process all events for keys queued to the watcher
 112      */
 113     void processEvents() {
 114         for (;;) {
 115 
 116             // wait for key to be signalled
 117             WatchKey key;
 118             try {
 119                 key = watcher.take();
 120             } catch (InterruptedException x) {
 121                 return;
 122             }
 123 
 124             Path dir = keys.get(key);
 125             if (dir == null) {
 126                 System.err.println("WatchKey not recognized!!");
 127                 continue;
 128             }
 129 
 130             for (WatchEvent<?> event: key.pollEvents()) {
 131                 WatchEvent.Kind kind = event.kind();
 132 
 133                 // TBD - provide example of how OVERFLOW event is handled
 134                 if (kind == OVERFLOW) {
 135                     continue;
 136                 }
 137 
 138                 // Context for directory entry event is the file name of entry
 139                 WatchEvent<Path> ev = cast(event);
 140                 Path name = ev.context();
 141                 Path child = dir.resolve(name);
 142 
 143                 // print out event
 144                 System.out.format("%s: %s\n", event.kind().name(), child);
 145 
 146                 // if directory is created, and watching recursively, then
 147                 // register it and its sub-directories
 148                 if (recursive && (kind == ENTRY_CREATE)) {
 149                     try {
 150                         if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
 151                             registerAll(child);
 152                         }
 153                     } catch (IOException x) {
 154                         // ignore to keep sample readbale
 155                     }
 156                 }
 157             }
 158 
 159             // reset key and remove from set if directory no longer accessible
 160             boolean valid = key.reset();
 161             if (!valid) {
 162                 keys.remove(key);
 163 
 164                 // all directories are inaccessible
 165                 if (keys.isEmpty()) {
 166                     break;
 167                 }
 168             }
 169         }
 170     }
 171 
 172     static void usage() {
 173         System.err.println("usage: java WatchDir [-r] dir");
 174         System.exit(-1);
 175     }
 176 
 177     public static void main(String[] args) throws IOException {
 178         // parse arguments
 179         if (args.length == 0 || args.length > 2)
 180             usage();
 181         boolean recursive = false;
 182         int dirArg = 0;
 183         if (args[0].equals("-r")) {
 184             if (args.length < 2)
 185                 usage();
 186             recursive = true;
 187             dirArg++;
 188         }
 189 


  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 import java.nio.file.*;
  33 import static java.nio.file.StandardWatchEventKind.*;
  34 import static java.nio.file.LinkOption.*;
  35 import java.nio.file.attribute.*;
  36 import java.io.IOException;

  37 
  38 /**
  39  * Example to watch a directory (or tree) for changes to files.
  40  */
  41 
  42 public class WatchDir {
  43 
  44     private final WatchService watcher;

  45     private final boolean recursive;
  46     private boolean trace = false;
  47     private int count;
  48 
  49     @SuppressWarnings("unchecked")
  50     static <T> WatchEvent<T> cast(WatchEvent<?> event) {
  51         return (WatchEvent<T>)event;
  52     }
  53 
  54     /**
  55      * Register the given directory with the WatchService
  56      */
  57     private void register(Path dir) throws IOException {
  58         WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
  59         count++;
  60         if (trace)

  61             System.out.format("register: %s\n", dir);



  62     }




  63 
  64     /**
  65      * Register the given directory, and all its sub-directories, with the
  66      * WatchService.
  67      */
  68     private void registerAll(final Path start) throws IOException {
  69         // register directory and sub-directories
  70         Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
  71             @Override
  72             public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
  73                 throws IOException
  74             {
  75                 register(dir);
  76                 return FileVisitResult.CONTINUE;
  77             }
  78         });
  79     }
  80 
  81     /**
  82      * Creates a WatchService and registers the given directory
  83      */
  84     WatchDir(Path dir, boolean recursive) throws IOException {
  85         this.watcher = FileSystems.getDefault().newWatchService();

  86         this.recursive = recursive;
  87 
  88         if (recursive) {
  89             System.out.format("Scanning %s ...\n", dir);
  90             registerAll(dir);
  91             System.out.println("Done.");
  92         } else {
  93             register(dir);
  94         }
  95 
  96         // enable trace after initial registration
  97         this.trace = true;
  98     }
  99 
 100     /**
 101      * Process all events for keys queued to the watcher
 102      */
 103     void processEvents() {
 104         for (;;) {
 105 
 106             // wait for key to be signalled
 107             WatchKey key;
 108             try {
 109                 key = watcher.take();
 110             } catch (InterruptedException x) {
 111                 return;
 112             }
 113 






 114             for (WatchEvent<?> event: key.pollEvents()) {
 115                 WatchEvent.Kind kind = event.kind();
 116 
 117                 // TBD - provide example of how OVERFLOW event is handled
 118                 if (kind == OVERFLOW) {
 119                     continue;
 120                 }
 121 
 122                 // Context for directory entry event is the file name of entry
 123                 WatchEvent<Path> ev = cast(event);
 124                 Path name = ev.context();
 125                 Path child = ((Path)key.watchable()).resolve(name);
 126 
 127                 // print out event
 128                 System.out.format("%s: %s\n", event.kind().name(), child);
 129 
 130                 // if directory is created, and watching recursively, then
 131                 // register it and its sub-directories
 132                 if (recursive && (kind == ENTRY_CREATE)) {
 133                     try {
 134                         if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
 135                             registerAll(child);
 136                         }
 137                     } catch (IOException x) {
 138                         // ignore to keep sample readbale
 139                     }
 140                 }
 141             }
 142 
 143             // reset key 
 144             boolean valid = key.reset();
 145             if (!valid) {
 146                 // directory no longer accessible
 147                 count--;
 148                 if (count == 0)

 149                     break;
 150             }
 151         }

 152     }
 153 
 154     static void usage() {
 155         System.err.println("usage: java WatchDir [-r] dir");
 156         System.exit(-1);
 157     }
 158 
 159     public static void main(String[] args) throws IOException {
 160         // parse arguments
 161         if (args.length == 0 || args.length > 2)
 162             usage();
 163         boolean recursive = false;
 164         int dirArg = 0;
 165         if (args[0].equals("-r")) {
 166             if (args.length < 2)
 167                 usage();
 168             recursive = true;
 169             dirArg++;
 170         }
 171