diff --git a/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTracker.java b/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTracker.java index ccd5af86b8..7154b5c47a 100644 --- a/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTracker.java +++ b/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTracker.java @@ -78,8 +78,8 @@ public abstract class AbstractScriptDependencyTracker } @Override - public void processWatchEvent(WatchService.Kind kind, Path path) { - File file = libraryPath.resolve(path).toFile(); + public void processWatchEvent(WatchService.Kind kind, Path fullPath) { + File file = fullPath.toFile(); if (kind == DELETE || (!file.isHidden() && file.canRead() && (kind == CREATE || kind == MODIFY))) { dependencyChanged(file.toString()); } diff --git a/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptFileWatcher.java b/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptFileWatcher.java index 98eef26380..4619fcd226 100644 --- a/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptFileWatcher.java +++ b/bundles/org.openhab.core.automation.module.script.rulesupport/src/main/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptFileWatcher.java @@ -218,13 +218,12 @@ public abstract class AbstractScriptFileWatcher implements WatchService.WatchEve } @Override - public void processWatchEvent(WatchService.Kind kind, Path path) { + public void processWatchEvent(WatchService.Kind kind, Path fullPath) { if (!initialized.isDone()) { // discard events if the initial import has not finished return; } - Path fullPath = watchPath.resolve(path); File file = fullPath.toFile(); // Subdirectory events are filtered out by WatchService, so we only need to deal with files diff --git a/bundles/org.openhab.core.automation.module.script.rulesupport/src/test/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTrackerTest.java b/bundles/org.openhab.core.automation.module.script.rulesupport/src/test/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTrackerTest.java index 3e603eed71..b840f73c8e 100644 --- a/bundles/org.openhab.core.automation.module.script.rulesupport/src/test/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTrackerTest.java +++ b/bundles/org.openhab.core.automation.module.script.rulesupport/src/test/java/org/openhab/core/automation/module/script/rulesupport/loader/AbstractScriptDependencyTrackerTest.java @@ -92,7 +92,7 @@ public class AbstractScriptDependencyTrackerTest { scriptDependencyTracker.addChangeTracker(listener2); scriptDependencyTracker.startTracking("scriptId", depPath.toString()); - scriptDependencyTracker.processWatchEvent(WatchService.Kind.CREATE, DEPENDENCY); + scriptDependencyTracker.processWatchEvent(WatchService.Kind.CREATE, depPath); verify(listener1).onDependencyChange(eq("scriptId")); verify(listener2).onDependencyChange(eq("scriptId")); @@ -108,7 +108,7 @@ public class AbstractScriptDependencyTrackerTest { scriptDependencyTracker.startTracking("scriptId1", depPath.toString()); scriptDependencyTracker.startTracking("scriptId2", depPath.toString()); - scriptDependencyTracker.processWatchEvent(WatchService.Kind.MODIFY, DEPENDENCY); + scriptDependencyTracker.processWatchEvent(WatchService.Kind.MODIFY, depPath); verify(listener).onDependencyChange(eq("scriptId1")); verify(listener).onDependencyChange(eq("scriptId2")); @@ -123,8 +123,8 @@ public class AbstractScriptDependencyTrackerTest { scriptDependencyTracker.startTracking("scriptId", depPath.toString()); scriptDependencyTracker.startTracking("scriptId", depPath2.toString()); - scriptDependencyTracker.processWatchEvent(WatchService.Kind.MODIFY, DEPENDENCY); - scriptDependencyTracker.processWatchEvent(WatchService.Kind.DELETE, DEPENDENCY2); + scriptDependencyTracker.processWatchEvent(WatchService.Kind.MODIFY, depPath); + scriptDependencyTracker.processWatchEvent(WatchService.Kind.DELETE, depPath2); verify(listener, times(2)).onDependencyChange(eq("scriptId")); verifyNoMoreInteractions(listener); @@ -139,7 +139,7 @@ public class AbstractScriptDependencyTrackerTest { scriptDependencyTracker.startTracking("scriptId1", depPath.toString()); scriptDependencyTracker.startTracking("scriptId2", depPath2.toString()); - scriptDependencyTracker.processWatchEvent(WatchService.Kind.CREATE, DEPENDENCY); + scriptDependencyTracker.processWatchEvent(WatchService.Kind.CREATE, depPath); verify(listener).onDependencyChange(eq("scriptId1")); verifyNoMoreInteractions(listener); diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/provider/file/AutomationWatchService.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/provider/file/AutomationWatchService.java index 3843bbdd4a..50b825628e 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/provider/file/AutomationWatchService.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/provider/file/AutomationWatchService.java @@ -58,8 +58,7 @@ public class AutomationWatchService implements WatchService.WatchEventListener { } @Override - public void processWatchEvent(WatchService.Kind kind, Path path) { - Path fullPath = watchingDir.resolve(path); + public void processWatchEvent(WatchService.Kind kind, Path fullPath) { try { if (kind == WatchService.Kind.DELETE) { provider.removeResources(fullPath.toFile()); diff --git a/bundles/org.openhab.core.config.dispatch/src/main/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcher.java b/bundles/org.openhab.core.config.dispatch/src/main/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcher.java index 35bdcbeb2b..6abe709329 100644 --- a/bundles/org.openhab.core.config.dispatch/src/main/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcher.java +++ b/bundles/org.openhab.core.config.dispatch/src/main/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcher.java @@ -63,8 +63,7 @@ public class ConfigDispatcherFileWatcher implements WatchService.WatchEventListe } @Override - public void processWatchEvent(WatchService.Kind kind, Path path) { - Path fullPath = watchService.getWatchPath().resolve(SERVICES_FOLDER).resolve(path); + public void processWatchEvent(WatchService.Kind kind, Path fullPath) { try { if (kind == WatchService.Kind.CREATE || kind == WatchService.Kind.MODIFY) { if (!Files.isHidden(fullPath) && fullPath.toString().endsWith(".cfg")) { @@ -79,7 +78,7 @@ public class ConfigDispatcherFileWatcher implements WatchService.WatchEventListe configDispatcher.fileRemoved(fullPath.toString()); } } catch (IOException e) { - logger.error("Failed to process watch event {} for {}", kind, path, e); + logger.error("Failed to process watch event {} for {}", kind, fullPath, e); } } } diff --git a/bundles/org.openhab.core.config.dispatch/src/test/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcherTest.java b/bundles/org.openhab.core.config.dispatch/src/test/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcherTest.java index 9f153c2372..b22543279e 100644 --- a/bundles/org.openhab.core.config.dispatch/src/test/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcherTest.java +++ b/bundles/org.openhab.core.config.dispatch/src/test/java/org/openhab/core/config/dispatch/internal/ConfigDispatcherFileWatcherTest.java @@ -49,8 +49,6 @@ public class ConfigDispatcherFileWatcherTest { configDispatcherFileWatcher = new ConfigDispatcherFileWatcher(configDispatcherMock, watchService); verify(configDispatcherMock).processConfigFile(any()); - when(watchService.getWatchPath()).thenReturn(tempDir.toAbsolutePath()); - cfgPath = tempDir.resolve("myPath.cfg"); nonCfgPath = tempDir.resolve("myPath"); diff --git a/bundles/org.openhab.core.model.core/src/main/java/org/openhab/core/model/core/internal/folder/FolderObserver.java b/bundles/org.openhab.core.model.core/src/main/java/org/openhab/core/model/core/internal/folder/FolderObserver.java index 092ac57a50..c27b4cfb53 100644 --- a/bundles/org.openhab.core.model.core/src/main/java/org/openhab/core/model/core/internal/folder/FolderObserver.java +++ b/bundles/org.openhab.core.model.core/src/main/java/org/openhab/core/model/core/internal/folder/FolderObserver.java @@ -59,6 +59,7 @@ import org.slf4j.LoggerFactory; @Component(name = "org.openhab.core.folder", immediate = true, configurationPid = "org.openhab.folder", configurationPolicy = ConfigurationPolicy.REQUIRE) public class FolderObserver implements WatchService.WatchEventListener { private final WatchService watchService; + private final Path watchPath; private final Logger logger = LoggerFactory.getLogger(FolderObserver.class); /* the model repository is provided as a service */ @@ -88,6 +89,7 @@ public class FolderObserver implements WatchService.WatchEventListener { this.modelRepository = modelRepo; this.readyService = readyService; this.watchService = watchService; + this.watchPath = watchService.getWatchPath(); } @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, policy = ReferencePolicy.DYNAMIC) @@ -127,7 +129,7 @@ public class FolderObserver implements WatchService.WatchEventListener { continue; } - Path folderPath = watchService.getWatchPath().resolve(folderName); + Path folderPath = watchPath.resolve(folderName); if (Files.exists(folderPath) && Files.isDirectory(folderPath)) { String[] validExtensions = ((String) config.get(folderName)).split(","); folderFileExtMap.put(folderName, Set.of(validExtensions)); @@ -191,7 +193,7 @@ public class FolderObserver implements WatchService.WatchEventListener { continue; } - Path folderPath = watchService.getWatchPath().resolve(folderName); + Path folderPath = watchPath.resolve(folderName); logger.debug("Adding files in '{}' to the model", folderPath); try (DirectoryStream stream = Files.newDirectoryStream(folderPath, new FileExtensionsFilter(validExtensions))) { @@ -287,7 +289,8 @@ public class FolderObserver implements WatchService.WatchEventListener { } @Override - public void processWatchEvent(WatchService.Kind kind, Path path) { + public void processWatchEvent(WatchService.Kind kind, Path fullPath) { + Path path = watchPath.relativize(fullPath); if (path.getNameCount() != 2) { logger.trace("{} event for {} ignored (only depth 1 allowed)", kind, path); return; @@ -310,7 +313,6 @@ public class FolderObserver implements WatchService.WatchEventListener { return; } - Path resolvedPath = watchService.getWatchPath().resolve(path); - checkPath(resolvedPath, kind); + checkPath(fullPath, kind); } } diff --git a/bundles/org.openhab.core.model.core/src/test/java/org/openhab/core/model/core/internal/folder/FolderObserverTest.java b/bundles/org.openhab.core.model.core/src/test/java/org/openhab/core/model/core/internal/folder/FolderObserverTest.java index d40dfbd581..44e7b277f4 100644 --- a/bundles/org.openhab.core.model.core/src/test/java/org/openhab/core/model/core/internal/folder/FolderObserverTest.java +++ b/bundles/org.openhab.core.model.core/src/test/java/org/openhab/core/model/core/internal/folder/FolderObserverTest.java @@ -90,7 +90,7 @@ public class FolderObserverTest extends JavaTest { when(modelParserMock.getExtension()).thenReturn("java"); when(contextMock.getProperties()).thenReturn(configProps); - when(watchServiceMock.getWatchPath()).thenReturn(WATCHED_DIRECTORY.toPath()); + when(watchServiceMock.getWatchPath()).thenReturn(WATCHED_DIRECTORY.toPath().toAbsolutePath()); folderObserver = new FolderObserver(modelRepoMock, readyServiceMock, watchServiceMock); folderObserver.addModelParser(modelParserMock); @@ -129,7 +129,7 @@ public class FolderObserverTest extends JavaTest { Files.writeString(file.toPath(), INITIAL_FILE_CONTENT, StandardCharsets.UTF_8, StandardOpenOption.CREATE); waitForAssert(() -> assertThat(file.exists(), is(true))); - folderObserver.processWatchEvent(CREATE, WATCHED_DIRECTORY.toPath().relativize(file.toPath())); + folderObserver.processWatchEvent(CREATE, file.toPath().toAbsolutePath()); verify(modelRepoMock).addOrRefreshModel(eq(file.getName()), any()); verifyNoMoreInteractions(modelRepoMock); @@ -154,12 +154,12 @@ public class FolderObserverTest extends JavaTest { Files.writeString(file.toPath(), INITIAL_FILE_CONTENT, StandardCharsets.UTF_8, StandardOpenOption.CREATE); waitForAssert(() -> assertThat(file.exists(), is(true))); - folderObserver.processWatchEvent(CREATE, WATCHED_DIRECTORY.toPath().relativize(file.toPath())); + folderObserver.processWatchEvent(CREATE, file.toPath().toAbsolutePath()); String text = "Additional content"; Files.writeString(file.toPath(), text, StandardCharsets.UTF_8, StandardOpenOption.APPEND); - folderObserver.processWatchEvent(MODIFY, WATCHED_DIRECTORY.toPath().relativize(file.toPath())); + folderObserver.processWatchEvent(MODIFY, file.toPath().toAbsolutePath()); verify(modelRepoMock, times(2)).addOrRefreshModel(eq(file.getName()), any()); verifyNoMoreInteractions(modelRepoMock); @@ -183,7 +183,7 @@ public class FolderObserverTest extends JavaTest { Files.writeString(file.toPath(), INITIAL_FILE_CONTENT, StandardCharsets.UTF_8, StandardOpenOption.CREATE); waitForAssert(() -> assertThat(file.exists(), is(true))); - folderObserver.processWatchEvent(CREATE, WATCHED_DIRECTORY.toPath().relativize(file.toPath())); + folderObserver.processWatchEvent(CREATE, file.toPath().toAbsolutePath()); verifyNoInteractions(modelRepoMock); } @@ -203,7 +203,7 @@ public class FolderObserverTest extends JavaTest { File file = new File(EXISTING_SUBDIR_PATH, "NewlyCreatedMockFile.java"); Files.writeString(file.toPath(), INITIAL_FILE_CONTENT, StandardCharsets.UTF_8, StandardOpenOption.CREATE); waitForAssert(() -> assertThat(file.exists(), is(true))); - folderObserver.processWatchEvent(CREATE, WATCHED_DIRECTORY.toPath().relativize(file.toPath())); + folderObserver.processWatchEvent(CREATE, file.toPath().toAbsolutePath()); verifyNoInteractions(modelRepoMock); } @@ -256,7 +256,7 @@ public class FolderObserverTest extends JavaTest { Files.writeString(file.toPath(), INITIAL_FILE_CONTENT, StandardCharsets.UTF_8, StandardOpenOption.CREATE); waitForAssert(() -> assertThat(file.exists(), is(true))); - folderObserver.processWatchEvent(CREATE, WATCHED_DIRECTORY.toPath().relativize(file.toPath())); + folderObserver.processWatchEvent(CREATE, file.toPath().toAbsolutePath()); verifyNoInteractions(modelRepoMock); } @@ -275,13 +275,11 @@ public class FolderObserverTest extends JavaTest { File mockFileWithValidExt = new File(EXISTING_SUBDIR_PATH, "MockFileForModification." + validExtension); Files.writeString(mockFileWithValidExt.toPath(), INITIAL_FILE_CONTENT, StandardCharsets.UTF_8, StandardOpenOption.CREATE); - localFolderObserver.processWatchEvent(CREATE, - WATCHED_DIRECTORY.toPath().relativize(mockFileWithValidExt.toPath())); + localFolderObserver.processWatchEvent(CREATE, mockFileWithValidExt.toPath().toAbsolutePath()); Files.writeString(mockFileWithValidExt.toPath(), "Additional content", StandardCharsets.UTF_8, StandardOpenOption.APPEND); - localFolderObserver.processWatchEvent(MODIFY, - WATCHED_DIRECTORY.toPath().relativize(mockFileWithValidExt.toPath())); + localFolderObserver.processWatchEvent(MODIFY, mockFileWithValidExt.toPath().toAbsolutePath()); verify(modelRepoMock, times(2)).addOrRefreshModel(eq(mockFileWithValidExt.getName()), any()); } @@ -325,7 +323,7 @@ public class FolderObserverTest extends JavaTest { walk.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); } } - folderObserver.processWatchEvent(CREATE, Path.of(EXISTING_SUBDIR_PATH.getName(), filename)); + folderObserver.processWatchEvent(CREATE, Path.of(EXISTING_SUBDIR_PATH.getName(), filename).toAbsolutePath()); verifyNoInteractions(modelRepoMock); } } diff --git a/bundles/org.openhab.core.model.yaml/src/main/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImpl.java b/bundles/org.openhab.core.model.yaml/src/main/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImpl.java index 9407c154c3..39b9114c68 100644 --- a/bundles/org.openhab.core.model.yaml/src/main/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImpl.java +++ b/bundles/org.openhab.core.model.yaml/src/main/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImpl.java @@ -130,8 +130,7 @@ public class YamlModelRepositoryImpl implements WatchService.WatchEventListener, public FileVisitResult visitFile(@NonNullByDefault({}) Path file, @NonNullByDefault({}) BasicFileAttributes attrs) throws IOException { if (attrs.isRegularFile()) { - Path relativePath = watchPath.relativize(file); - processWatchEvent(CREATE, relativePath); + processWatchEvent(CREATE, file); } return FileVisitResult.CONTINUE; } @@ -156,10 +155,10 @@ public class YamlModelRepositoryImpl implements WatchService.WatchEventListener, // The method is "synchronized" to avoid concurrent files processing @Override @SuppressWarnings({ "rawtypes", "unchecked" }) - public synchronized void processWatchEvent(Kind kind, Path path) { - Path fullPath = watchPath.resolve(path); - String modelName = path.toString(); - if (path.startsWith("automation") || !modelName.endsWith(".yaml")) { + public synchronized void processWatchEvent(Kind kind, Path fullPath) { + Path relativePath = watchPath.relativize(fullPath); + String modelName = relativePath.toString(); + if (relativePath.startsWith("automation") || !modelName.endsWith(".yaml")) { logger.trace("Ignored {}", fullPath); return; } diff --git a/bundles/org.openhab.core.model.yaml/src/test/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImplTest.java b/bundles/org.openhab.core.model.yaml/src/test/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImplTest.java index 5efec189b0..5dfd0ebd58 100644 --- a/bundles/org.openhab.core.model.yaml/src/test/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImplTest.java +++ b/bundles/org.openhab.core.model.yaml/src/test/java/org/openhab/core/model/yaml/internal/YamlModelRepositoryImplTest.java @@ -103,8 +103,8 @@ public class YamlModelRepositoryImplTest { modelRepository.addYamlModelListener(secondTypeListener1); modelRepository.addYamlModelListener(secondTypeListener2); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); verify(firstTypeListener).addedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); verify(firstTypeListener).addedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); @@ -158,8 +158,8 @@ public class YamlModelRepositoryImplTest { YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); modelRepository.addYamlModelListener(firstTypeListener); modelRepository.addYamlModelListener(secondTypeListener1); @@ -217,23 +217,23 @@ public class YamlModelRepositoryImplTest { // File in v1 format Files.copy(SOURCE_PATH.resolve("modelFileUpdatePost.yaml"), fullModelPath); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); verify(firstTypeListener).addedModel(eq(MODEL_NAME), any()); Files.copy(SOURCE_PATH.resolve("modelFileUpdatePre.yaml"), fullModelPath, StandardCopyOption.REPLACE_EXISTING); - modelRepository.processWatchEvent(WatchService.Kind.MODIFY, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.MODIFY, fullModelPath); verify(firstTypeListener, times(2)).addedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); verify(firstTypeListener).updatedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); verify(firstTypeListener).removedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); // File in v2 format Files.copy(SOURCE_PATH.resolve("modelV2FileUpdatePost.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); verify(firstTypeListener).addedModel(eq(MODEL2_NAME), any()); Files.copy(SOURCE_PATH.resolve("modelV2FileUpdatePre.yaml"), fullModel2Path, StandardCopyOption.REPLACE_EXISTING); - modelRepository.processWatchEvent(WatchService.Kind.MODIFY, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.MODIFY, fullModel2Path); verify(firstTypeListener, times(2)).addedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); verify(firstTypeListener).updatedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); verify(firstTypeListener).removedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); @@ -282,11 +282,11 @@ public class YamlModelRepositoryImplTest { // File in v1 format Files.copy(SOURCE_PATH.resolve("modelFileUpdatePost.yaml"), fullModelPath); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); verify(firstTypeListener).addedModel(eq(MODEL_NAME), any()); Files.copy(SOURCE_PATH.resolve(v1File), fullModelPath, StandardCopyOption.REPLACE_EXISTING); - modelRepository.processWatchEvent(WatchService.Kind.MODIFY, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.MODIFY, fullModelPath); verify(firstTypeListener).removedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); Collection firstTypeElements = firstTypeCaptor.getAllValues().getFirst(); @@ -298,11 +298,11 @@ public class YamlModelRepositoryImplTest { // File in v2 format Files.copy(SOURCE_PATH.resolve("modelV2FileUpdatePost.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); verify(firstTypeListener).addedModel(eq(MODEL2_NAME), any()); Files.copy(SOURCE_PATH.resolve(v2File), fullModel2Path, StandardCopyOption.REPLACE_EXISTING); - modelRepository.processWatchEvent(WatchService.Kind.MODIFY, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.MODIFY, fullModel2Path); verify(firstTypeListener).removedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); assertThat(firstTypeCaptor.getAllValues(), hasSize(2)); @@ -322,8 +322,8 @@ public class YamlModelRepositoryImplTest { // File in v1 format Files.copy(SOURCE_PATH.resolve("modelFileUpdatePost.yaml"), fullModelPath); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); - modelRepository.processWatchEvent(WatchService.Kind.DELETE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); + modelRepository.processWatchEvent(WatchService.Kind.DELETE, fullModelPath); verify(firstTypeListener).addedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); verify(firstTypeListener, never()).updatedModel(any(), any()); @@ -331,8 +331,8 @@ public class YamlModelRepositoryImplTest { // File in v2 format Files.copy(SOURCE_PATH.resolve("modelV2FileUpdatePost.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); - modelRepository.processWatchEvent(WatchService.Kind.DELETE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); + modelRepository.processWatchEvent(WatchService.Kind.DELETE, fullModel2Path); verify(firstTypeListener).addedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); verify(firstTypeListener, never()).updatedModel(any(), any()); @@ -367,7 +367,7 @@ public class YamlModelRepositoryImplTest { YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); modelRepository.addYamlModelListener(firstTypeListener); modelRepository.addYamlModelListener(secondTypeListener1); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); FirstTypeDTO added = new FirstTypeDTO("element3", "description3"); modelRepository.addElementToModel(MODEL_NAME, added); @@ -388,7 +388,7 @@ public class YamlModelRepositoryImplTest { assertThat(yaml.load(actualFileContent), equalTo(yaml.load(expectedFileContent))); Files.copy(SOURCE_PATH.resolve("modifyModelV2InitialContent.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); modelRepository.addElementToModel(MODEL2_NAME, added); modelRepository.addElementToModel(MODEL2_NAME, added2); verify(firstTypeListener, times(2)).addedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); @@ -424,7 +424,7 @@ public class YamlModelRepositoryImplTest { YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); modelRepository.addYamlModelListener(firstTypeListener); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); FirstTypeDTO updated = new FirstTypeDTO("element1", "newDescription1"); modelRepository.updateElementInModel(MODEL_NAME, updated); @@ -440,7 +440,7 @@ public class YamlModelRepositoryImplTest { assertThat(yaml.load(actualFileContent), equalTo(yaml.load(expectedFileContent))); Files.copy(SOURCE_PATH.resolve("modifyModelV2InitialContent.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); modelRepository.updateElementInModel(MODEL2_NAME, updated); verify(firstTypeListener).addedModel(eq(MODEL2_NAME), any()); verify(firstTypeListener).updatedModel(eq(MODEL2_NAME), firstTypeCaptor.capture()); @@ -464,7 +464,7 @@ public class YamlModelRepositoryImplTest { Files.copy(SOURCE_PATH.resolve("modifyModelInitialContent.yaml"), fullModelPath); YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); FirstTypeDTO removed = new FirstTypeDTO("element1", "description1"); modelRepository.addYamlModelListener(firstTypeListener); @@ -481,7 +481,7 @@ public class YamlModelRepositoryImplTest { assertThat(yaml.load(actualFileContent), equalTo(yaml.load(expectedFileContent))); Files.copy(SOURCE_PATH.resolve("modifyModelV2InitialContent.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); modelRepository.removeElementFromModel(MODEL2_NAME, removed); verify(firstTypeListener).addedModel(eq(MODEL2_NAME), any()); verify(firstTypeListener, never()).updatedModel(any(), any()); @@ -505,7 +505,7 @@ public class YamlModelRepositoryImplTest { Files.copy(SOURCE_PATH.resolve("modelFileAddedOrRemoved.yaml"), fullModelPath); YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); FirstTypeDTO added = new FirstTypeDTO("element3", "description3"); modelRepository.addElementToModel(MODEL_NAME, added); @@ -523,7 +523,7 @@ public class YamlModelRepositoryImplTest { assertThat(yaml.load(actualFileContent), equalTo(yaml.load(expectedFileContent))); Files.copy(SOURCE_PATH.resolve("modelV2FileAddedOrRemoved.yaml"), fullModel2Path); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); modelRepository.addElementToModel(MODEL2_NAME, added); modelRepository.removeElementFromModel(MODEL2_NAME, removed); modelRepository.updateElementInModel(MODEL2_NAME, updated); @@ -546,7 +546,7 @@ public class YamlModelRepositoryImplTest { YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); modelRepository.addYamlModelListener(firstTypeListener); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); verify(firstTypeListener).addedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); verify(firstTypeListener, never()).updatedModel(any(), any()); @@ -570,7 +570,7 @@ public class YamlModelRepositoryImplTest { YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); modelRepository.addYamlModelListener(firstTypeListener); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); verify(firstTypeListener).addedModel(eq(MODEL_NAME), firstTypeCaptor.capture()); verify(firstTypeListener, never()).updatedModel(any(), any()); @@ -594,7 +594,7 @@ public class YamlModelRepositoryImplTest { YamlModelRepositoryImpl modelRepository = new YamlModelRepositoryImpl(watchServiceMock); modelRepository.addYamlModelListener(firstTypeListener); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); verify(firstTypeListener, never()).addedModel(any(), any()); verify(firstTypeListener, never()).updatedModel(any(), any()); @@ -619,8 +619,8 @@ public class YamlModelRepositoryImplTest { modelRepository.addYamlModelListener(secondTypeListener1); modelRepository.addYamlModelListener(secondTypeListener2); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL_PATH); - modelRepository.processWatchEvent(WatchService.Kind.CREATE, MODEL2_PATH); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModelPath); + modelRepository.processWatchEvent(WatchService.Kind.CREATE, fullModel2Path); verify(secondTypeListener1).addedModel(eq(MODEL_NAME), secondTypeCaptor1.capture()); verify(secondTypeListener1, never()).addedModel(eq(MODEL2_NAME), any()); diff --git a/bundles/org.openhab.core.transform/src/main/java/org/openhab/core/transform/FileTransformationProvider.java b/bundles/org.openhab.core.transform/src/main/java/org/openhab/core/transform/FileTransformationProvider.java index 71a651acff..728dc00ad4 100644 --- a/bundles/org.openhab.core.transform/src/main/java/org/openhab/core/transform/FileTransformationProvider.java +++ b/bundles/org.openhab.core.transform/src/main/java/org/openhab/core/transform/FileTransformationProvider.java @@ -67,8 +67,7 @@ public class FileTransformationProvider implements WatchService.WatchEventListen watchService.registerListener(this, transformationPath); // read initial contents try (Stream files = Files.walk(transformationPath)) { - files.filter(Files::isRegularFile).map(transformationPath::relativize) - .forEach(f -> processWatchEvent(CREATE, f)); + files.filter(Files::isRegularFile).forEach(f -> processWatchEvent(CREATE, f)); } catch (IOException e) { logger.warn("Could not list files in '{}', transformation configurations might be missing: {}", transformationPath, e.getMessage()); @@ -96,8 +95,8 @@ public class FileTransformationProvider implements WatchService.WatchEventListen } @Override - public void processWatchEvent(WatchService.Kind kind, Path path) { - Path finalPath = transformationPath.resolve(path); + public void processWatchEvent(WatchService.Kind kind, Path fullPath) { + Path path = transformationPath.relativize(fullPath); try { if (kind == DELETE) { Transformation oldElement = transformationConfigurations.remove(path); @@ -105,7 +104,7 @@ public class FileTransformationProvider implements WatchService.WatchEventListen logger.trace("Removed configuration from file '{}", path); listeners.forEach(listener -> listener.removed(this, oldElement)); } - } else if (Files.isRegularFile(finalPath) && !Files.isHidden(finalPath) + } else if (Files.isRegularFile(fullPath) && !Files.isHidden(fullPath) && ((kind == CREATE) || (kind == MODIFY))) { String fileName = path.getFileName().toString(); Matcher m = FILENAME_PATTERN.matcher(fileName); @@ -122,7 +121,7 @@ public class FileTransformationProvider implements WatchService.WatchEventListen return; } - String content = new String(Files.readAllBytes(finalPath)); + String content = new String(Files.readAllBytes(fullPath)); String uid = path.toString(); Transformation newElement = new Transformation(uid, uid, fileExtension, Map.of(FUNCTION, content)); diff --git a/bundles/org.openhab.core.transform/src/test/java/org/openhab/core/transform/FileTransformationProviderTest.java b/bundles/org.openhab.core.transform/src/test/java/org/openhab/core/transform/FileTransformationProviderTest.java index 2de29170ee..de0aa20ad1 100644 --- a/bundles/org.openhab.core.transform/src/test/java/org/openhab/core/transform/FileTransformationProviderTest.java +++ b/bundles/org.openhab.core.transform/src/test/java/org/openhab/core/transform/FileTransformationProviderTest.java @@ -89,10 +89,11 @@ public class FileTransformationProviderTest { @Test public void testAddingConfigurationIsPropagated() throws IOException { - Files.writeString(transformationPath.resolve(ADDED_FILENAME), ADDED_CONTENT); + Path path = transformationPath.resolve(ADDED_FILENAME); + Files.writeString(path, ADDED_CONTENT); Transformation addedConfiguration = new Transformation(ADDED_FILENAME.toString(), ADDED_FILENAME.toString(), FOO_TYPE, Map.of(FUNCTION, ADDED_CONTENT)); - provider.processWatchEvent(CREATE, ADDED_FILENAME); + provider.processWatchEvent(CREATE, path); // assert registry is notified and internal cache updated Mockito.verify(listenerMock).added(provider, addedConfiguration); @@ -101,10 +102,11 @@ public class FileTransformationProviderTest { @Test public void testUpdatingConfigurationIsPropagated() throws IOException { - Files.writeString(transformationPath.resolve(INITIAL_FILENAME), "updated"); + Path path = transformationPath.resolve(INITIAL_FILENAME); + Files.writeString(path, "updated"); Transformation updatedConfiguration = new Transformation(INITIAL_FILENAME.toString(), INITIAL_FILENAME.toString(), FOO_TYPE, Map.of(FUNCTION, "updated")); - provider.processWatchEvent(MODIFY, INITIAL_FILENAME); + provider.processWatchEvent(MODIFY, path); Mockito.verify(listenerMock).updated(provider, INITIAL_CONFIGURATION, updatedConfiguration); assertThat(provider.getAll(), contains(updatedConfiguration)); @@ -113,7 +115,7 @@ public class FileTransformationProviderTest { @Test public void testDeletingConfigurationIsPropagated() { - provider.processWatchEvent(DELETE, INITIAL_FILENAME); + provider.processWatchEvent(DELETE, transformationPath.resolve(INITIAL_FILENAME)); Mockito.verify(listenerMock).removed(provider, INITIAL_CONFIGURATION); assertThat(provider.getAll(), not(contains(INITIAL_CONFIGURATION))); @@ -128,15 +130,14 @@ public class FileTransformationProviderTest { Transformation expected = new Transformation(fileName, fileName, FOO_TYPE, Map.of(FUNCTION, INITIAL_CONTENT)); - provider.processWatchEvent(CREATE, Path.of(fileName)); + provider.processWatchEvent(CREATE, path); assertThat(provider.getAll(), hasItem(expected)); } @Test public void testMissingExtensionIsIgnored() throws IOException { - Path extensionMissing = Path.of("extensionMissing"); - Path path = transformationPath.resolve(extensionMissing); - Files.writeString(path, INITIAL_CONTENT); + Path extensionMissing = transformationPath.resolve("extensionMissing"); + Files.writeString(extensionMissing, INITIAL_CONTENT); provider.processWatchEvent(CREATE, extensionMissing); provider.processWatchEvent(MODIFY, extensionMissing); @@ -146,9 +147,8 @@ public class FileTransformationProviderTest { @Test public void testIgnoredExtensionIsIgnored() throws IOException { - Path extensionIgnored = Path.of("extensionIgnore.txt"); - Path path = transformationPath.resolve(extensionIgnored); - Files.writeString(path, INITIAL_CONTENT); + Path extensionIgnored = transformationPath.resolve("extensionIgnore.txt"); + Files.writeString(extensionIgnored, INITIAL_CONTENT); provider.processWatchEvent(CREATE, extensionIgnored); provider.processWatchEvent(MODIFY, extensionIgnored); diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/service/WatchServiceImpl.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/service/WatchServiceImpl.java index 6ee6061d33..0161542eba 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/service/WatchServiceImpl.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/service/WatchServiceImpl.java @@ -289,8 +289,8 @@ public class WatchServiceImpl implements WatchService, DirectoryChangeListener { private record Listener(Path rootPath, WatchEventListener watchEventListener) { - void notify(Path path, Kind kind) { - watchEventListener.processWatchEvent(kind, rootPath.relativize(path)); + void notify(Path fullPath, Kind kind) { + watchEventListener.processWatchEvent(kind, fullPath); } static Predicate isListener(WatchEventListener watchEventListener) { diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/service/WatchService.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/service/WatchService.java index 42e39f7cec..07ee5283b7 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/service/WatchService.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/service/WatchService.java @@ -119,9 +119,9 @@ public interface WatchService { * Notify Listener about watch event * * @param kind the {@link Kind} of this event - * @param path the relative path of the file associated with this event + * @param fullPath the absolute path of the file associated with this event */ - void processWatchEvent(Kind kind, Path path); + void processWatchEvent(Kind kind, Path fullPath); } enum Kind { diff --git a/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/service/WatchServiceImplTest.java b/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/service/WatchServiceImplTest.java index b08595c111..b32335ecf6 100644 --- a/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/service/WatchServiceImplTest.java +++ b/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/service/WatchServiceImplTest.java @@ -48,6 +48,7 @@ import org.osgi.framework.BundleContext; @MockitoSettings(strictness = Strictness.LENIENT) public class WatchServiceImplTest extends JavaTest { private static final String SUB_DIR_PATH_NAME = "subDir"; + private static final String SUB_DIR2_PATH_NAME = "subDir2"; private static final String TEST_FILE_NAME = "testFile"; public @Mock @NonNullByDefault({}) WatchServiceImpl.WatchServiceConfiguration configurationMock; @@ -78,19 +79,18 @@ public class WatchServiceImplTest extends JavaTest { watchService.registerListener(listener, rootPath, false); Path testFile = rootPath.resolve(TEST_FILE_NAME); - Path relativeTestFilePath = Path.of(TEST_FILE_NAME); Files.writeString(testFile, "initial content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.CREATE); + assertEvent(testFile, Kind.CREATE); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.MODIFY); + assertEvent(testFile, Kind.MODIFY); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); assertNoEvent(); Files.delete(testFile); - assertEvent(relativeTestFilePath, Kind.DELETE); + assertEvent(testFile, Kind.DELETE); } @Test @@ -101,19 +101,18 @@ public class WatchServiceImplTest extends JavaTest { watchService.registerListener(listener, rootPath, true); Path testFile = rootPath.resolve(SUB_DIR_PATH_NAME).resolve(TEST_FILE_NAME); - Path relativeTestFilePath = Path.of(SUB_DIR_PATH_NAME, TEST_FILE_NAME); Files.writeString(testFile, "initial content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.CREATE); + assertEvent(testFile, Kind.CREATE); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.MODIFY); + assertEvent(testFile, Kind.MODIFY); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); assertNoEvent(); Files.delete(testFile); - assertEvent(relativeTestFilePath, Kind.DELETE); + assertEvent(testFile, Kind.DELETE); } @Test @@ -122,21 +121,21 @@ public class WatchServiceImplTest extends JavaTest { // listener is only listening to sub-dir of root watchService.registerListener(listener, Path.of(SUB_DIR_PATH_NAME), false); + watchService.registerListener(listener, Path.of(SUB_DIR2_PATH_NAME), false); Path testFile = rootPath.resolve(SUB_DIR_PATH_NAME).resolve(TEST_FILE_NAME); - Path relativeTestFilePath = Path.of(TEST_FILE_NAME); Files.writeString(testFile, "initial content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.CREATE); + assertEvent(testFile, Kind.CREATE); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.MODIFY); + assertEvent(testFile, Kind.MODIFY); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); assertNoEvent(); Files.delete(testFile); - assertEvent(relativeTestFilePath, Kind.DELETE); + assertEvent(testFile, Kind.DELETE); } @Test @@ -168,36 +167,70 @@ public class WatchServiceImplTest extends JavaTest { assertNoEvent(); Path testFile = subDirSubDir.resolve(TEST_FILE_NAME); - Path relativeTestFilePath = rootPath.relativize(testFile); Files.writeString(testFile, "initial content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.CREATE); + assertEvent(testFile, Kind.CREATE); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); - assertEvent(relativeTestFilePath, Kind.MODIFY); + assertEvent(testFile, Kind.MODIFY); Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); assertNoEvent(); Files.delete(testFile); - assertEvent(relativeTestFilePath, Kind.DELETE); + assertEvent(testFile, Kind.DELETE); Files.delete(subDirSubDir); assertNoEvent(); } + @Test + public void testWatchMultiplePaths() throws IOException, InterruptedException { + Files.createDirectories(rootPath.resolve(SUB_DIR_PATH_NAME)); + Files.createDirectories(rootPath.resolve(SUB_DIR2_PATH_NAME)); + + watchService.registerListener(listener, List.of(Path.of(SUB_DIR_PATH_NAME), Path.of(SUB_DIR2_PATH_NAME)), true); + + Path testFile = rootPath.resolve(SUB_DIR_PATH_NAME).resolve(TEST_FILE_NAME); + Path testFile2 = rootPath.resolve(SUB_DIR2_PATH_NAME).resolve(TEST_FILE_NAME); + + Files.writeString(testFile, "initial content", StandardCharsets.UTF_8); + assertEvent(testFile, Kind.CREATE); + + Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); + assertEvent(testFile, Kind.MODIFY); + + Files.writeString(testFile, "modified content", StandardCharsets.UTF_8); + assertNoEvent(); + + Files.writeString(testFile2, "initial content", StandardCharsets.UTF_8); + assertEvent(testFile2, Kind.CREATE); + + Files.writeString(testFile2, "modified content", StandardCharsets.UTF_8); + assertEvent(testFile2, Kind.MODIFY); + + Files.writeString(testFile2, "modified content", StandardCharsets.UTF_8); + assertNoEvent(); + + Files.delete(testFile); + assertEvent(testFile, Kind.DELETE); + + Files.delete(testFile2); + assertEvent(testFile2, Kind.DELETE); + } + private void assertNoEvent() throws InterruptedException { Thread.sleep(5000); assertThat(listener.events, empty()); } - private void assertEvent(Path path, Kind kind) throws InterruptedException { + private void assertEvent(Path fullPath, Kind kind) throws InterruptedException { waitForAssert(() -> assertThat(listener.events, not(empty()))); Thread.sleep(500); assertThat(listener.events, hasSize(1)); - assertThat(listener.events, hasItem(new Event(path, kind))); + assertThat(listener.events, hasItem(new Event(fullPath, kind))); listener.events.clear(); } @@ -205,11 +238,11 @@ public class WatchServiceImplTest extends JavaTest { List events = new CopyOnWriteArrayList<>(); @Override - public void processWatchEvent(Kind kind, Path path) { - events.add(new Event(path, kind)); + public void processWatchEvent(Kind kind, Path fullPath) { + events.add(new Event(fullPath, kind)); } } - record Event(Path path, Kind kind) { + record Event(Path fullPath, Kind kind) { } }