jdaugherty commented on code in PR #16089:
URL: https://github.com/apache/grails-core/pull/16089#discussion_r3714422372


##########
grails-bootstrap/src/main/groovy/org/grails/io/watch/DirectoryWatcher.java:
##########
@@ -45,32 +45,57 @@ public class DirectoryWatcher extends Thread {
      */
     public DirectoryWatcher() {
         setDaemon(true);
-        AbstractDirectoryWatcher directoryWatcherDelegate;
+        this.directoryWatcherDelegate = createDelegate();
+    }
+
+    /**
+     * Selects the best available watcher implementation.
+     *
+     * <p>On macOS the native FSEvents based watcher is preferred, but it 
requires the optional
+     * {@code io.methvin:directory-watcher} dependency. When that isn't 
available the JDK
+     * {@link java.nio.file.WatchService} is used instead. Polling is only a 
last resort.</p>
+     *
+     * @return the watcher to delegate to
+     */
+    private static AbstractDirectoryWatcher createDelegate() {
+        if (System.getProperty("os.name").equals("Mac OS X")) {
+            AbstractDirectoryWatcher macOsWatcher = createMacOsWatcher();
+            if (macOsWatcher != null) {
+                return macOsWatcher;
+            }
+        }
         try {
-            if (System.getProperty("os.name").equals("Mac OS X")) {
-                Boolean jnaAvailable = false;
-                try {
-                    Class.forName("com.sun.jna.Pointer");
-                    jnaAvailable = true;
-                } catch (ClassNotFoundException e) {
-                    if (LOG.isWarnEnabled()) {
-                        LOG.warn("Error Initializing Native OS X File Event 
Watcher. Add JNA to classpath for Faster File Watching performance.");
-                    }
-
-                }
-                if (jnaAvailable) {
-                    directoryWatcherDelegate = (AbstractDirectoryWatcher) 
Class.forName("org.grails.io.watch.MacOsWatchServiceDirectoryWatcher").getDeclaredConstructor().newInstance();
-                } else {
-                    directoryWatcherDelegate = (AbstractDirectoryWatcher) 
Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").getDeclaredConstructor().newInstance();
-                }
-            } else {
-                directoryWatcherDelegate = (AbstractDirectoryWatcher) 
Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").getDeclaredConstructor().newInstance();
+            return new WatchServiceDirectoryWatcher();
+        } catch (Throwable e) {
+            LOG.warn("Could not create a WatchService based directory watcher. 
Falling back to PollingDirectoryWatcher.", e);
+            return new PollingDirectoryWatcher();
+        }
+    }
+
+    /**
+     * @return the native macOS watcher, or {@code null} if it is unavailable
+     */
+    private static AbstractDirectoryWatcher createMacOsWatcher() {
+        try {
+            // MacOsWatchServiceDirectoryWatcher delegates to io.methvin's 
MacOSXListeningWatchService,
+            // an optional dependency of this module. Probe for that class 
rather than for JNA: JNA is
+            // frequently present transitively (Testcontainers, docker-java, 
...) without the watcher
+            // library, and using it as the signal sends those applications 
down a load that can't succeed.
+            // A LinkageError means the class is present but its own 
dependencies (JNA) are not, which is
+            // equally unusable, so treat both as simply unavailable.
+            
Class.forName("io.methvin.watchservice.MacOSXListeningWatchService");
+        } catch (ClassNotFoundException | LinkageError e) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Native macOS file event watching is unavailable. 
Add 'io.methvin:directory-watcher' to the classpath for faster file watching.", 
e);

Review Comment:
   Shouldn't this be warn?  Once you added the right library, doesn't this 
resolve itself? 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to