Search in sources :

Example 61 with WatchKey

use of java.nio.file.WatchKey in project hutool by looly.

the class WatchServer method watch.

/**
 * 执行事件获取并处理
 *
 * @param action     监听回调函数,实现此函数接口用于处理WatchEvent事件
 * @param watchFilter 监听过滤接口,通过实现此接口过滤掉不需要监听的情况,null表示不过滤
 * @since 5.4.0
 */
public void watch(WatchAction action, Filter<WatchEvent<?>> watchFilter) {
    WatchKey wk;
    try {
        wk = watchService.take();
    } catch (InterruptedException | ClosedWatchServiceException e) {
        // 用户中断
        close();
        return;
    }
    final Path currentPath = watchKeyPathMap.get(wk);
    for (WatchEvent<?> event : wk.pollEvents()) {
        // 如果监听文件,检查当前事件是否与所监听文件关联
        if (null != watchFilter && false == watchFilter.accept(event)) {
            continue;
        }
        action.doAction(event, currentPath);
    }
    wk.reset();
}
Also used : Path(java.nio.file.Path) WatchKey(java.nio.file.WatchKey) ClosedWatchServiceException(java.nio.file.ClosedWatchServiceException)

Example 62 with WatchKey

use of java.nio.file.WatchKey in project hutool by looly.

the class WatchServer method registerPath.

/**
 * 将指定路径加入到监听中
 *
 * @param path     路径
 * @param maxDepth 递归下层目录的最大深度
 */
public void registerPath(Path path, int maxDepth) {
    final WatchEvent.Kind<?>[] kinds = ArrayUtil.defaultIfEmpty(this.events, WatchKind.ALL);
    try {
        final WatchKey key;
        if (ArrayUtil.isEmpty(this.modifiers)) {
            key = path.register(this.watchService, kinds);
        } else {
            key = path.register(this.watchService, kinds, this.modifiers);
        }
        watchKeyPathMap.put(key, path);
        // 递归注册下一层层级的目录
        if (maxDepth > 1) {
            // 遍历所有子目录并加入监听
            Files.walkFileTree(path, EnumSet.noneOf(FileVisitOption.class), maxDepth, new SimpleFileVisitor<Path>() {

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    // 继续添加目录
                    registerPath(dir, 0);
                    return super.postVisitDirectory(dir, exc);
                }
            });
        }
    } catch (IOException e) {
        if (false == (e instanceof AccessDeniedException)) {
            throw new WatchException(e);
        }
    // 对于禁止访问的目录,跳过监听
    }
}
Also used : Path(java.nio.file.Path) AccessDeniedException(java.nio.file.AccessDeniedException) FileVisitOption(java.nio.file.FileVisitOption) WatchKey(java.nio.file.WatchKey) FileVisitResult(java.nio.file.FileVisitResult) IOException(java.io.IOException)

Example 63 with WatchKey

use of java.nio.file.WatchKey in project gradle by gradle.

the class WatchServiceRegistrar method watchDir.

protected void watchDir(Path dir) throws IOException {
    LOG.debug("Registering watch for {}", dir);
    if (Thread.currentThread().isInterrupted()) {
        LOG.debug("Skipping adding watch since current thread is interrupted.");
    }
    // on Windows, check if any parent is already watched
    for (Path path = dir; path != null; path = FILE_TREE_WATCHING_SUPPORTED ? path.getParent() : null) {
        WatchKey previousWatchKey = watchKeys.get(path);
        if (previousWatchKey != null && previousWatchKey.isValid()) {
            LOG.debug("Directory {} is already watched and the watch is valid, not adding another one.", path);
            return;
        }
    }
    int retryCount = 0;
    IOException lastException = null;
    while (retryCount++ < 2) {
        try {
            WatchKey watchKey = dir.register(watchService, WATCH_KINDS, WATCH_MODIFIERS);
            watchKeys.put(dir, watchKey);
            return;
        } catch (IOException e) {
            LOG.debug("Exception in registering for watching of " + dir, e);
            lastException = e;
            if (e instanceof NoSuchFileException) {
                LOG.debug("Return silently since directory doesn't exist.");
                return;
            }
            if (e instanceof FileSystemException && e.getMessage() != null && e.getMessage().contains("Bad file descriptor")) {
                // retry after getting "Bad file descriptor" exception
                LOG.debug("Retrying after 'Bad file descriptor'");
                continue;
            }
            // So, we just ignore the exception if the dir doesn't exist anymore
            if (!Files.exists(dir)) {
                // return silently when directory doesn't exist
                LOG.debug("Return silently since directory doesn't exist.");
                return;
            } else {
                // no retry
                throw e;
            }
        }
    }
    LOG.debug("Retry count exceeded, throwing last exception");
    throw lastException;
}
Also used : Path(java.nio.file.Path) FileSystemException(java.nio.file.FileSystemException) WatchKey(java.nio.file.WatchKey) NoSuchFileException(java.nio.file.NoSuchFileException) IOException(java.io.IOException)

Example 64 with WatchKey

use of java.nio.file.WatchKey in project cas by apereo.

the class ServiceRegistryConfigWatcher method run.

@Override
public void run() {
    if (this.running.compareAndSet(false, true)) {
        while (this.running.get()) {
            // wait for key to be signaled
            WatchKey key = null;
            try {
                key = this.watcher.take();
                handleEvent(key);
            } catch (final InterruptedException e) {
                return;
            } finally {
                /*
                        Reset the key -- this step is critical to receive
                        further watch events. If the key is no longer valid, the directory
                        is inaccessible so exit the loop.
                     */
                final boolean valid = key != null && key.reset();
                if (!valid) {
                    LOGGER.warn("Directory key is no longer valid. Quitting watcher service");
                }
            }
        }
    }
}
Also used : WatchKey(java.nio.file.WatchKey)

