]> git.basschouten.com Git - openhab-addons.git/commitdiff
[jythonscripting] Refactor, improve and simplify (#16508)
authorHolger Hees <holger.hees@gmail.com>
Sun, 17 Mar 2024 22:14:49 +0000 (23:14 +0100)
committerGitHub <noreply@github.com>
Sun, 17 Mar 2024 22:14:49 +0000 (23:14 +0100)
* moved implementation to 'internal'
* refactored JythonScriptEngineFactory
* implemented JythonScriptFileWatcher
* fixed addon.xml & package-info.java
* simplify stream list collector in JythonScriptEngineFactory
* changed codeowner for jythonscripting
* organized imports in JythonScriptEngineFactory

Signed-off-by: Holger Hees <holger.hees@gmail.com>
CODEOWNERS
bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/JythonScriptEngineFactory.java [deleted file]
bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/JythonScriptEngineFactory.java [new file with mode: 0644]
bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/package-info.java [new file with mode: 0644]
bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/watch/JythonScriptFileWatcher.java [new file with mode: 0644]
bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/package-info.java [deleted file]
bundles/org.openhab.automation.jythonscripting/src/main/resources/OH-INF/addon/addon.xml

index 0a8e564cbb30660e7d840679c655ceee282578a2..a3a4786ac56f1feb071994fc16da34f801991fec 100644 (file)
@@ -9,7 +9,7 @@
 /bundles/org.openhab.automation.jrubyscripting/ @ccutrer @jimtng
 /bundles/org.openhab.automation.jsscripting/ @jpg0 @florian-h05
 /bundles/org.openhab.automation.jsscriptingnashorn/ @wborn
-/bundles/org.openhab.automation.jythonscripting/ @openhab/add-ons-maintainers
+/bundles/org.openhab.automation.jythonscripting/ @HolgerHees
 /bundles/org.openhab.automation.pidcontroller/ @fwolter
 /bundles/org.openhab.automation.pwm/ @fwolter
 /bundles/org.openhab.binding.adorne/ @theiding
diff --git a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/JythonScriptEngineFactory.java b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/JythonScriptEngineFactory.java
deleted file mode 100644 (file)
index fc3ee61..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.jythonscripting;
-
-import java.io.File;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import javax.script.ScriptEngine;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.OpenHAB;
-import org.openhab.core.automation.module.script.AbstractScriptEngineFactory;
-import org.openhab.core.automation.module.script.ScriptEngineFactory;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-
-/**
- * This is an implementation of {@link ScriptEngineFactory} for Jython.
- *
- * @author Scott Rushworth - Initial contribution
- * @author Wouter Born - Initial contribution
- */
-@Component(service = ScriptEngineFactory.class)
-@NonNullByDefault
-public class JythonScriptEngineFactory extends AbstractScriptEngineFactory {
-
-    private static final String PYTHON_CACHEDIR = "python.cachedir";
-    private static final String PYTHON_HOME = "python.home";
-    private static final String PYTHON_PATH = "python.path";
-
-    private static final String DEFAULT_PYTHON_PATH = Paths
-            .get(OpenHAB.getConfigFolder(), "automation", "lib", "python").toString();
-
-    private static final String SCRIPT_TYPE = "py";
-    private static final javax.script.ScriptEngineManager ENGINE_MANAGER = new javax.script.ScriptEngineManager();
-
-    @Activate
-    public JythonScriptEngineFactory() {
-        logger.debug("Loading JythonScriptEngineFactory");
-
-        String pythonHome = JythonScriptEngineFactory.class.getProtectionDomain().getCodeSource().getLocation()
-                .toString().replace("file:", "");
-        System.setProperty(PYTHON_HOME, pythonHome);
-
-        String existingPythonPath = System.getProperty(PYTHON_PATH);
-        if (existingPythonPath == null || existingPythonPath.isEmpty()) {
-            System.setProperty(PYTHON_PATH, DEFAULT_PYTHON_PATH);
-        } else if (!existingPythonPath.contains(DEFAULT_PYTHON_PATH)) {
-            Set<String> newPythonPathList = new TreeSet<>(Arrays.asList(existingPythonPath.split(File.pathSeparator)));
-            newPythonPathList.add(DEFAULT_PYTHON_PATH);
-            System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, newPythonPathList));
-        }
-
-        System.setProperty(PYTHON_CACHEDIR, Paths
-                .get(OpenHAB.getUserDataFolder(), "cache", JythonScriptEngineFactory.class.getPackageName(), "cachedir")
-                .toString());
-
-        logPythonPaths();
-    }
-
-    private void logPythonPaths() {
-        logger.trace("{}: {}, {}: {}, {}: {}", //
-                PYTHON_HOME, System.getProperty(PYTHON_HOME), //
-                PYTHON_PATH, System.getProperty(PYTHON_PATH), //
-                PYTHON_CACHEDIR, System.getProperty(PYTHON_CACHEDIR));
-    }
-
-    @Override
-    public List<String> getScriptTypes() {
-        List<String> scriptTypes = new ArrayList<>();
-
-        for (javax.script.ScriptEngineFactory factory : ENGINE_MANAGER.getEngineFactories()) {
-            List<String> extensions = factory.getExtensions();
-
-            if (extensions.contains(SCRIPT_TYPE)) {
-                scriptTypes.addAll(extensions);
-                scriptTypes.addAll(factory.getMimeTypes());
-            }
-        }
-        return scriptTypes;
-    }
-
-    @Override
-    public @Nullable ScriptEngine createScriptEngine(String scriptType) {
-        ScriptEngine scriptEngine = ENGINE_MANAGER.getEngineByExtension(scriptType);
-        if (scriptEngine == null) {
-            scriptEngine = ENGINE_MANAGER.getEngineByMimeType(scriptType);
-        }
-        if (scriptEngine == null) {
-            scriptEngine = ENGINE_MANAGER.getEngineByName(scriptType);
-        }
-        return scriptEngine;
-    }
-
-    @Deactivate
-    public void removePythonPath() {
-        logger.debug("Unloading JythonScriptEngineFactory");
-
-        String existingPythonPath = System.getProperty(PYTHON_PATH);
-        if (existingPythonPath != null && existingPythonPath.contains(DEFAULT_PYTHON_PATH)) {
-            Set<String> newPythonPathList = new TreeSet<>(Arrays.asList(existingPythonPath.split(File.pathSeparator)));
-            newPythonPathList.remove(DEFAULT_PYTHON_PATH);
-            System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, newPythonPathList));
-        }
-
-        System.clearProperty(PYTHON_HOME);
-        System.clearProperty(PYTHON_CACHEDIR);
-
-        logPythonPaths();
-    }
-}
diff --git a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/JythonScriptEngineFactory.java b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/JythonScriptEngineFactory.java
new file mode 100644 (file)
index 0000000..5937f3c
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2010-2024 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.jythonscripting.internal;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Stream;
+
+import javax.script.ScriptEngine;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.OpenHAB;
+import org.openhab.core.automation.module.script.AbstractScriptEngineFactory;
+import org.openhab.core.automation.module.script.ScriptEngineFactory;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+/**
+ * This is an implementation of {@link ScriptEngineFactory} for Jython.
+ *
+ * @author Scott Rushworth - Initial contribution
+ * @author Wouter Born - Initial contribution
+ * @author Holger Hees - Further development
+ */
+@Component(service = ScriptEngineFactory.class)
+@NonNullByDefault
+public class JythonScriptEngineFactory extends AbstractScriptEngineFactory {
+
+    private static final String PYTHON_HOME = "python.home";
+    private static final String PYTHON_HOME_PATH = JythonScriptEngineFactory.class.getProtectionDomain().getCodeSource()
+            .getLocation().toString().replace("file:", "");
+
+    private static final String PYTHON_PATH = "python.path";
+    private static final String PYTHON_DEFAULT_PATH = Paths
+            .get(OpenHAB.getConfigFolder(), "automation", "jython", "lib").toString();
+
+    private static final String PYTHON_CACHEDIR = "python.cachedir";
+    private static final String PYTHON_CACHEDIR_PATH = Paths
+            .get(OpenHAB.getUserDataFolder(), "cache", JythonScriptEngineFactory.class.getPackageName(), "cachedir")
+            .toString();
+
+    private static final org.python.jsr223.PyScriptEngineFactory factory = new org.python.jsr223.PyScriptEngineFactory();
+
+    private final List<String> scriptTypes = (List<String>) Stream.of(factory.getExtensions(), factory.getMimeTypes())
+            .flatMap(List::stream) //
+            .toList();
+
+    @Activate
+    public JythonScriptEngineFactory() {
+        logger.debug("Loading JythonScriptEngineFactory");
+
+        System.setProperty(PYTHON_HOME, PYTHON_HOME_PATH);
+
+        Set<String> pythonPathList = new TreeSet<>(Arrays.asList(PYTHON_DEFAULT_PATH));
+        String existingPythonPath = System.getProperty(PYTHON_PATH);
+        if (existingPythonPath != null && !existingPythonPath.isEmpty()) {
+            pythonPathList.addAll(Arrays.asList(existingPythonPath.split(File.pathSeparator)));
+        }
+        System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, pythonPathList));
+
+        System.setProperty(PYTHON_CACHEDIR, PYTHON_CACHEDIR_PATH);
+
+        logPythonPaths();
+    }
+
+    @Deactivate
+    public void cleanup() {
+        logger.debug("Unloading JythonScriptEngineFactory");
+
+        System.clearProperty(PYTHON_HOME);
+
+        String existingPythonPath = System.getProperty(PYTHON_PATH);
+        if (existingPythonPath != null && !existingPythonPath.isEmpty()) {
+            Set<String> newPythonPathList = new TreeSet<>(Arrays.asList(existingPythonPath.split(File.pathSeparator)));
+            newPythonPathList.remove(PYTHON_DEFAULT_PATH);
+            System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, newPythonPathList));
+        }
+
+        System.clearProperty(PYTHON_CACHEDIR);
+
+        logPythonPaths();
+    }
+
+    @Override
+    public List<String> getScriptTypes() {
+        return scriptTypes;
+    }
+
+    @Override
+    public @Nullable ScriptEngine createScriptEngine(String scriptType) {
+        if (!scriptTypes.contains(scriptType)) {
+            return null;
+        }
+        return factory.getScriptEngine();
+    }
+
+    private void logPythonPaths() {
+        logger.trace("{}: {}, {}: {}, {}: {}", //
+                PYTHON_HOME, System.getProperty(PYTHON_HOME), //
+                PYTHON_PATH, System.getProperty(PYTHON_PATH), //
+                PYTHON_CACHEDIR, System.getProperty(PYTHON_CACHEDIR));
+    }
+}
diff --git a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/package-info.java b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/package-info.java
new file mode 100644 (file)
index 0000000..66806c5
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2010-2024 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
+ */
+@org.osgi.annotation.bundle.Header(name = org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE, value = "*")
+package org.openhab.automation.jythonscripting.internal;
+
+/**
+ * Additional information for the Jython Scripting package
+ *
+ * @author Wouter Born - Initial contribution
+ * @author Holger Hees - Further development
+ */
diff --git a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/watch/JythonScriptFileWatcher.java b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/watch/JythonScriptFileWatcher.java
new file mode 100644 (file)
index 0000000..3682dea
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2010-2024 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.jythonscripting.internal.watch;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+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.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;
+
+/**
+ * Monitors {@code <openHAB-conf>/automation/jython} for Jython files, but not libraries
+ *
+ * @author Holger Hees - Initial contribution
+ */
+@Component(immediate = true, service = { ScriptFileWatcher.class, ScriptDependencyTracker.Listener.class })
+@NonNullByDefault
+public class JythonScriptFileWatcher extends AbstractScriptFileWatcher {
+    private static final String FILE_DIRECTORY = "automation" + File.separator + "jython";
+
+    @Activate
+    public JythonScriptFileWatcher(
+            final @Reference(target = WatchService.CONFIG_WATCHER_FILTER) WatchService watchService,
+            final @Reference ScriptEngineManager manager, final @Reference ReadyService readyService,
+            final @Reference StartLevelService startLevelService) {
+        super(watchService, manager, readyService, startLevelService, FILE_DIRECTORY, true);
+    }
+
+    @Override
+    protected Optional<String> getScriptType(Path scriptFilePath) {
+        String scriptType = super.getScriptType(scriptFilePath).orElse(null);
+        if (!scriptFilePath.startsWith(getWatchPath().resolve("lib")) && ("py".equals(scriptType))) {
+            return Optional.of(scriptType);
+        }
+        return Optional.empty();
+    }
+}
diff --git a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/package-info.java b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/package-info.java
deleted file mode 100644 (file)
index 5223631..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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
- */
-@org.osgi.annotation.bundle.Header(name = org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE, value = "*")
-package org.openhab.automation.jythonscripting;
-
-/**
- * Additional information for the Jython Scripting package
- *
- * @author Wouter Born - Initial contribution
- */
index 19bd7bbb56cbc3177693a9a99d457f245cb3a047..d479fd0831e638e455096a4523c74131fe1f1e0b 100644 (file)
@@ -4,8 +4,11 @@
        xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
 
        <type>automation</type>
-       <name>Jython Scripting (DEPRECATED)</name>
+       <name>Jython Scripting</name>
        <description>This adds a Jython script engine.</description>
        <connection>none</connection>
 
+       <service-id>org.openhab.automation.jythonscripting</service-id>
+       <config-description-ref uri="automation:jythonscripting"/>
+
 </addon:addon>