diff --git a/build.gradle.kts b/build.gradle.kts index b777394..31fffea 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ group = "org.gradle.fileevents" dependencies { compileOnly("com.google.code.findbugs:jsr305:3.0.2") - api("net.rubygrapefruit:native-platform:0.22-milestone-26") + api("net.rubygrapefruit:native-platform:0.22-milestone-28") implementation("org.slf4j:slf4j-api:1.7.36") testImplementation(platform("org.junit:junit-bom:5.11.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/src/main/java/org/gradle/fileevents/FileEvents.java b/src/main/java/org/gradle/fileevents/FileEvents.java index c3da05f..1a54bba 100644 --- a/src/main/java/org/gradle/fileevents/FileEvents.java +++ b/src/main/java/org/gradle/fileevents/FileEvents.java @@ -22,8 +22,12 @@ */ @ThreadSafe public class FileEvents { - private static final Map, Object> integrations = new HashMap<>(); - private static boolean initialized; + private static FileEvents instance; + + private final Map, Object> integrations = new HashMap<>(); + + private FileEvents() { + } /** * Initializes the native file events integration. @@ -35,10 +39,10 @@ public class FileEvents { * @throws NativeException On failure to initialize the native integration. */ @ThreadSafe - static public void init(File extractDir) throws NativeException { + static public FileEvents init(File extractDir) throws NativeException { synchronized (FileEvents.class) { - if (initialized) { - return; + if (instance != null) { + throw new NativeException("File-system watching native library has already been initialized."); } Platform platform = Platform.current(); String platformName = getPlatformName(platform); @@ -49,7 +53,6 @@ static public void init(File extractDir) throws NativeException { throw new NativeIntegrationUnavailableException(String.format("Native file events integration is not available for %s.", platform)); } System.load(library.getCanonicalPath()); - initialized = true; String nativeVersion = AbstractNativeFileEventFunctions.getVersion(); if (!nativeVersion.equals(FileEventsVersion.VERSION)) { @@ -59,6 +62,9 @@ static public void init(File extractDir) throws NativeException { nativeVersion )); } + + instance = new FileEvents(); + return instance; } catch (NativeException e) { throw e; } catch (Throwable t) { @@ -132,12 +138,9 @@ private static boolean isLinuxWithMusl() { * @throws NativeException On failure to load the native integration. */ @ThreadSafe - public static T get(Class type) + public T get(Class type) throws NativeIntegrationUnavailableException, NativeException { - synchronized (FileEvents.class) { - if (!initialized) { - throw new NativeException(String.format("File-system watching native library has not been initialized.", type.getSimpleName())); - } + synchronized (this) { Platform platform = Platform.current(); Object instance = integrations.get(type); if (instance == null) { diff --git a/src/test/groovy/org/gradle/fileevents/internal/AbstractFileEventFunctionsTest.groovy b/src/test/groovy/org/gradle/fileevents/internal/AbstractFileEventFunctionsTest.groovy index a0338a3..e8e715e 100644 --- a/src/test/groovy/org/gradle/fileevents/internal/AbstractFileEventFunctionsTest.groovy +++ b/src/test/groovy/org/gradle/fileevents/internal/AbstractFileEventFunctionsTest.groovy @@ -33,6 +33,8 @@ import spock.lang.Specification import spock.lang.TempDir import spock.lang.Timeout +import java.nio.file.Files +import java.nio.file.Paths import java.util.concurrent.BlockingQueue import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit @@ -51,6 +53,18 @@ abstract class AbstractFileEventFunctionsTest extends Specification { LoggingCapture logging = new LoggingCapture(NativeLogger, Level.INFO) + private static FileEvents fileEventsIntegration + + protected static FileEvents getFileEvents() { + if (fileEventsIntegration == null) { + def testOutputDir = Paths.get("build/test-outputs") + Files.createDirectories(testOutputDir) + def tempDir = Files.createTempDirectory(testOutputDir, "file-events") + fileEventsIntegration = FileEvents.init(tempDir.toFile()) + } + return fileEventsIntegration + } + @TempDir File tmpDir String testName @@ -84,8 +98,6 @@ abstract class AbstractFileEventFunctionsTest extends Specification { assert rootDir.mkdirs() uncaughtFailureOnThread = [] expectedLogMessages = [:] - - FileEvents.init(null) } def cleanup() { @@ -152,7 +164,7 @@ abstract class AbstractFileEventFunctionsTest extends Specification { @Memoized @Override OsxFileEventFunctions getService() { - FileEvents.get(OsxFileEventFunctions) + AbstractFileEventFunctionsTest.getFileEvents().get(OsxFileEventFunctions) } @Override @@ -173,7 +185,7 @@ abstract class AbstractFileEventFunctionsTest extends Specification { @Memoized @Override LinuxFileEventFunctions getService() { - FileEvents.get(LinuxFileEventFunctions) + AbstractFileEventFunctionsTest.getFileEvents().get(LinuxFileEventFunctions) } @Override @@ -193,7 +205,7 @@ abstract class AbstractFileEventFunctionsTest extends Specification { @Memoized @Override WindowsFileEventFunctions getService() { - FileEvents.get(WindowsFileEventFunctions) + AbstractFileEventFunctionsTest.getFileEvents().get(WindowsFileEventFunctions) } @Override