WatchAndRestartMachine implements Runnable { @Override public void run() { for (;;) { WatchKey watchKey; try { watchKey = watchService.take(); takeCount.incrementAndGet(); } catch (InterruptedException e) { if (!shutdown) { log.error("Unexpectedly interrupted while waiting for take()", e); } return; } Path path = mapOfWatchKeysToPaths.get(watchKey); if (path == null) { log.error("WatchKey not recognized!!"); continue; } for (WatchEvent<?> watchEvent : watchKey.pollEvents()) { WatchEvent.Kind watchEventKind = watchEvent.kind(); if (watchEventKind == OVERFLOW) { continue; } WatchEvent<Path> ev = (WatchEvent<Path>) watchEvent; Path name = ev.context(); Path child = path.resolve(name); if (watchEventKind == ENTRY_MODIFY) { if (!child.toFile().isDirectory()) { handleNewOrModifiedFile("Modified", child); } } if (watchEventKind == ENTRY_CREATE) { if (!child.toFile().isDirectory()) { handleNewOrModifiedFile("New", child); } try { if (Files.isDirectory(child, NOFOLLOW_LINKS)) { registerAll(child); } } catch (IOException e) { log.error("Something fishy happened. Unable to register new dir for watching", e); } } } boolean valid = watchKey.reset(); if (!valid) { mapOfWatchKeysToPaths.remove(watchKey); if (mapOfWatchKeysToPaths.isEmpty()) { break; } } } } WatchAndRestartMachine(
            Path directoryToRecursivelyWatch,
            Set<String> includes,
            Set<String> excludes,
            DelayedRestartTrigger restartTrigger);  WatchAndRestartMachine(
            Set<Path> directoriesToRecursivelyWatch,
            Set<String> includes,
            Set<String> excludes,
            DelayedRestartTrigger restartTrigger); void shutdown(); @Override void run(); void handleNewOrModifiedFile(String newOrMod, Path path); static RuleMatch matchRule(Set<String> includes, Set<String> excludes, String string); static boolean checkIfWouldBeExcluded(Set<String> patterns, String string);  }
@Test public void run() throws Exception { File watchDir = new File("target/fake-watch-dir"); watchDir.mkdirs(); File assetsDir = new File(watchDir, "assets"); assetsDir.mkdirs(); File newTxtFile = new File(watchDir, "test.txt"); newTxtFile.delete(); File newIncludedTxtFile = new File(assetsDir, "included.txt"); newIncludedTxtFile.delete(); File newPngFile = new File(assetsDir, "test.png"); newPngFile.delete(); DelayedRestartTrigger restartTrigger = mock(DelayedRestartTrigger.class); final WatchAndRestartMachine watcher = new WatchAndRestartMachine( watchDir.toPath(), new HashSet<>(Arrays.asList("(.*)included.txt")), new HashSet<>(Arrays.asList(DEFAULT_EXCLUDE_PATTERNS)), restartTrigger ); Thread watcherThread = new Thread(watcher); watcherThread.start(); try { OutputStream os = new FileOutputStream(newTxtFile); os.close(); verify(restartTrigger, timeout(10000)).trigger(); Mockito.reset(restartTrigger); os = new FileOutputStream(newTxtFile); os.write("Hello!".getBytes()); os.close(); verify(restartTrigger, timeout(10000).atLeast(1)).trigger(); verify(restartTrigger, atMost(2)).trigger(); Mockito.reset(restartTrigger); os = new FileOutputStream(newPngFile); os.close(); verify(restartTrigger, Mockito.after(10000).never()).trigger(); os = new FileOutputStream(newPngFile); os.write("Hello!".getBytes()); os.close(); verify(restartTrigger, Mockito.after(10000).never()).trigger(); os = new FileOutputStream(newIncludedTxtFile); os.close(); verify(restartTrigger, timeout(10000).atLeast(1)).trigger(); verify(restartTrigger, atMost(2)).trigger(); } finally { watcher.shutdown(); watcherThread.interrupt(); } }