From 147482ccafa1497f2d6d5274ee6fbe2513c8a1a3 Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Fri, 12 Dec 2025 15:12:17 -0800 Subject: [PATCH] Fix file watcher test for Java 25 --- .../api/annotations/JavaRuntimeVersion.java | 2 -- .../api/files/FileSystemWatcherImpl.java | 35 +++++++++++-------- api/src/org/labkey/api/jsp/JspLoader.java | 4 +-- .../api/jsp/RecompilingJspClassLoader.java | 4 +-- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/api/src/org/labkey/api/annotations/JavaRuntimeVersion.java b/api/src/org/labkey/api/annotations/JavaRuntimeVersion.java index a2e7057cda8..2681523df25 100644 --- a/api/src/org/labkey/api/annotations/JavaRuntimeVersion.java +++ b/api/src/org/labkey/api/annotations/JavaRuntimeVersion.java @@ -19,8 +19,6 @@ Used to mark code that is specific to a particular Java runtime version, for example, hacks that work around problems in the runtime or links to the Java documentation. Re-evaluate these when Java versions are released or deprecated. Search for text "@JavaRuntimeVersion" to find all usages. - User: adam - Date: 9/11/13 */ import java.lang.annotation.Retention; diff --git a/api/src/org/labkey/api/files/FileSystemWatcherImpl.java b/api/src/org/labkey/api/files/FileSystemWatcherImpl.java index 5f8339d4352..3d1781b7ac1 100644 --- a/api/src/org/labkey/api/files/FileSystemWatcherImpl.java +++ b/api/src/org/labkey/api/files/FileSystemWatcherImpl.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.junit.Assert; import org.junit.Test; +import org.labkey.api.annotations.JavaRuntimeVersion; import org.labkey.api.cloud.CloudWatchService; import org.labkey.api.cloud.CloudWatcherConfig; import org.labkey.api.collections.ConcurrentHashSet; @@ -61,16 +62,20 @@ import static java.nio.file.StandardWatchEventKinds.OVERFLOW; /** - * Wraps the low-level Java WatchService API with a simple listener-based interface. Unlike WatchService, which is limited to one - * registration per file system directory, a single instance of this class should be sufficient to handle all file system listener - * needs of the entire server. - * - * Callers register a FileSystemDirectoryListener on a directory Path, specifying the desired WatchEvent.Kinds (CREATE, DELETE, - * and/or MODIFY); whenever an event occurs on any file or child directory in that directory, the appropriate method is invoked - * on all listeners registered on that directory that have requested notification of that event. - * - * This class is thread-safe, for both listener registration and event invocation. Implementations of FileSystemDirectoryListener - * must be thread-safe. Listener methods must return quickly since they are all invoked by a single thread. + *

Wraps the low-level Java WatchService API with a simple listener-based interface. Unlike WatchService, which is + * limited to one registration per file system directory, a single instance of this class should be sufficient to handle + * all file system listener needs of the entire server. + *

+ *

+ * Callers register a FileSystemDirectoryListener on a directory Path, specifying the desired WatchEvent.Kinds (CREATE, + * DELETE, and/or MODIFY); whenever an event occurs on any file or child directory in that directory, the appropriate + * method is invoked on all listeners registered on that directory that have requested notification of that event. + *

+ *

+ * This class is thread-safe, for both listener registration and event invocation. Implementations of + * FileSystemDirectoryListener must be thread-safe. Listener methods must return quickly since they are all invoked by a + * single thread. + *

*/ public class FileSystemWatcherImpl implements FileSystemWatcher { @@ -586,8 +591,10 @@ public void overflow() assertEquals(3, created.size()); assertTrue(created.containsAll(Set.of("a", "b", "c"))); - // Note: Modified events occur on delete on Windows, but not Linux - Set expectedModified = SystemUtils.IS_OS_WINDOWS ? Set.of("a", "b", "c") : Set.of("a", "c"); + // Note: In Java 17 on Windows, modified events occur on delete. This has never been the case on Linux and + // is no longer the case in Java 25. TODO: Delete this check once we require Java 25 + @JavaRuntimeVersion + Set expectedModified = SystemUtils.IS_OS_WINDOWS && SystemUtils.IS_JAVA_17 ? Set.of("a", "b", "c") : Set.of("a", "c"); assertEquals(expectedModified.size(), modified.size()); assertTrue(created.containsAll(expectedModified)); int deletedCount = deleted.size(); @@ -613,9 +620,9 @@ private void waitForEvents(AtomicInteger events, int targetCount) throws Interru i++; } - LOG.info("Waiting for file watcher events took " + StringUtilsLabKey.pluralize(i, "second")); + LOG.info("Waiting for file watcher events took {}", StringUtilsLabKey.pluralize(i, "second")); - LOG.info("Actual event count: " + events.get() + " vs. target: " + targetCount); + LOG.info("Actual event count: {} vs. target: {}", events.get(), targetCount); //assertEquals(expectedEventCount, events.get()); } } diff --git a/api/src/org/labkey/api/jsp/JspLoader.java b/api/src/org/labkey/api/jsp/JspLoader.java index c2a11522fc4..5f422a129b6 100644 --- a/api/src/org/labkey/api/jsp/JspLoader.java +++ b/api/src/org/labkey/api/jsp/JspLoader.java @@ -66,7 +66,7 @@ public void moduleStartupComplete(ServletContext servletContext) * Create a new JSP page. * * @param jspFile Full path to the JSP page, starting with "/" - * @return inited page + * @return initialized page */ public static HttpJspPage createPage(String jspFile) { @@ -84,7 +84,7 @@ public static HttpJspPage createPage(String jspFile) } } - public static Class loadClass(String jspFile) + public static Class loadClass(String jspFile) { try { diff --git a/api/src/org/labkey/api/jsp/RecompilingJspClassLoader.java b/api/src/org/labkey/api/jsp/RecompilingJspClassLoader.java index dfff873721a..65f6164def5 100644 --- a/api/src/org/labkey/api/jsp/RecompilingJspClassLoader.java +++ b/api/src/org/labkey/api/jsp/RecompilingJspClassLoader.java @@ -63,7 +63,7 @@ public class RecompilingJspClassLoader extends JspClassLoader private static final String DB_SCRIPT_PATH = "/schemas/dbscripts"; @Override - public Class loadClass(ServletContext context, String jspFilename) throws ClassNotFoundException + public Class loadClass(ServletContext context, String jspFilename) throws ClassNotFoundException { String compiledJspPath = getCompiledJspPath(jspFilename); Collection finders = ModuleLoader.getInstance().getResourceFindersForPath(compiledJspPath); @@ -86,7 +86,7 @@ public Class loadClass(ServletContext context, String jspFilename) throws ClassN @JavaRuntimeVersion // Change CompilerTargetVM and CompilerSourceVM settings below - private Class getCompiledClassFile(File classFile, File jspJavaFileBuildDirectory, File jspClassesFileBuildDir, ResourceFinder finder, String jspFileName) + private Class getCompiledClassFile(File classFile, File jspJavaFileBuildDirectory, File jspClassesFileBuildDir, ResourceFinder finder, String jspFileName) { String relativePath = getSourceJspPath(jspFileName); // Create File object for JSP source