From ae677dcd9d07bc265cf3b4d3083be9c0863f76be Mon Sep 17 00:00:00 2001 From: J-N-K Date: Tue, 29 Nov 2022 21:59:58 +0100 Subject: [PATCH] [jsscripting] Refactor dependency tracking (#13756) Signed-off-by: Jan N. Klug --- .../internal/GraalJSScriptEngineFactory.java | 19 ++++--- .../fs/watch/JSDependencyTracker.java | 29 +++++++++- .../internal/fs/watch/JSFileWatcher.java | 57 ------------------- .../fs/watch/JSScriptFileWatcher.java | 16 ++++-- 4 files changed, 50 insertions(+), 71 deletions(-) delete mode 100644 bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSFileWatcher.java diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java index 8a4745ea4..31c69745e 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java @@ -12,13 +12,14 @@ */ package org.openhab.automation.jsscripting.internal; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import javax.script.ScriptEngine; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker; +import org.openhab.core.automation.module.script.ScriptDependencyTracker; import org.openhab.core.automation.module.script.ScriptEngineFactory; import org.openhab.core.config.core.ConfigurableService; import org.osgi.framework.Constants; @@ -39,6 +40,7 @@ import org.osgi.service.component.annotations.Reference; public final class GraalJSScriptEngineFactory implements ScriptEngineFactory { private static final String CFG_INJECTION_ENABLED = "injectionEnabled"; private static final String INJECTION_CODE = "Object.assign(this, require('openhab'));"; + private final JSDependencyTracker jsDependencyTracker; private boolean injectionEnabled = true; public static final String MIME_TYPE = "application/javascript;version=ECMAScript-2021"; @@ -46,14 +48,14 @@ public final class GraalJSScriptEngineFactory implements ScriptEngineFactory { @Activate public GraalJSScriptEngineFactory(final @Reference JSScriptServiceUtil jsScriptServiceUtil, - Map config) { + final @Reference JSDependencyTracker jsDependencyTracker, Map config) { + this.jsDependencyTracker = jsDependencyTracker; this.jsScriptServiceUtil = jsScriptServiceUtil; modified(config); } @Override public List getScriptTypes() { - List scriptTypes = new ArrayList<>(); /* * Whilst we run in parallel with Nashorn, we use a custom mime-type to avoid @@ -66,9 +68,7 @@ public final class GraalJSScriptEngineFactory implements ScriptEngineFactory { // scriptTypes.addAll(graalJSEngineFactory.getMimeTypes()); // scriptTypes.addAll(graalJSEngineFactory.getExtensions()); - scriptTypes.add(MIME_TYPE); - - return Collections.unmodifiableList(scriptTypes); + return List.of(MIME_TYPE); } @Override @@ -82,6 +82,11 @@ public final class GraalJSScriptEngineFactory implements ScriptEngineFactory { new OpenhabGraalJSScriptEngine(injectionEnabled ? INJECTION_CODE : null, jsScriptServiceUtil)); } + @Override + public @Nullable ScriptDependencyTracker getDependencyTracker() { + return jsDependencyTracker; + } + @Modified protected void modified(Map config) { Object injectionEnabled = config.get(CFG_INJECTION_ENABLED); diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java index f4cb934d9..c8cb1c669 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java @@ -14,8 +14,16 @@ package org.openhab.automation.jsscripting.internal.fs.watch; import java.io.File; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.OpenHAB; -import org.openhab.core.automation.module.script.rulesupport.loader.DependencyTracker; +import org.openhab.core.automation.module.script.ScriptDependencyTracker; +import org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptDependencyTracker; +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.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,7 +32,9 @@ import org.slf4j.LoggerFactory; * * @author Jonathan Gilbert - Initial contribution */ -public class JSDependencyTracker extends DependencyTracker { +@Component(service = JSDependencyTracker.class) +@NonNullByDefault +public class JSDependencyTracker extends AbstractScriptDependencyTracker { private final Logger logger = LoggerFactory.getLogger(JSDependencyTracker.class); @@ -35,6 +45,7 @@ public class JSDependencyTracker extends DependencyTracker { super(LIB_PATH); } + @Activate public void activate() { File directory = new File(LIB_PATH); if (!directory.exists()) { @@ -47,4 +58,18 @@ public class JSDependencyTracker extends DependencyTracker { super.activate(); } + + @Deactivate + public void deactivate() { + super.deactivate(); + } + + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, unbind = "removeChangeTracker") + public void addChangeTracker(ScriptDependencyTracker.Listener listener) { + super.addChangeTracker(listener); + } + + public void removeChangeTracker(ScriptDependencyTracker.Listener listener) { + super.removeChangeTracker(listener); + } } diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSFileWatcher.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSFileWatcher.java deleted file mode 100644 index c801c3f49..000000000 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSFileWatcher.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2010-2022 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.jsscripting.internal.fs.watch; - -import org.openhab.core.automation.module.script.ScriptEngineManager; -import org.openhab.core.service.ReadyService; -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; - -/** - * Monitors /automation/js for Javascript files & libraries. - * - * This class is required to ensure that the *order* of set up is correct. Specifically, the dependency tracker must - * be activated after the script file watcher. This is because AbstractWatchService only allows a single service to - * watch a single directory, and given that the watchers are nested and the last registration wins, the one we want to - * monitor the libraries must be registered last. - * - * @author Jonathan Gilbert - Initial contribution - */ -@Component(immediate = true, service = JSFileWatcher.class) -public class JSFileWatcher { - - private final JSScriptFileWatcher jsScriptFileWatcher; - private final JSDependencyTracker jsDependencyTracker; - - @Activate - public JSFileWatcher(final @Reference ScriptEngineManager manager, final @Reference ReadyService readyService) { - jsDependencyTracker = new JSDependencyTracker(); - jsScriptFileWatcher = new JSScriptFileWatcher(manager, readyService, jsDependencyTracker); - } - - @Activate - public void activate() { - jsScriptFileWatcher.activate(); - jsDependencyTracker.activate(); - jsDependencyTracker.addChangeTracker(jsScriptFileWatcher); - } - - @Deactivate - void deactivate() { - jsDependencyTracker.removeChangeTracker(jsScriptFileWatcher); - jsDependencyTracker.deactivate(); - jsScriptFileWatcher.deactivate(); - } -} diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java index 2285c2690..817e64a8d 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java @@ -20,24 +20,30 @@ import java.util.Optional; import org.eclipse.jdt.annotation.Nullable; import org.openhab.automation.jsscripting.internal.GraalJSScriptEngineFactory; +import org.openhab.core.automation.module.script.ScriptDependencyTracker; import org.openhab.core.automation.module.script.ScriptEngineManager; +import org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher; import org.openhab.core.automation.module.script.rulesupport.loader.ScriptFileReference; -import org.openhab.core.automation.module.script.rulesupport.loader.ScriptFileWatcher; import org.openhab.core.service.ReadyService; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * Monitors /automation/js for Javascript files, but not libraries * * @author Jonathan Gilbert - Initial contribution */ -public class JSScriptFileWatcher extends ScriptFileWatcher { +@Component(immediate = true, service = ScriptDependencyTracker.Listener.class) +public class JSScriptFileWatcher extends AbstractScriptFileWatcher { private static final String FILE_DIRECTORY = "automation" + File.separator + "js"; private final String ignorePath; - public JSScriptFileWatcher(final ScriptEngineManager manager, final ReadyService readyService, - JSDependencyTracker dependencyTracker) { - super(manager, dependencyTracker, readyService, FILE_DIRECTORY); + @Activate + public JSScriptFileWatcher(final @Reference ScriptEngineManager manager, + final @Reference ReadyService readyService) { + super(manager, readyService, FILE_DIRECTORY); ignorePath = pathToWatch + File.separator + "node_modules"; }