2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.automation.jythonscripting;
16 import java.nio.file.Paths;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.List;
21 import java.util.TreeSet;
23 import javax.script.ScriptEngine;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.core.OpenHAB;
28 import org.openhab.core.automation.module.script.AbstractScriptEngineFactory;
29 import org.openhab.core.automation.module.script.ScriptEngineFactory;
30 import org.osgi.service.component.annotations.Activate;
31 import org.osgi.service.component.annotations.Component;
32 import org.osgi.service.component.annotations.Deactivate;
35 * This is an implementation of {@link ScriptEngineFactory} for Jython.
37 * @author Scott Rushworth - Initial contribution
38 * @author Wouter Born - Initial contribution
40 @Component(service = ScriptEngineFactory.class)
42 public class JythonScriptEngineFactory extends AbstractScriptEngineFactory {
44 private static final String PYTHON_CACHEDIR = "python.cachedir";
45 private static final String PYTHON_HOME = "python.home";
46 private static final String PYTHON_PATH = "python.path";
48 private static final String DEFAULT_PYTHON_PATH = Paths
49 .get(OpenHAB.getConfigFolder(), "automation", "lib", "python").toString();
51 private static final String SCRIPT_TYPE = "py";
52 private static final javax.script.ScriptEngineManager ENGINE_MANAGER = new javax.script.ScriptEngineManager();
55 public JythonScriptEngineFactory() {
56 logger.debug("Loading JythonScriptEngineFactory");
58 String pythonHome = JythonScriptEngineFactory.class.getProtectionDomain().getCodeSource().getLocation()
59 .toString().replace("file:", "");
60 System.setProperty(PYTHON_HOME, pythonHome);
62 String existingPythonPath = System.getProperty(PYTHON_PATH);
63 if (existingPythonPath == null || existingPythonPath.isEmpty()) {
64 System.setProperty(PYTHON_PATH, DEFAULT_PYTHON_PATH);
65 } else if (!existingPythonPath.contains(DEFAULT_PYTHON_PATH)) {
66 Set<String> newPythonPathList = new TreeSet<>(Arrays.asList(existingPythonPath.split(File.pathSeparator)));
67 newPythonPathList.add(DEFAULT_PYTHON_PATH);
68 System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, newPythonPathList));
71 System.setProperty(PYTHON_CACHEDIR, Paths
72 .get(OpenHAB.getUserDataFolder(), "cache", JythonScriptEngineFactory.class.getPackageName(), "cachedir")
78 private void logPythonPaths() {
79 logger.trace("{}: {}, {}: {}, {}: {}", //
80 PYTHON_HOME, System.getProperty(PYTHON_HOME), //
81 PYTHON_PATH, System.getProperty(PYTHON_PATH), //
82 PYTHON_CACHEDIR, System.getProperty(PYTHON_CACHEDIR));
86 public List<String> getScriptTypes() {
87 List<String> scriptTypes = new ArrayList<>();
89 for (javax.script.ScriptEngineFactory factory : ENGINE_MANAGER.getEngineFactories()) {
90 List<String> extensions = factory.getExtensions();
92 if (extensions.contains(SCRIPT_TYPE)) {
93 scriptTypes.addAll(extensions);
94 scriptTypes.addAll(factory.getMimeTypes());
101 public @Nullable ScriptEngine createScriptEngine(String scriptType) {
102 ScriptEngine scriptEngine = ENGINE_MANAGER.getEngineByExtension(scriptType);
103 if (scriptEngine == null) {
104 scriptEngine = ENGINE_MANAGER.getEngineByMimeType(scriptType);
106 if (scriptEngine == null) {
107 scriptEngine = ENGINE_MANAGER.getEngineByName(scriptType);
113 public void removePythonPath() {
114 logger.debug("Unloading JythonScriptEngineFactory");
116 String existingPythonPath = System.getProperty(PYTHON_PATH);
117 if (existingPythonPath != null && existingPythonPath.contains(DEFAULT_PYTHON_PATH)) {
118 Set<String> newPythonPathList = new TreeSet<>(Arrays.asList(existingPythonPath.split(File.pathSeparator)));
119 newPythonPathList.remove(DEFAULT_PYTHON_PATH);
120 System.setProperty(PYTHON_PATH, String.join(File.pathSeparator, newPythonPathList));
123 System.clearProperty(PYTHON_HOME);
124 System.clearProperty(PYTHON_CACHEDIR);