diff --git a/CODEOWNERS b/CODEOWNERS index 0a8e564cbb3..a3a4786ac56 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/internal/JythonScriptEngineFactory.java similarity index 55% rename from bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/JythonScriptEngineFactory.java rename to bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/JythonScriptEngineFactory.java index fc3ee61df32..5937f3c3a0c 100644 --- 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/internal/JythonScriptEngineFactory.java @@ -10,15 +10,15 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.automation.jythonscripting; +package org.openhab.automation.jythonscripting.internal; 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 java.util.stream.Stream; import javax.script.ScriptEngine; @@ -36,93 +36,84 @@ import org.osgi.service.component.annotations.Deactivate; * * @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_CACHEDIR = "python.cachedir"; 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 DEFAULT_PYTHON_PATH = Paths - .get(OpenHAB.getConfigFolder(), "automation", "lib", "python").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 String SCRIPT_TYPE = "py"; - private static final javax.script.ScriptEngineManager ENGINE_MANAGER = new javax.script.ScriptEngineManager(); + 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"); - String pythonHome = JythonScriptEngineFactory.class.getProtectionDomain().getCodeSource().getLocation() - .toString().replace("file:", ""); - System.setProperty(PYTHON_HOME, pythonHome); + 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()) { - System.setProperty(PYTHON_PATH, DEFAULT_PYTHON_PATH); - } else if (!existingPythonPath.contains(DEFAULT_PYTHON_PATH)) { + if (existingPythonPath != null && !existingPythonPath.isEmpty()) { Set newPythonPathList = new TreeSet<>(Arrays.asList(existingPythonPath.split(File.pathSeparator))); - newPythonPathList.add(DEFAULT_PYTHON_PATH); + newPythonPathList.remove(PYTHON_DEFAULT_PATH); System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, newPythonPathList)); } - System.setProperty(PYTHON_CACHEDIR, Paths - .get(OpenHAB.getUserDataFolder(), "cache", JythonScriptEngineFactory.class.getPackageName(), "cachedir") - .toString()); + 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)); } - - @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/package-info.java b/bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/package-info.java similarity index 85% rename from bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/package-info.java rename to bundles/org.openhab.automation.jythonscripting/src/main/java/org/openhab/automation/jythonscripting/internal/package-info.java index 522363121fc..66806c5fc1c 100644 --- 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/internal/package-info.java @@ -11,10 +11,11 @@ * SPDX-License-Identifier: EPL-2.0 */ @org.osgi.annotation.bundle.Header(name = org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE, value = "*") -package org.openhab.automation.jythonscripting; +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 00000000000..3682dea1d59 --- /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/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.automation.jythonscripting/src/main/resources/OH-INF/addon/addon.xml index 19bd7bbb56c..d479fd0831e 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 + +