|
26 | 26 | */ |
27 | 27 | package engineering.swat.watch; |
28 | 28 |
|
| 29 | +import java.io.FileNotFoundException; |
29 | 30 | import java.io.IOException; |
| 31 | +import java.nio.file.FileSystemException; |
30 | 32 | import java.nio.file.Files; |
| 33 | +import java.nio.file.InvalidPathException; |
31 | 34 | import java.nio.file.LinkOption; |
| 35 | +import java.nio.file.NoSuchFileException; |
| 36 | +import java.nio.file.NotDirectoryException; |
32 | 37 | import java.nio.file.Path; |
33 | 38 | import java.util.concurrent.Executor; |
34 | 39 | import java.util.function.BiConsumer; |
@@ -76,28 +81,13 @@ private Watch(Path path, WatchScope scope) { |
76 | 81 | * Watch a path for updates, optionally also get events for its children/descendants |
77 | 82 | * @param path which absolute path to monitor, can be a file or a directory, but has to be absolute |
78 | 83 | * @param scope for directories you can also choose to monitor it's direct children or all it's descendants |
79 | | - * @throws IllegalArgumentException in case a path is not supported (in relation to the scope) |
| 84 | + * @throws IllegalArgumentException in case a path is not supported |
80 | 85 | * @return watch builder that can be further configured and then started |
81 | 86 | */ |
82 | 87 | public static Watch build(Path path, WatchScope scope) { |
83 | 88 | if (!path.isAbsolute()) { |
84 | 89 | throw new IllegalArgumentException("We can only watch absolute paths"); |
85 | 90 | } |
86 | | - switch (scope) { |
87 | | - case PATH_AND_CHILDREN: // intended fallthrough |
88 | | - case PATH_AND_ALL_DESCENDANTS: |
89 | | - if (!Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { |
90 | | - throw new IllegalArgumentException("Only directories are supported for this scope: " + scope); |
91 | | - } |
92 | | - break; |
93 | | - case PATH_ONLY: |
94 | | - if (Files.isSymbolicLink(path)) { |
95 | | - throw new IllegalArgumentException("Symlinks are not supported"); |
96 | | - } |
97 | | - break; |
98 | | - default: |
99 | | - throw new IllegalArgumentException("Unsupported scope: " + scope); |
100 | | - } |
101 | 91 | return new Watch(path, scope); |
102 | 92 | } |
103 | 93 |
|
@@ -192,16 +182,38 @@ public Watch onOverflow(Approximation whichFiles) { |
192 | 182 | return this; |
193 | 183 | } |
194 | 184 |
|
| 185 | + private void validateOptions() throws IOException { |
| 186 | + if (this.eventHandler == EMPTY_HANDLER) { |
| 187 | + throw new IllegalStateException("There is no `on` handler defined"); |
| 188 | + } |
| 189 | + if (!Files.exists(path)) { |
| 190 | + throw new NoSuchFileException(path.toString(), null, "Cannot open a watch on a non-existing path"); |
| 191 | + } |
| 192 | + switch (scope) { |
| 193 | + case PATH_AND_CHILDREN: // intended fallthrough |
| 194 | + case PATH_AND_ALL_DESCENDANTS: |
| 195 | + if (!Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { |
| 196 | + throw new FileSystemException(path.toString(), null, "Only directories are supported for this scope: " + scope); |
| 197 | + } |
| 198 | + break; |
| 199 | + case PATH_ONLY: |
| 200 | + if (Files.isSymbolicLink(path)) { |
| 201 | + throw new FileSystemException(path.toString(), null, "Symlinks are not supported"); |
| 202 | + } |
| 203 | + break; |
| 204 | + default: |
| 205 | + throw new IllegalArgumentException("Unsupported scope: " + scope); |
| 206 | + } |
| 207 | + } |
| 208 | + |
195 | 209 | /** |
196 | 210 | * Start watch the path for events. |
197 | 211 | * @return a subscription for the watch, when closed, new events will stop being registered to the worker pool. |
198 | | - * @throws IOException in case the starting of the watcher caused an underlying IO exception |
| 212 | + * @throws IOException in case the starting of the watcher caused an underlying IO exception or we detect it is an invalid watch |
199 | 213 | * @throws IllegalStateException the watchers is not configured correctly (for example, missing {@link #on(Consumer)}, or a watcher is started twice) |
200 | 214 | */ |
201 | 215 | public ActiveWatch start() throws IOException { |
202 | | - if (this.eventHandler == EMPTY_HANDLER) { |
203 | | - throw new IllegalStateException("There is no onEvent handler defined"); |
204 | | - } |
| 216 | + validateOptions(); |
205 | 217 | var executor = this.executor; |
206 | 218 | if (executor == null) { |
207 | 219 | executor = FALLBACK_EXECUTOR; |
|
0 commit comments