From: Holger Hees Date: Sun, 17 Mar 2024 22:14:49 +0000 (+0100) Subject: [jythonscripting] Refactor, improve and simplify (#16508) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=e857f32a8afdd005d17ccf17a82d15928850e289;p=openhab-addons.git [jythonscripting] Refactor, improve and simplify (#16508) * 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 --- diff --git a/CODEOWNERS b/CODEOWNERS index 0a8e564cbb..a3a4786ac5 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -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 index fc3ee61df3..0000000000 --- a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/JythonScriptEngineFactory.java +++ /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 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 getScriptTypes() { - List scriptTypes = new ArrayList<>(); - - for (javax.script.ScriptEngineFactory factory : ENGINE_MANAGER.getEngineFactories()) { - List 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 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 index 0000000000..5937f3c3a0 --- /dev/null +++ b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/JythonScriptEngineFactory.java @@ -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 scriptTypes = (List) 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 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 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 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 index 0000000000..66806c5fc1 --- /dev/null +++ b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/package-info.java @@ -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 index 0000000000..3682dea1d5 --- /dev/null +++ b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/watch/JythonScriptFileWatcher.java @@ -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 /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 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 index 522363121f..0000000000 --- a/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/package-info.java +++ /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 - */ diff --git a/bundles/org.openhab.automation.jythonscripting/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.automation.jythonscripting/src/main/resources/OH-INF/addon/addon.xml index 19bd7bbb56..d479fd0831 100644 --- a/bundles/org.openhab.automation.jythonscripting/src/main/resources/OH-INF/addon/addon.xml +++ b/bundles/org.openhab.automation.jythonscripting/src/main/resources/OH-INF/addon/addon.xml @@ -4,8 +4,11 @@ xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd"> automation - Jython Scripting (DEPRECATED) + Jython Scripting This adds a Jython script engine. none + org.openhab.automation.jythonscripting + +