Skip to content

Commit

Permalink
improvements
Browse files Browse the repository at this point in the history
Signed-off-by: Jan N. Klug <[email protected]>
  • Loading branch information
J-N-K committed Jul 31, 2022
1 parent 658c79c commit e8fa89a
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.service;
package org.openhab.core.internal.service;

import java.nio.file.Path;
import java.util.Dictionary;
Expand All @@ -20,6 +20,8 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.OpenHAB;
import org.openhab.core.service.WatchService;
import org.openhab.core.service.WatchServiceFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentException;
import org.osgi.service.component.ComponentFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,20 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.service;
package org.openhab.core.internal.service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.service.WatchService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
Expand All @@ -45,15 +42,14 @@
@NonNullByDefault
@Component(factory = "org.openhab.core.service.watchservice.factory")
public class WatchServiceImpl implements WatchService, DirectoryChangeListener {
private static final String THREAD_POOL_NAME = "file-processing";

private final Logger logger = LoggerFactory.getLogger(WatchServiceImpl.class);
private final ScheduledExecutorService scheduler = ThreadPoolManager.getScheduledPool(THREAD_POOL_NAME);
private final Path basePath;

private final List<Listener> dirPathListeners = new CopyOnWriteArrayList<>();
private final List<Listener> subDirPathListeners = new CopyOnWriteArrayList<>();

private final Thread watchThread;

private final DirectoryWatcher dirWatcher;
private final String name;

Expand All @@ -66,10 +62,16 @@ public WatchServiceImpl(Map<String, Object> config) throws IOException {
logger.error("Tried to instantiate WatchService '{}' with missing configuration.", name);
throw new IllegalArgumentException("Path to watch is missing.");
}

try {
basePath = Path.of(path).toAbsolutePath();
if (!Files.exists(basePath)) {
logger.info("Watch directory '{}' does not exists. Trying to create it.", basePath);
Files.createDirectories(basePath);
}
dirWatcher = DirectoryWatcher.builder().listener(this).path(basePath).build();
// schedule immediately but make sure not in this thread as the implementation is blocking
watchThread = new Thread(dirWatcher::watch, name);
watchThread.start();
} catch (NoSuchFileException e) {
// log message here, otherwise it'll be swallowed by the call to newInstance in the factory
// also re-throw the exception to indicate that we failed
Expand All @@ -81,19 +83,29 @@ public WatchServiceImpl(Map<String, Object> config) throws IOException {
logger.warn("Could not instantiate WatchService '{}':", name, e);
throw e;
}
scheduler.schedule(dirWatcher::watch, 0, TimeUnit.SECONDS);
}

@Deactivate
public void deactivate() throws IOException {
dirWatcher.close();
watchThread.interrupt();
}

@Override
public void registerListener(WatchEventListener watchEventListener, List<Path> paths, boolean withSubDirectories) {
List<Listener> list = withSubDirectories ? this.subDirPathListeners : dirPathListeners;
paths.stream().map(this::toAbsolutePath).filter(Objects::nonNull)
.map(p -> new Listener((@NonNull Path) p, watchEventListener)).forEach(list::add);
for (Path path : paths) {
Path absolutePath = path.isAbsolute() ? path : basePath.resolve(path).toAbsolutePath();
if (absolutePath.startsWith(basePath)) {
if (withSubDirectories) {
subDirPathListeners.add(new Listener(absolutePath, watchEventListener));
} else {
dirPathListeners.add(new Listener(absolutePath, watchEventListener));
}
} else {
logger.warn("Tried to add path '{}' to listener '{}', but the base path of this listener is '{}'", path,
name, basePath);
}
}
}

@Override
Expand All @@ -102,18 +114,6 @@ public void unregisterListener(WatchEventListener watchEventListener) {
dirPathListeners.removeIf(Listener.isListener(watchEventListener));
}

private @Nullable Path toAbsolutePath(Path path) {
if (path.isAbsolute()) {
if (path.startsWith(basePath)) {
return path;
}
logger.warn("Tried to add path '{}' to listener '{}', but the base path of this listener is '{}'", path,
name, basePath);
return null;
}
return basePath.resolve(path).toAbsolutePath();
}

@Override
public void onEvent(@Nullable DirectoryChangeEvent directoryChangeEvent) throws IOException {
if (directoryChangeEvent == null || directoryChangeEvent.isDirectory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.service;
package org.openhab.core.internal.service;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
Expand Down Expand Up @@ -38,6 +38,7 @@
import org.openhab.core.JavaTest;
import org.openhab.core.OpenHAB;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.service.WatchService;
import org.openhab.core.service.WatchService.Kind;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public class FolderObserverTest extends JavaOSGiTest {

private static final String INITIAL_FILE_CONTENT = "Initial content";

private static final String WATCH_SERVICE_NAME = "testWatcher";

private @NonNullByDefault({}) Dictionary<String, Object> configProps;
private @NonNullByDefault({}) String defaultWatchedDir;
private @NonNullByDefault({}) FolderObserver folderObserver;
Expand Down Expand Up @@ -124,7 +126,8 @@ private void setUpServices() throws IOException {
when(contextMock.getProperties()).thenReturn(configProps);

watchServiceFactory = getService(WatchServiceFactory.class);
watchService = watchServiceFactory.getWatchService("watcher", WATCHED_DIRECTORY.toPath());
watchService = watchServiceFactory.getWatchService(WATCH_SERVICE_NAME,
WATCHED_DIRECTORY.toPath().toAbsolutePath());
modelRepo = new ModelRepoDummy();

folderObserver = new FolderObserver(modelRepo, readyServiceMock, watchService);
Expand All @@ -140,7 +143,7 @@ private void setUpServices() throws IOException {
@AfterEach
public void tearDown() throws Exception {
folderObserver.deactivate();
watchServiceFactory.removeWatchService("watcher");
watchServiceFactory.removeWatchService(WATCH_SERVICE_NAME);

try (Stream<Path> walk = Files.walk(WATCHED_DIRECTORY.toPath())) {
walk.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
Expand Down

0 comments on commit e8fa89a

Please sign in to comment.