From 96072854aee200ad3ca4a8c39de4302b7c01cd12 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 21 Feb 2025 17:19:12 +0100 Subject: [PATCH 1/3] Add `ActiveWatch` as event handler arg to `JDK...Watch` classes --- .../swat/watch/impl/jdk/JDKBaseWatch.java | 8 ++++---- .../swat/watch/impl/jdk/JDKDirectoryWatch.java | 7 ++++--- .../swat/watch/impl/jdk/JDKFileWatch.java | 9 +++++---- .../watch/impl/jdk/JDKRecursiveDirectoryWatch.java | 14 +++++++------- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java index fd5cfc32..ad1c9d99 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java @@ -31,7 +31,7 @@ import java.nio.file.StandardWatchEventKinds; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; +import java.util.function.BiConsumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -45,10 +45,10 @@ public abstract class JDKBaseWatch implements ActiveWatch { protected final Path path; protected final Executor exec; - protected final Consumer eventHandler; + protected final BiConsumer eventHandler; protected final AtomicBoolean started = new AtomicBoolean(); - protected JDKBaseWatch(Path path, Executor exec, Consumer eventHandler) { + protected JDKBaseWatch(Path path, Executor exec, BiConsumer eventHandler) { this.path = path; this.exec = exec; this.eventHandler = eventHandler; @@ -123,7 +123,7 @@ private WatchEvent.Kind translate(java.nio.file.WatchEvent.Kind jdkKind) { @Override public void handleEvent(WatchEvent e) { - eventHandler.accept(e); + eventHandler.accept(this, e); } @Override diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java index 79cd65c2..65e6b028 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java @@ -31,12 +31,13 @@ import java.nio.file.Path; import java.util.List; import java.util.concurrent.Executor; -import java.util.function.Consumer; +import java.util.function.BiConsumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import engineering.swat.watch.ActiveWatch; import engineering.swat.watch.WatchEvent; import engineering.swat.watch.impl.util.BundledSubscription; import engineering.swat.watch.impl.util.SubscriptionKey; @@ -49,11 +50,11 @@ public class JDKDirectoryWatch extends JDKBaseWatch { private static final BundledSubscription>> BUNDLED_JDK_WATCHERS = new BundledSubscription<>(JDKPoller::register); - public JDKDirectoryWatch(Path directory, Executor exec, Consumer eventHandler) { + public JDKDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler) { this(directory, exec, eventHandler, false); } - public JDKDirectoryWatch(Path directory, Executor exec, Consumer eventHandler, boolean nativeRecursive) { + public JDKDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler, boolean nativeRecursive) { super(directory, exec, eventHandler); this.nativeRecursive = nativeRecursive; } diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java index c74e99cb..8bf41e6b 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java @@ -29,12 +29,13 @@ import java.io.IOException; import java.nio.file.Path; import java.util.concurrent.Executor; -import java.util.function.Consumer; +import java.util.function.BiConsumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; +import engineering.swat.watch.ActiveWatch; import engineering.swat.watch.WatchEvent; /** @@ -46,7 +47,7 @@ public class JDKFileWatch extends JDKBaseWatch { private final Logger logger = LogManager.getLogger(); private final JDKBaseWatch internal; - public JDKFileWatch(Path file, Executor exec, Consumer eventHandler) { + public JDKFileWatch(Path file, Executor exec, BiConsumer eventHandler) { super(file, exec, eventHandler); var message = "The root path is not a valid path for a file watch"; @@ -54,9 +55,9 @@ public JDKFileWatch(Path file, Executor exec, Consumer eventHandler) var fileName = requireNonNull(file.getFileName(), message); assert !parent.equals(file); - this.internal = new JDKDirectoryWatch(parent, exec, e -> { + this.internal = new JDKDirectoryWatch(parent, exec, (w, e) -> { if (fileName.equals(e.getRelativePath())) { - eventHandler.accept(e); + eventHandler.accept(w, e); } }); diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java index 2ea15483..62d22442 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java @@ -42,24 +42,25 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; -import java.util.function.Consumer; +import java.util.function.BiConsumer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import engineering.swat.watch.ActiveWatch; import engineering.swat.watch.WatchEvent; public class JDKRecursiveDirectoryWatch extends JDKBaseWatch { private final Logger logger = LogManager.getLogger(); private final ConcurrentMap activeWatches = new ConcurrentHashMap<>(); - public JDKRecursiveDirectoryWatch(Path directory, Executor exec, Consumer eventHandler) { + public JDKRecursiveDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler) { super(directory, exec, eventHandler); } private void processEvents(WatchEvent ev) { logger.trace("Forwarding event: {}", ev); - eventHandler.accept(ev); + eventHandler.accept(this, ev); logger.trace("Unwrapping event: {}", ev); switch (ev.getKind()) { case CREATED: handleCreate(ev); break; @@ -71,10 +72,9 @@ private void processEvents(WatchEvent ev) { private void publishExtraEvents(List ev) { logger.trace("Reporting new nested directories & files: {}", ev); - ev.forEach(eventHandler); + ev.forEach(e -> eventHandler.accept(this, e)); } - private void handleCreate(WatchEvent ev) { // between the event and the current state of the file system // we might have some nested directories we missed @@ -161,9 +161,9 @@ private void addNewDirectory(Path dir) throws IOException { } /** Make sure that the events are relative to the actual root of the recursive watch */ - private Consumer relocater(Path subRoot) { + private BiConsumer relocater(Path subRoot) { final Path newRelative = path.relativize(subRoot); - return ev -> { + return (w, ev) -> { var rewritten = new WatchEvent(ev.getKind(), path, newRelative.resolve(ev.getRelativePath())); processEvents(rewritten); }; From 4fb69dcf9f958d74a0468c2547a93ce2f830464b Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 21 Feb 2025 17:24:52 +0100 Subject: [PATCH 2/3] Add `ActiveWatch` as event handler arg to `Watcher` --- src/main/java/engineering/swat/watch/Watcher.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/engineering/swat/watch/Watcher.java b/src/main/java/engineering/swat/watch/Watcher.java index c176dfdb..d8c181ba 100644 --- a/src/main/java/engineering/swat/watch/Watcher.java +++ b/src/main/java/engineering/swat/watch/Watcher.java @@ -32,6 +32,7 @@ import java.nio.file.Path; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.function.BiConsumer; import java.util.function.Consumer; import org.apache.logging.log4j.LogManager; @@ -54,8 +55,8 @@ public class Watcher { private final Path path; private volatile Executor executor = CompletableFuture::runAsync; - private static final Consumer EMPTY_HANDLER = p -> {}; - private volatile Consumer eventHandler = EMPTY_HANDLER; + private static final BiConsumer EMPTY_HANDLER = (w, e) -> {}; + private volatile BiConsumer eventHandler = EMPTY_HANDLER; private Watcher(WatchScope scope, Path path) { @@ -103,7 +104,7 @@ public Watcher on(Consumer eventHandler) { if (this.eventHandler != EMPTY_HANDLER) { throw new IllegalArgumentException("on handler cannot be set more than once"); } - this.eventHandler = eventHandler; + this.eventHandler = (w, e) -> eventHandler.accept(e); return this; } @@ -114,7 +115,7 @@ public Watcher on(WatchEventListener listener) { if (this.eventHandler != EMPTY_HANDLER) { throw new IllegalArgumentException("on handler cannot be set more than once"); } - this.eventHandler = ev -> { + this.eventHandler = (w, ev) -> { switch (ev.getKind()) { case CREATED: listener.onCreated(ev); From 9ef704f301a1f99308ee29cc796b28e0deae3ac8 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 24 Feb 2025 12:11:14 +0100 Subject: [PATCH 3/3] Use `EventHandlingWatch` instead of `ActiveWatch` internally --- src/main/java/engineering/swat/watch/Watcher.java | 5 +++-- .../java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java | 4 ++-- .../engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java | 6 +++--- .../java/engineering/swat/watch/impl/jdk/JDKFileWatch.java | 4 ++-- .../swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java | 6 +++--- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/engineering/swat/watch/Watcher.java b/src/main/java/engineering/swat/watch/Watcher.java index d8c181ba..67d9345f 100644 --- a/src/main/java/engineering/swat/watch/Watcher.java +++ b/src/main/java/engineering/swat/watch/Watcher.java @@ -38,6 +38,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import engineering.swat.watch.impl.EventHandlingWatch; import engineering.swat.watch.impl.jdk.JDKDirectoryWatch; import engineering.swat.watch.impl.jdk.JDKFileWatch; import engineering.swat.watch.impl.jdk.JDKRecursiveDirectoryWatch; @@ -55,8 +56,8 @@ public class Watcher { private final Path path; private volatile Executor executor = CompletableFuture::runAsync; - private static final BiConsumer EMPTY_HANDLER = (w, e) -> {}; - private volatile BiConsumer eventHandler = EMPTY_HANDLER; + private static final BiConsumer EMPTY_HANDLER = (w, e) -> {}; + private volatile BiConsumer eventHandler = EMPTY_HANDLER; private Watcher(WatchScope scope, Path path) { diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java index 6981d2a0..f40595c3 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKBaseWatch.java @@ -45,10 +45,10 @@ public abstract class JDKBaseWatch implements EventHandlingWatch { protected final Path path; protected final Executor exec; - protected final BiConsumer eventHandler; + protected final BiConsumer eventHandler; protected final AtomicBoolean started = new AtomicBoolean(); - protected JDKBaseWatch(Path path, Executor exec, BiConsumer eventHandler) { + protected JDKBaseWatch(Path path, Executor exec, BiConsumer eventHandler) { this.path = path; this.exec = exec; this.eventHandler = eventHandler; diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java index 65e6b028..4fd2041b 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKDirectoryWatch.java @@ -37,8 +37,8 @@ import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import engineering.swat.watch.ActiveWatch; import engineering.swat.watch.WatchEvent; +import engineering.swat.watch.impl.EventHandlingWatch; import engineering.swat.watch.impl.util.BundledSubscription; import engineering.swat.watch.impl.util.SubscriptionKey; @@ -50,11 +50,11 @@ public class JDKDirectoryWatch extends JDKBaseWatch { private static final BundledSubscription>> BUNDLED_JDK_WATCHERS = new BundledSubscription<>(JDKPoller::register); - public JDKDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler) { + public JDKDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler) { this(directory, exec, eventHandler, false); } - public JDKDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler, boolean nativeRecursive) { + public JDKDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler, boolean nativeRecursive) { super(directory, exec, eventHandler); this.nativeRecursive = nativeRecursive; } diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java index 8bf41e6b..01820649 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKFileWatch.java @@ -35,8 +35,8 @@ import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; -import engineering.swat.watch.ActiveWatch; import engineering.swat.watch.WatchEvent; +import engineering.swat.watch.impl.EventHandlingWatch; /** * It's not possible to monitor a single file (or directory), so we have to find a directory watcher, and connect to that @@ -47,7 +47,7 @@ public class JDKFileWatch extends JDKBaseWatch { private final Logger logger = LogManager.getLogger(); private final JDKBaseWatch internal; - public JDKFileWatch(Path file, Executor exec, BiConsumer eventHandler) { + public JDKFileWatch(Path file, Executor exec, BiConsumer eventHandler) { super(file, exec, eventHandler); var message = "The root path is not a valid path for a file watch"; diff --git a/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java b/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java index cad19fdb..21245e5e 100644 --- a/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java +++ b/src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java @@ -47,14 +47,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import engineering.swat.watch.ActiveWatch; import engineering.swat.watch.WatchEvent; +import engineering.swat.watch.impl.EventHandlingWatch; public class JDKRecursiveDirectoryWatch extends JDKBaseWatch { private final Logger logger = LogManager.getLogger(); private final ConcurrentMap activeWatches = new ConcurrentHashMap<>(); - public JDKRecursiveDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler) { + public JDKRecursiveDirectoryWatch(Path directory, Executor exec, BiConsumer eventHandler) { super(directory, exec, eventHandler); } @@ -161,7 +161,7 @@ private void addNewDirectory(Path dir) throws IOException { } /** Make sure that the events are relative to the actual root of the recursive watch */ - private BiConsumer relocater(Path subRoot) { + private BiConsumer relocater(Path subRoot) { final Path newRelative = path.relativize(subRoot); return (w, ev) -> { var rewritten = new WatchEvent(ev.getKind(), path, newRelative.resolve(ev.getRelativePath()));