mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[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 <holger.hees@gmail.com>
This commit is contained in:
parent
9af5bd0944
commit
e857f32a8a
@ -9,7 +9,7 @@
|
|||||||
/bundles/org.openhab.automation.jrubyscripting/ @ccutrer @jimtng
|
/bundles/org.openhab.automation.jrubyscripting/ @ccutrer @jimtng
|
||||||
/bundles/org.openhab.automation.jsscripting/ @jpg0 @florian-h05
|
/bundles/org.openhab.automation.jsscripting/ @jpg0 @florian-h05
|
||||||
/bundles/org.openhab.automation.jsscriptingnashorn/ @wborn
|
/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.pidcontroller/ @fwolter
|
||||||
/bundles/org.openhab.automation.pwm/ @fwolter
|
/bundles/org.openhab.automation.pwm/ @fwolter
|
||||||
/bundles/org.openhab.binding.adorne/ @theiding
|
/bundles/org.openhab.binding.adorne/ @theiding
|
||||||
|
@ -10,15 +10,15 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*/
|
*/
|
||||||
package org.openhab.automation.jythonscripting;
|
package org.openhab.automation.jythonscripting.internal;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
|
|
||||||
@ -36,93 +36,84 @@ import org.osgi.service.component.annotations.Deactivate;
|
|||||||
*
|
*
|
||||||
* @author Scott Rushworth - Initial contribution
|
* @author Scott Rushworth - Initial contribution
|
||||||
* @author Wouter Born - Initial contribution
|
* @author Wouter Born - Initial contribution
|
||||||
|
* @author Holger Hees - Further development
|
||||||
*/
|
*/
|
||||||
@Component(service = ScriptEngineFactory.class)
|
@Component(service = ScriptEngineFactory.class)
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class JythonScriptEngineFactory extends AbstractScriptEngineFactory {
|
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 = "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_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
|
private static final String PYTHON_CACHEDIR = "python.cachedir";
|
||||||
.get(OpenHAB.getConfigFolder(), "automation", "lib", "python").toString();
|
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 org.python.jsr223.PyScriptEngineFactory factory = new org.python.jsr223.PyScriptEngineFactory();
|
||||||
private static final javax.script.ScriptEngineManager ENGINE_MANAGER = new javax.script.ScriptEngineManager();
|
|
||||||
|
private final List<String> scriptTypes = (List<String>) Stream.of(factory.getExtensions(), factory.getMimeTypes())
|
||||||
|
.flatMap(List::stream) //
|
||||||
|
.toList();
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public JythonScriptEngineFactory() {
|
public JythonScriptEngineFactory() {
|
||||||
logger.debug("Loading JythonScriptEngineFactory");
|
logger.debug("Loading JythonScriptEngineFactory");
|
||||||
|
|
||||||
String pythonHome = JythonScriptEngineFactory.class.getProtectionDomain().getCodeSource().getLocation()
|
System.setProperty(PYTHON_HOME, PYTHON_HOME_PATH);
|
||||||
.toString().replace("file:", "");
|
|
||||||
System.setProperty(PYTHON_HOME, pythonHome);
|
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);
|
String existingPythonPath = System.getProperty(PYTHON_PATH);
|
||||||
if (existingPythonPath == null || existingPythonPath.isEmpty()) {
|
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)));
|
Set<String> 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_PATH, String.join(File.pathSeparator, newPythonPathList));
|
||||||
}
|
}
|
||||||
|
|
||||||
System.setProperty(PYTHON_CACHEDIR, Paths
|
System.clearProperty(PYTHON_CACHEDIR);
|
||||||
.get(OpenHAB.getUserDataFolder(), "cache", JythonScriptEngineFactory.class.getPackageName(), "cachedir")
|
|
||||||
.toString());
|
|
||||||
|
|
||||||
logPythonPaths();
|
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() {
|
private void logPythonPaths() {
|
||||||
logger.trace("{}: {}, {}: {}, {}: {}", //
|
logger.trace("{}: {}, {}: {}, {}: {}", //
|
||||||
PYTHON_HOME, System.getProperty(PYTHON_HOME), //
|
PYTHON_HOME, System.getProperty(PYTHON_HOME), //
|
||||||
PYTHON_PATH, System.getProperty(PYTHON_PATH), //
|
PYTHON_PATH, System.getProperty(PYTHON_PATH), //
|
||||||
PYTHON_CACHEDIR, System.getProperty(PYTHON_CACHEDIR));
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -11,10 +11,11 @@
|
|||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*/
|
*/
|
||||||
@org.osgi.annotation.bundle.Header(name = org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE, value = "*")
|
@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
|
* Additional information for the Jython Scripting package
|
||||||
*
|
*
|
||||||
* @author Wouter Born - Initial contribution
|
* @author Wouter Born - Initial contribution
|
||||||
|
* @author Holger Hees - Further development
|
||||||
*/
|
*/
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,11 @@
|
|||||||
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
||||||
|
|
||||||
<type>automation</type>
|
<type>automation</type>
|
||||||
<name>Jython Scripting (DEPRECATED)</name>
|
<name>Jython Scripting</name>
|
||||||
<description>This adds a Jython script engine.</description>
|
<description>This adds a Jython script engine.</description>
|
||||||
<connection>none</connection>
|
<connection>none</connection>
|
||||||
|
|
||||||
|
<service-id>org.openhab.automation.jythonscripting</service-id>
|
||||||
|
<config-description-ref uri="automation:jythonscripting"/>
|
||||||
|
|
||||||
</addon:addon>
|
</addon:addon>
|
||||||
|
Loading…
Reference in New Issue
Block a user