Example 65 with WatchKey

use of java.nio.file.WatchKey in project bazel by bazelbuild.

the class WatchServiceDiffAwareness method collectChanges.

/** Returns the changed files caught by the watch service. */
private Set<Path> collectChanges() throws BrokenDiffAwarenessException, IOException {
    Set<Path> createdFilesAndDirectories = new HashSet<>();
    Set<Path> deletedOrModifiedFilesAndDirectories = new HashSet<>();
    Set<Path> deletedTrackedDirectories = new HashSet<>();
    WatchKey watchKey;
    while ((watchKey = watchService.poll()) != null) {
        Path dir = watchKeyToDirBiMap.get(watchKey);
        Preconditions.checkArgument(dir != null);
        // construct the diff of this directory since the last #collectChanges call.
        for (WatchEvent<?> event : watchKey.pollEvents()) {
            Kind<?> kind = event.kind();
            if (kind == StandardWatchEventKinds.OVERFLOW) {
                // gently.
                throw new BrokenDiffAwarenessException("Overflow when watching local filesystem for " + "changes");
            }
            if (event.context() == null) {
                // detail here.
                throw new BrokenDiffAwarenessException("Insufficient information from local file system " + "watcher");
            }
            // For the events we've registered, the context given is a relative path.
            Path relativePath = (Path) event.context();
            Path path = dir.resolve(relativePath);
            Preconditions.checkState(path.isAbsolute(), path);
            if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
                createdFilesAndDirectories.add(path);
                deletedOrModifiedFilesAndDirectories.remove(path);
            } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
                createdFilesAndDirectories.remove(path);
                deletedOrModifiedFilesAndDirectories.add(path);
                WatchKey deletedDirectoryKey = watchKeyToDirBiMap.inverse().get(path);
                if (deletedDirectoryKey != null) {
                    // If the deleted directory has children, then there will also be events for the
                    // WatchKey of the directory itself. WatchService#poll doesn't specify the order in
                    // which WatchKeys are returned, so the key for the directory itself may be processed
                    // *after* the current key (the parent of the deleted directory), and so we don't want
                    // to remove the deleted directory from our bimap just yet.
                    //
                    // For example, suppose we have the file '/root/a/foo.txt' and are watching the
                    // directories '/root' and '/root/a'. If the directory '/root/a' gets deleted then the
                    // following is a valid sequence of events by key.
                    //
                    // WatchKey '/root/'
                    // WatchEvent EVENT_MODIFY 'a'
                    // WatchEvent EVENT_DELETE 'a'
                    // WatchKey '/root/a'
                    // WatchEvent EVENT_DELETE 'foo.txt'
                    deletedTrackedDirectories.add(path);
                    // Since inotify uses inodes under the covers we cancel our registration on this key to
                    // avoid getting WatchEvents from a new directory that happens to have the same inode.
                    deletedDirectoryKey.cancel();
                }
            } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
                // created.
                if (!createdFilesAndDirectories.contains(path)) {
                    deletedOrModifiedFilesAndDirectories.add(path);
                }
            }
        }
        if (!watchKey.reset()) {
            // Watcher got deleted, directory no longer valid.
            watchKeyToDirBiMap.remove(watchKey);
        }
    }
    for (Path path : deletedTrackedDirectories) {
        WatchKey staleKey = watchKeyToDirBiMap.inverse().get(path);
        watchKeyToDirBiMap.remove(staleKey);
    }
    if (watchKeyToDirBiMap.isEmpty()) {
        // No more directories to watch, something happened the root directory being watched.
        throw new IOException("Root directory " + watchRootPath + " became inaccessible.");
    }
    Set<Path> changedPaths = new HashSet<>();
    for (Path path : createdFilesAndDirectories) {
        if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) {
            // This is a new directory, so changes to it since its creation have not been watched.
            // We manually traverse the directory tree to register all the new subdirectories and find
            // all the new subdirectories and files.
            changedPaths.addAll(registerSubDirectoriesAndReturnContents(path));
        } else {
            changedPaths.add(path);
        }
    }
    changedPaths.addAll(deletedOrModifiedFilesAndDirectories);
    return changedPaths;
}
Also used : Path(java.nio.file.Path) WatchKey(java.nio.file.WatchKey) IOException(java.io.IOException) HashSet(java.util.HashSet)

Aggregations

WatchKey (java.nio.file.WatchKey)134 Path (java.nio.file.Path)88 WatchEvent (java.nio.file.WatchEvent)65 IOException (java.io.IOException)49 WatchService (java.nio.file.WatchService)30 File (java.io.File)27 ClosedWatchServiceException (java.nio.file.ClosedWatchServiceException)18 ArrayList (java.util.ArrayList)10 Test (org.junit.Test)10 HashMap (java.util.HashMap)7 Map (java.util.Map)7 FileSystems (java.nio.file.FileSystems)6 FileVisitResult (java.nio.file.FileVisitResult)6 HashSet (java.util.HashSet)6 List (java.util.List)6 StandardWatchEventKinds (java.nio.file.StandardWatchEventKinds)5 InputStream (java.io.InputStream)4 AccessDeniedException (java.nio.file.AccessDeniedException)4 Kind (java.nio.file.WatchEvent.Kind)4 Logger (org.slf4j.Logger)4