OSDN Git Service

要修正コメント追加
[coroid/inqubus.git] / frontend / src / yukihane / inqubus / filewatch / FileWatch.java
1 package yukihane.inqubus.filewatch;
2
3 import java.io.IOException;
4 import java.nio.file.DirectoryStream;
5 import java.nio.file.FileSystems;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.nio.file.StandardWatchEventKinds;
9 import java.nio.file.WatchEvent;
10 import java.nio.file.WatchEvent.Kind;
11 import java.nio.file.WatchKey;
12 import java.nio.file.WatchService;
13 import java.util.Collection;
14 import java.util.HashSet;
15 import java.util.Set;
16 import java.util.logging.Level;
17 import java.util.logging.Logger;
18
19 /**
20  *
21  * @author yuki
22  */
23 public final class FileWatch implements Runnable {
24
25     private static final Logger logger = Logger.getLogger(FileWatch.class.getName());
26     private final Set<Path> files;
27     private final Set<Path> directories;
28
29     public FileWatch(Collection<Path> dirs) {
30         FileDir res = new FileDir();
31         getFileDir(dirs, res);
32
33         this.files = new HashSet<>(res.files);
34         this.directories = new HashSet<>(res.dirs);
35         if(logger.isLoggable(Level.FINER)) {
36             logger.log(Level.FINER, "search dirs: {0}", directories);
37             logger.log(Level.FINER, "exist files: {0}", files);
38         }
39     }
40
41     public Set<Path> getFiles() {
42         synchronized (files) {
43             return new HashSet<>(files);
44         }
45     }
46
47     private void getFileDir(Iterable<Path> paths, FileDir result) {
48         for (Path p : paths) {
49             getFileDir(p, result);
50         }
51     }
52
53     private void getFileDir(Path path, FileDir result) {
54         try {
55             if (Files.isDirectory(path)) {
56                 result.dirs.add(path);
57                 DirectoryStream<Path> dir = Files.newDirectoryStream(path);
58                 getFileDir(dir, result);
59             } else if (Files.isRegularFile(path)) {
60                 result.files.add(path);
61             }
62         } catch (IOException ex) {
63             logger.log(Level.WARNING, "パスの処理中にエラー: {0}", new Object[]{path});
64         }
65     }
66
67     private static class FileDir {
68
69         private final Set<Path> files = new HashSet<>();
70         private final Set<Path> dirs = new HashSet<>();
71     }
72
73     @Override
74     public void run() {
75         logger.log(Level.FINER, "FileWatch start");
76         try {
77             final WatchService ws = FileSystems.getDefault().newWatchService();
78             for (Path p : directories) {
79                 p.register(ws, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE);
80             }
81
82             while (true) {
83                 final WatchKey wk = ws.take();
84                 for (final WatchEvent<?> event : wk.pollEvents()) {
85                     final Kind<?> kind = event.kind();
86                     if (kind.equals(StandardWatchEventKinds.ENTRY_CREATE)) {
87                         final Path p = (Path) event.context();
88                         // FIXME isRegularFile だとファイルであると認識してくれない…?
89                         if (Files.isRegularFile(p)) {
90                             logger.log(Level.FINEST, "ファイル追加: {0}", p);
91                             synchronized (files) {
92                                 files.add(p);
93                             }
94                         }
95                     } else if (kind.equals(StandardWatchEventKinds.ENTRY_DELETE)) {
96                         final Path p = (Path) event.context();
97                         if (Files.isRegularFile(p)) {
98                             logger.log(Level.FINEST, "ファイル削除: {0}", p);
99                             synchronized (files) {
100                                 files.remove(p);
101                             }
102                         }
103                     }
104                 }
105
106                 if (!wk.reset()) {
107                     System.out.println("No longer valid");
108                     wk.cancel();
109                     ws.close();
110                     break;
111                 }
112
113             }
114         } catch (InterruptedException ex) {
115             ex.printStackTrace();
116         } catch (IOException ex) {
117             ex.printStackTrace();
118         }
119     }
120 }