Adapt addons to core watch service changes (#14004)

Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
J-N-K 2023-02-13 16:37:57 +01:00 committed by GitHub
parent ed7159c780
commit d613641bbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 216 additions and 187 deletions

View File

@ -32,6 +32,7 @@ import org.openhab.core.automation.module.script.ScriptDependencyTracker;
import org.openhab.core.automation.module.script.ScriptEngineFactory;
import org.openhab.core.automation.module.script.ScriptExtensionManagerWrapper;
import org.openhab.core.config.core.ConfigurableService;
import org.openhab.core.service.WatchService;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@ -57,9 +58,9 @@ public class JRubyScriptEngineFactory extends AbstractScriptEngineFactory {
private final javax.script.ScriptEngineFactory factory = new org.jruby.embed.jsr223.JRubyEngineFactory();
private final List<String> scriptTypes = Stream.concat(Objects.requireNonNull(factory.getExtensions()).stream(),
Objects.requireNonNull(factory.getMimeTypes()).stream()).collect(Collectors.toUnmodifiableList());
Objects.requireNonNull(factory.getMimeTypes()).stream()).toList();
private JRubyDependencyTracker jrubyDependencyTracker;
private final JRubyDependencyTracker jrubyDependencyTracker;
// Adds $ in front of a set of variables so that Ruby recognizes them as global
// variables
@ -73,8 +74,9 @@ public class JRubyScriptEngineFactory extends AbstractScriptEngineFactory {
}
@Activate
public JRubyScriptEngineFactory(Map<String, Object> config) {
jrubyDependencyTracker = new JRubyDependencyTracker(this);
public JRubyScriptEngineFactory(@Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService,
Map<String, Object> config) {
jrubyDependencyTracker = new JRubyDependencyTracker(watchService, this);
modified(config);
}

View File

@ -12,6 +12,7 @@
*/
package org.openhab.automation.jrubyscripting.internal.watch;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -22,7 +23,7 @@ import java.util.function.Consumer;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.jrubyscripting.internal.JRubyScriptEngineFactory;
import org.openhab.core.automation.module.script.ScriptDependencyTracker;
import org.openhab.core.service.AbstractWatchService;
import org.openhab.core.service.WatchService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -30,6 +31,7 @@ import org.slf4j.LoggerFactory;
* Tracks Ruby dependencies
*
* @author Cody Cutrer - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@NonNullByDefault
public class JRubyDependencyTracker implements ScriptDependencyTracker {
@ -40,29 +42,27 @@ public class JRubyDependencyTracker implements ScriptDependencyTracker {
private final BidiSetBag<String, String> scriptToLibs = new BidiSetBag<>();
private final JRubyScriptEngineFactory scriptEngineFactory;
private final List<AbstractWatchService> dependencyWatchServices = new ArrayList<>();
private final List<JRubyWatchService> dependencyWatchServices = new ArrayList<>();
private final WatchService watchService;
public JRubyDependencyTracker(final JRubyScriptEngineFactory scriptEngineFactory) {
public JRubyDependencyTracker(final WatchService watchService, final JRubyScriptEngineFactory scriptEngineFactory) {
this.watchService = watchService;
this.scriptEngineFactory = scriptEngineFactory;
}
public void activate() {
String gemHome = scriptEngineFactory.getGemHome();
if (!gemHome.isEmpty()) {
dependencyWatchServices.add(new JRubyGemWatchService(gemHome, this));
}
for (String libPath : scriptEngineFactory.getRubyLibPaths()) {
dependencyWatchServices.add(new JRubyLibWatchService(libPath, this));
}
for (AbstractWatchService dependencyWatchService : dependencyWatchServices) {
dependencyWatchService.activate();
dependencyWatchServices.add(new JRubyGemWatchService(watchService, gemHome, this));
}
List<Path> libPaths = scriptEngineFactory.getRubyLibPaths().stream().map(Path::of).toList();
dependencyWatchServices.add(new JRubyLibWatchService(watchService, libPaths, this));
dependencyWatchServices.forEach(JRubyWatchService::activate);
}
public void deactivate() {
for (AbstractWatchService dependencyWatchService : dependencyWatchServices) {
dependencyWatchService.deactivate();
}
dependencyWatchServices.forEach(JRubyWatchService::deactivate);
dependencyWatchServices.clear();
}

View File

@ -12,47 +12,45 @@
*/
package org.openhab.automation.jrubyscripting.internal.watch;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.service.AbstractWatchService;
import org.openhab.core.service.WatchService;
/**
* Watches a gem home
*
* @author Cody Cutrer - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@NonNullByDefault
public class JRubyGemWatchService extends AbstractWatchService {
public class JRubyGemWatchService implements JRubyWatchService, WatchService.WatchEventListener {
private static final String GEMSPEC = ".gemspec";
private final WatchService watchService;
private final Path path;
private JRubyDependencyTracker dependencyTracker;
JRubyGemWatchService(String path, JRubyDependencyTracker dependencyTracker) {
super(path);
JRubyGemWatchService(WatchService watchService, String path, JRubyDependencyTracker dependencyTracker) {
this.watchService = watchService;
this.dependencyTracker = dependencyTracker;
this.path = Path.of(path);
}
@Override
protected boolean watchSubDirectories() {
return true;
public void activate() {
watchService.registerListener(this, path);
}
@Override
protected WatchEvent.Kind<?> @Nullable [] getWatchEventKinds(Path path) {
return new WatchEvent.Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
public void deactivate() {
watchService.unregisterListener(this);
}
@Override
protected void processWatchEvent(WatchEvent<?> watchEvent, WatchEvent.Kind<?> kind, Path path) {
public void processWatchEvent(WatchService.Kind kind, Path path) {
String file = path.toFile().getName();
if (file.endsWith(GEMSPEC)) {
// This seems really lazy, but you can't definitively tell the name

View File

@ -12,47 +12,48 @@
*/
package org.openhab.automation.jrubyscripting.internal.watch;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static org.openhab.core.service.WatchService.Kind.*;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.service.AbstractWatchService;
import org.openhab.core.service.WatchService;
import org.openhab.core.service.WatchService.Kind;
/**
* Watches a Ruby lib dir
*
* @author Cody Cutrer - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@NonNullByDefault
public class JRubyLibWatchService extends AbstractWatchService {
private JRubyDependencyTracker dependencyTracker;
public class JRubyLibWatchService implements JRubyWatchService, WatchService.WatchEventListener {
private final JRubyDependencyTracker dependencyTracker;
private final WatchService watchService;
private final List<Path> paths;
JRubyLibWatchService(String path, JRubyDependencyTracker dependencyTracker) {
super(path);
JRubyLibWatchService(WatchService watchService, List<Path> paths, JRubyDependencyTracker dependencyTracker) {
this.watchService = watchService;
this.dependencyTracker = dependencyTracker;
this.paths = paths;
}
@Override
protected boolean watchSubDirectories() {
return true;
public void activate() {
watchService.registerListener(this, paths);
}
@Override
protected WatchEvent.Kind<?> @Nullable [] getWatchEventKinds(Path path) {
return new WatchEvent.Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
public void deactivate() {
watchService.unregisterListener(this);
}
@Override
protected void processWatchEvent(WatchEvent<?> watchEvent, WatchEvent.Kind<?> kind, Path path) {
public void processWatchEvent(Kind kind, Path path) {
File file = path.toFile();
if (!file.isHidden() && (kind.equals(ENTRY_DELETE)
|| (file.canRead() && (kind.equals(ENTRY_CREATE) || kind.equals(ENTRY_MODIFY))))) {
if (!file.isHidden() && (kind == DELETE || (file.canRead() && (kind == CREATE || kind == MODIFY)))) {
dependencyTracker.dependencyChanged(file.getPath());
}
}

View File

@ -25,6 +25,7 @@ import org.openhab.core.automation.module.script.rulesupport.loader.AbstractScri
import org.openhab.core.automation.module.script.rulesupport.loader.ScriptFileWatcher;
import org.openhab.core.service.ReadyService;
import org.openhab.core.service.StartLevelService;
import org.openhab.core.service.WatchService;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory;
* Monitors <openHAB-conf>/automation/ruby for Ruby files, but not libraries in lib or gems
*
* @author Cody Cutrer - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@Component(immediate = true, service = { ScriptFileWatcher.class, ScriptDependencyTracker.Listener.class })
@NonNullByDefault
@ -50,8 +52,9 @@ public class JRubyScriptFileWatcher extends AbstractScriptFileWatcher {
public JRubyScriptFileWatcher(final @Reference ScriptEngineManager manager,
final @Reference ReadyService readyService, final @Reference StartLevelService startLevelService,
final @Reference(target = "(" + Constants.SERVICE_PID
+ "=org.openhab.automation.jrubyscripting)") ScriptEngineFactory scriptEngineFactory) {
super(manager, readyService, startLevelService, FILE_DIRECTORY);
+ "=org.openhab.automation.jrubyscripting)") ScriptEngineFactory scriptEngineFactory,
final @Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService) {
super(watchService, manager, readyService, startLevelService, FILE_DIRECTORY, true);
this.scriptEngineFactory = (JRubyScriptEngineFactory) scriptEngineFactory;
}

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.automation.jrubyscripting.internal.watch;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JRubyWatchService} is an interface for controlling internal watch services
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public interface JRubyWatchService {
/**
* start watching
*/
void activate();
/**
* stop watching
*/
void deactivate();
}

View File

@ -13,11 +13,12 @@
package org.openhab.automation.jsscripting.internal.fs.watch;
import java.io.File;
import java.nio.file.Files;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.OpenHAB;
import org.openhab.core.automation.module.script.ScriptDependencyTracker;
import org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptDependencyTracker;
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;
@ -31,6 +32,7 @@ import org.slf4j.LoggerFactory;
* Tracks JS module dependencies
*
* @author Jonathan Gilbert - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@Component(service = JSDependencyTracker.class)
@NonNullByDefault
@ -38,25 +40,15 @@ public class JSDependencyTracker extends AbstractScriptDependencyTracker {
private final Logger logger = LoggerFactory.getLogger(JSDependencyTracker.class);
public static final String LIB_PATH = String.join(File.separator, OpenHAB.getConfigFolder(), "automation", "js",
"node_modules");
public JSDependencyTracker() {
super(LIB_PATH);
}
public static final String LIB_PATH = String.join(File.separator, "automation", "js", "node_modules");
@Activate
public void activate() {
File directory = new File(LIB_PATH);
if (!directory.exists()) {
if (!directory.mkdirs()) {
logger.warn("Failed to create watched directory: {}", LIB_PATH);
}
} else if (directory.isFile()) {
logger.warn("Trying to watch directory {}, however it is a file", LIB_PATH);
}
public JSDependencyTracker(@Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService) {
super(watchService, LIB_PATH);
super.activate();
if (Files.isRegularFile(this.libraryPath)) {
logger.warn("Trying to watch directory '{}', however it is a file", this.libraryPath);
}
}
@Deactivate

View File

@ -16,6 +16,7 @@ import java.io.File;
import java.nio.file.Path;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.jsscripting.internal.GraalJSScriptEngineFactory;
import org.openhab.core.automation.module.script.ScriptDependencyTracker;
import org.openhab.core.automation.module.script.ScriptEngineManager;
@ -23,6 +24,7 @@ import org.openhab.core.automation.module.script.rulesupport.loader.AbstractScri
import org.openhab.core.automation.module.script.rulesupport.loader.ScriptFileWatcher;
import org.openhab.core.service.ReadyService;
import org.openhab.core.service.StartLevelService;
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.Reference;
@ -31,29 +33,27 @@ import org.osgi.service.component.annotations.Reference;
* Monitors <openHAB-conf>/automation/js for Javascript files, but not libraries
*
* @author Jonathan Gilbert - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@Component(immediate = true, service = { ScriptFileWatcher.class, ScriptDependencyTracker.Listener.class })
@NonNullByDefault
public class JSScriptFileWatcher extends AbstractScriptFileWatcher {
private static final String FILE_DIRECTORY = "automation" + File.separator + "js";
@Activate
public JSScriptFileWatcher(final @Reference ScriptEngineManager manager, final @Reference ReadyService readyService,
public JSScriptFileWatcher(final @Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService,
final @Reference ScriptEngineManager manager, final @Reference ReadyService readyService,
final @Reference StartLevelService startLevelService) {
super(manager, readyService, startLevelService, FILE_DIRECTORY);
super(watchService, manager, readyService, startLevelService, FILE_DIRECTORY, true);
}
@Override
protected Optional<String> getScriptType(Path scriptFilePath) {
if (!scriptFilePath.startsWith(pathToWatch + File.separator + "node_modules")
if (!scriptFilePath.startsWith(FILE_DIRECTORY + File.separator + "node_modules")
&& "js".equals(super.getScriptType(scriptFilePath).orElse(null))) {
return Optional.of(GraalJSScriptEngineFactory.MIME_TYPE);
} else {
return Optional.empty();
}
}
@Override
protected boolean watchSubDirectories() {
return false;
}
}

View File

@ -14,22 +14,19 @@ package org.openhab.binding.exec.internal;
import static java.nio.file.StandardWatchEventKinds.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.OpenHAB;
import org.openhab.core.service.AbstractWatchService;
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;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -40,35 +37,34 @@ import org.slf4j.LoggerFactory;
*/
@Component(service = ExecWhitelistWatchService.class)
@NonNullByDefault
public class ExecWhitelistWatchService extends AbstractWatchService {
private static final String COMMAND_WHITELIST_PATH = OpenHAB.getConfigFolder() + File.separator + "misc";
private static final String COMMAND_WHITELIST_FILE = "exec.whitelist";
public class ExecWhitelistWatchService implements WatchService.WatchEventListener {
private static final Path COMMAND_WHITELIST_FILE = Path.of("misc", "exec.whitelist");
private final Logger logger = LoggerFactory.getLogger(ExecWhitelistWatchService.class);
private final Set<String> commandWhitelist = new HashSet<>();
private final WatchService watchService;
@Activate
public ExecWhitelistWatchService() {
super(COMMAND_WHITELIST_PATH);
processWatchEvent(null, null, Paths.get(COMMAND_WHITELIST_PATH, COMMAND_WHITELIST_FILE));
public ExecWhitelistWatchService(
final @Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService) {
this.watchService = watchService;
watchService.registerListener(this, COMMAND_WHITELIST_FILE, false);
// read initial content
processWatchEvent(WatchService.Kind.CREATE, COMMAND_WHITELIST_FILE);
}
@Deactivate
public void deactivate() {
watchService.unregisterListener(this);
}
@Override
protected boolean watchSubDirectories() {
return false;
}
@Override
protected Kind<?> @Nullable [] getWatchEventKinds(@Nullable Path directory) {
return new Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
}
@Override
protected void processWatchEvent(@Nullable WatchEvent<?> event, @Nullable Kind<?> kind, @Nullable Path path) {
if (path != null && path.endsWith(COMMAND_WHITELIST_FILE)) {
public void processWatchEvent(WatchService.Kind kind, Path path) {
if (path.endsWith(COMMAND_WHITELIST_FILE)) {
commandWhitelist.clear();
try {
Files.lines(path).filter(line -> !line.trim().startsWith("#")).forEach(commandWhitelist::add);
try (Stream<String> lines = Files.lines(path)) {
lines.filter(line -> !line.trim().startsWith("#")).forEach(commandWhitelist::add);
logger.debug("Updated command whitelist: {}", commandWhitelist);
} catch (IOException e) {
logger.warn("Cannot read whitelist file, exec binding commands won't be processed: {}", e.getMessage());

View File

@ -12,7 +12,6 @@
*/
package org.openhab.binding.miio.internal.basic;
import static java.nio.file.StandardWatchEventKinds.*;
import static org.openhab.binding.miio.internal.MiIoBindingConstants.BINDING_DATABASE_PATH;
import java.io.File;
@ -20,9 +19,6 @@ import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -33,11 +29,14 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.miio.internal.MiIoBindingConstants;
import org.openhab.binding.miio.internal.Utils;
import org.openhab.core.service.AbstractWatchService;
import org.openhab.core.OpenHAB;
import org.openhab.core.service.WatchService;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,23 +49,29 @@ import com.google.gson.JsonParseException;
* The {@link MiIoDatabaseWatchService} creates a registry of database file per ModelId
*
* @author Marcel Verpaalen - Initial contribution
* @author Jan N. Klug - Refactored to new WatchService
*/
@Component(service = MiIoDatabaseWatchService.class)
@NonNullByDefault
public class MiIoDatabaseWatchService extends AbstractWatchService {
public class MiIoDatabaseWatchService implements WatchService.WatchEventListener {
private static final String DATABASE_FILES = ".json";
private static final Gson GSON = new GsonBuilder().serializeNulls().create();
private final Logger logger = LoggerFactory.getLogger(MiIoDatabaseWatchService.class);
private final WatchService watchService;
private Map<String, URL> databaseList = new HashMap<>();
private final Path watchPath;
@Activate
public MiIoDatabaseWatchService() {
super(BINDING_DATABASE_PATH);
public MiIoDatabaseWatchService(@Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService) {
this.watchService = watchService;
this.watchPath = Path.of(BINDING_DATABASE_PATH).relativize(Path.of(OpenHAB.getConfigFolder()));
watchService.registerListener(this, watchPath);
logger.debug(
"Started miio basic devices local databases watch service. Watching for database files at path: {}",
BINDING_DATABASE_PATH);
processWatchEvent(null, null, Paths.get(BINDING_DATABASE_PATH));
processWatchEvent(WatchService.Kind.CREATE, watchPath);
populateDatabase();
if (logger.isTraceEnabled()) {
for (String device : databaseList.keySet()) {
@ -75,26 +80,19 @@ public class MiIoDatabaseWatchService extends AbstractWatchService {
}
}
@Override
protected boolean watchSubDirectories() {
return true;
@Deactivate
public void deactivate() {
watchService.unregisterListener(this);
}
@Override
protected Kind<?> @Nullable [] getWatchEventKinds(@Nullable Path directory) {
return new Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
}
@Override
protected void processWatchEvent(@Nullable WatchEvent<?> event, @Nullable Kind<?> kind, @Nullable Path path) {
if (path != null) {
public void processWatchEvent(WatchService.Kind kind, Path path) {
final Path p = path.getFileName();
if (p != null && p.toString().endsWith(DATABASE_FILES)) {
logger.debug("Local Databases file {} changed. Refreshing device database.", p.getFileName());
populateDatabase();
}
}
}
/**
* Return the database file URL for a given modelId

View File

@ -12,24 +12,19 @@
*/
package org.openhab.transform.exec.internal;
import static java.nio.file.StandardWatchEventKinds.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.OpenHAB;
import org.openhab.core.service.AbstractWatchService;
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;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -40,35 +35,34 @@ import org.slf4j.LoggerFactory;
*/
@Component(service = ExecTransformationWhitelistWatchService.class)
@NonNullByDefault
public class ExecTransformationWhitelistWatchService extends AbstractWatchService {
private static final String COMMAND_WHITELIST_PATH = OpenHAB.getConfigFolder() + File.separator + "misc";
private static final String COMMAND_WHITELIST_FILE = "exec.whitelist";
public class ExecTransformationWhitelistWatchService implements WatchService.WatchEventListener {
private static final Path COMMAND_WHITELIST_FILE = Path.of("misc", "exec.whitelist");
private final Logger logger = LoggerFactory.getLogger(ExecTransformationWhitelistWatchService.class);
private final Set<String> commandWhitelist = new HashSet<>();
private final WatchService watchService;
@Activate
public ExecTransformationWhitelistWatchService() {
super(COMMAND_WHITELIST_PATH);
processWatchEvent(null, null, Paths.get(COMMAND_WHITELIST_PATH, COMMAND_WHITELIST_FILE));
public ExecTransformationWhitelistWatchService(
final @Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService) {
this.watchService = watchService;
watchService.registerListener(this, COMMAND_WHITELIST_FILE);
// read initial content
processWatchEvent(WatchService.Kind.CREATE, COMMAND_WHITELIST_FILE);
}
@Deactivate
public void deactivate() {
watchService.unregisterListener(this);
}
@Override
protected boolean watchSubDirectories() {
return false;
}
@Override
protected Kind<?> @Nullable [] getWatchEventKinds(@Nullable Path directory) {
return new Kind<?>[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY };
}
@Override
protected void processWatchEvent(@Nullable WatchEvent<?> event, @Nullable Kind<?> kind, @Nullable Path path) {
if (path != null && path.endsWith(COMMAND_WHITELIST_FILE)) {
public void processWatchEvent(WatchService.Kind kind, Path path) {
if (path.endsWith(COMMAND_WHITELIST_FILE)) {
commandWhitelist.clear();
try {
Files.lines(path).filter(line -> !line.trim().startsWith("#")).forEach(commandWhitelist::add);
try (Stream<String> lines = Files.lines(path)) {
lines.filter(line -> !line.trim().startsWith("#")).forEach(commandWhitelist::add);
logger.debug("Updated command whitelist: {}", commandWhitelist);
} catch (IOException e) {
logger.warn("Cannot read whitelist file, exec transformations won't be processed: {}", e.getMessage());

View File

@ -66,4 +66,8 @@ Fragment-Host: org.openhab.automation.jsscriptingnashorn
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
org.threeten.extra;version='[1.5.0,1.5.1)'
org.threeten.extra;version='[1.5.0,1.5.1)',\
com.sun.jna;version='[5.12.1,5.12.2)',\
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
org.apache.felix.configadmin;version='[1.9.24,1.9.25)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)'

View File

@ -50,4 +50,6 @@ Fragment-Host: org.openhab.binding.astro
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.storage.json;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)'
com.google.gson;version='[2.9.1,2.9.2)',\
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -77,4 +77,6 @@ Fragment-Host: org.openhab.binding.avmfritz
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.objectweb.asm;version='[9.4.0,9.4.1)'
org.objectweb.asm;version='[9.4.0,9.4.1)',\
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.feed
-runrequires: \
bnd.identity;id='org.openhab.binding.feed.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml',\
bnd.identity;id='org.apache.felix.configadmin',\
osgi.identity;filter:='(&(osgi.identity=org.ops4j.pax.web.pax-web-runtime)(version>=7.2.3))'
@ -77,4 +76,5 @@ Fragment-Host: org.openhab.binding.feed
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.hue
-runrequires: \
bnd.identity;id='org.openhab.binding.hue.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml',\
bnd.identity;id='org.eclipse.jdt.annotation'
@ -81,4 +80,5 @@ Fragment-Host: org.openhab.binding.hue
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.max
-runrequires: \
bnd.identity;id='org.openhab.binding.max.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -68,4 +67,5 @@ Fragment-Host: org.openhab.binding.max
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.mielecloud
-runrequires: \
bnd.identity;id='org.openhab.binding.mielecloud.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
-runblacklist: \
@ -87,4 +86,5 @@ Fragment-Host: org.openhab.binding.mielecloud
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.modbus
-runrequires: \
bnd.identity;id='org.openhab.binding.modbus.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# 1) We would like to use the "volatile" storage only, drop other storage
@ -77,4 +76,5 @@ Fragment-Host: org.openhab.binding.modbus
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -13,7 +13,6 @@ Import-Package: \
-runrequires: \
bnd.identity;id='org.openhab.binding.mqtt.homeassistant.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -111,5 +110,6 @@ Import-Package: \
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
jakarta.ws.rs-api;version='[2.1.6,2.1.7)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)',\
jakarta.ws.rs-api;version='[2.1.6,2.1.7)'

View File

@ -13,7 +13,6 @@ Import-Package: \
-runrequires: \
bnd.identity;id='org.openhab.binding.mqtt.homie.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -111,6 +110,7 @@ Import-Package: \
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
jakarta.ws.rs-api;version='[2.1.6,2.1.7)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)',\
jakarta.ws.rs-api;version='[2.1.6,2.1.7)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.nest
-runrequires: \
bnd.identity;id='org.openhab.binding.nest.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -106,5 +105,6 @@ Fragment-Host: org.openhab.binding.nest
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.objectweb.asm;version='[9.4.0,9.4.1)',\
com.fasterxml.woodstox.woodstox-core;version='[6.4.0,6.4.1)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)',\
com.fasterxml.woodstox.woodstox-core;version='[6.4.0,6.4.1)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.ntp
-runrequires: \
bnd.identity;id='org.openhab.binding.ntp.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -72,4 +71,5 @@ Fragment-Host: org.openhab.binding.ntp
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.systeminfo
-runrequires: \
bnd.identity;id='org.openhab.binding.systeminfo.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -76,4 +75,4 @@ Fragment-Host: org.openhab.binding.systeminfo
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.tradfri
-runrequires: \
bnd.identity;id='org.openhab.binding.tradfri.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -79,4 +78,5 @@ Fragment-Host: org.openhab.binding.tradfri
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -5,7 +5,6 @@ Fragment-Host: org.openhab.binding.wemo
-runrequires: \
bnd.identity;id='org.openhab.binding.wemo.tests',\
bnd.identity;id='org.openhab.core.addon.xml',\
bnd.identity;id='org.openhab.core.thing.xml'
# We would like to use the "volatile" storage only
@ -85,4 +84,5 @@ Fragment-Host: org.openhab.binding.wemo
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)',\
org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core.addon.xml;version='[4.0.0,4.0.1)'
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)'

View File

@ -59,4 +59,8 @@ Fragment-Host: org.openhab.persistence.mapdb
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.persistence.mapdb;version='[4.0.0,4.0.1)',\
org.openhab.persistence.mapdb.tests;version='[4.0.0,4.0.1)',\
com.google.gson;version='[2.9.1,2.9.2)'
com.google.gson;version='[2.9.1,2.9.2)',\
io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\
com.sun.jna;version='[5.12.1,5.12.2)',\
org.apache.felix.configadmin;version='[1.9.24,1.9.25)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)'