]> git.basschouten.com Git - openhab-addons.git/blob
61d7f97c4308fc60db43db3bd77d195ce2f0a6be
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.automation.jsscripting.internal;
14
15 import java.util.List;
16 import java.util.Map;
17 import java.util.stream.Stream;
18
19 import javax.script.ScriptEngine;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker;
24 import org.openhab.core.automation.module.script.ScriptDependencyTracker;
25 import org.openhab.core.automation.module.script.ScriptEngineFactory;
26 import org.openhab.core.config.core.ConfigParser;
27 import org.openhab.core.config.core.ConfigurableService;
28 import org.osgi.framework.Constants;
29 import org.osgi.service.component.annotations.Activate;
30 import org.osgi.service.component.annotations.Component;
31 import org.osgi.service.component.annotations.Modified;
32 import org.osgi.service.component.annotations.Reference;
33
34 import com.oracle.truffle.js.scriptengine.GraalJSEngineFactory;
35
36 /**
37  * An implementation of {@link ScriptEngineFactory} with customizations for GraalJS ScriptEngines.
38  *
39  * @author Jonathan Gilbert - Initial contribution
40  * @author Dan Cunningham - Script injections
41  */
42 @Component(service = ScriptEngineFactory.class, configurationPid = "org.openhab.jsscripting", property = Constants.SERVICE_PID
43         + "=org.openhab.jsscripting")
44 @ConfigurableService(category = "automation", label = "JS Scripting", description_uri = "automation:jsscripting")
45 @NonNullByDefault
46 public final class GraalJSScriptEngineFactory implements ScriptEngineFactory {
47     private static final String CFG_INJECTION_ENABLED = "injectionEnabled";
48     private static final String CFG_INJECTION_CACHING_ENABLED = "injectionCachingEnabled";
49
50     private static final GraalJSEngineFactory factory = new GraalJSEngineFactory();
51
52     private static final List<String> scriptTypes = createScriptTypes();
53
54     private static List<String> createScriptTypes() {
55         // Add those for backward compatibility (existing scripts may rely on those MIME types)
56         List<String> backwardCompat = List.of("application/javascript;version=ECMAScript-2021", "graaljs");
57         return Stream.of(factory.getMimeTypes(), factory.getExtensions(), backwardCompat).flatMap(List::stream)
58                 .toList();
59     }
60
61     private boolean injectionEnabled = true;
62     private boolean injectionCachingEnabled = true;
63
64     private final JSScriptServiceUtil jsScriptServiceUtil;
65     private final JSDependencyTracker jsDependencyTracker;
66
67     @Activate
68     public GraalJSScriptEngineFactory(final @Reference JSScriptServiceUtil jsScriptServiceUtil,
69             final @Reference JSDependencyTracker jsDependencyTracker, Map<String, Object> config) {
70         this.jsDependencyTracker = jsDependencyTracker;
71         this.jsScriptServiceUtil = jsScriptServiceUtil;
72         modified(config);
73     }
74
75     @Override
76     public List<String> getScriptTypes() {
77         return scriptTypes;
78     }
79
80     @Override
81     public void scopeValues(ScriptEngine scriptEngine, Map<String, Object> scopeValues) {
82         // noop; they are retrieved via modules, not injected
83     }
84
85     @Override
86     public @Nullable ScriptEngine createScriptEngine(String scriptType) {
87         if (!scriptTypes.contains(scriptType)) {
88             return null;
89         }
90         return new DebuggingGraalScriptEngine<>(new OpenhabGraalJSScriptEngine(injectionEnabled,
91                 injectionCachingEnabled, jsScriptServiceUtil, jsDependencyTracker));
92     }
93
94     @Override
95     public @Nullable ScriptDependencyTracker getDependencyTracker() {
96         return jsDependencyTracker;
97     }
98
99     @Modified
100     protected void modified(Map<String, ?> config) {
101         this.injectionEnabled = ConfigParser.valueAsOrElse(config.get(CFG_INJECTION_ENABLED), Boolean.class, true);
102         this.injectionCachingEnabled = ConfigParser.valueAsOrElse(config.get(CFG_INJECTION_CACHING_ENABLED),
103                 Boolean.class, true);
104     }
105 }