[jsscripting] Check if language is available (#19439)

This is required due to the service loading used by Graal, see https://github.com/openhab/openhab-osgiify/blob/81a752c60450ae9b5eb70bbf30f89ba18377a86e/README.md.

Signed-off-by: Florian Hotze <dev@florianhotze.com>
This commit is contained in:
Florian Hotze
2025-10-09 21:59:12 +02:00
committed by GitHub
parent 707cbeb5bf
commit 125e0055e0
2 changed files with 30 additions and 9 deletions
@@ -54,6 +54,8 @@ public class GraalJSScriptEngineFactory implements ScriptEngineFactory {
public static final String SCRIPT_TYPE = "application/javascript";
private static final String LANG_NOT_INITIALIZED_MSG = "Graal JavaScript language not initialized. Restart openHAB to initialize available Graal languages properly.";
private static final GraalJSEngineFactory FACTORY = new GraalJSEngineFactory();
private static final List<String> SCRIPT_TYPES = createScriptTypes();
@@ -79,6 +81,10 @@ public class GraalJSScriptEngineFactory implements ScriptEngineFactory {
this.jsDependencyTracker = jsDependencyTracker;
this.jsScriptServiceUtil = jsScriptServiceUtil;
this.configuration = new GraalJSScriptEngineConfiguration(config);
if (OpenhabGraalJSScriptEngine.getLanguage() == null) {
logger.error(LANG_NOT_INITIALIZED_MSG);
}
}
@Modified
@@ -101,6 +107,10 @@ public class GraalJSScriptEngineFactory implements ScriptEngineFactory {
if (!SCRIPT_TYPES.contains(scriptType)) {
return null;
}
if (OpenhabGraalJSScriptEngine.getLanguage() == null) {
logger.error(LANG_NOT_INITIALIZED_MSG);
return null;
}
return new DebuggingGraalScriptEngine<>(
new OpenhabGraalJSScriptEngine(configuration, jsScriptServiceUtil, jsDependencyTracker));
}
@@ -46,6 +46,7 @@ import org.eclipse.jdt.annotation.Nullable;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Language;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.io.IOAccess;
@@ -76,13 +77,15 @@ public class OpenhabGraalJSScriptEngine
extends InvocationInterceptingScriptEngineWithInvocableAndCompilableAndAutoCloseable<GraalJSScriptEngine>
implements Lock {
// see private constant GraalJSScriptEngine.ID
private static final String LANGUAGE_ID = "js";
private static final Source GLOBAL_SOURCE;
static {
try {
GLOBAL_SOURCE = Source
.newBuilder("js", getFileAsReader(GraalJSScriptEngineFactory.NODE_DIR + "/@jsscripting-globals.js"),
"@jsscripting-globals.js")
.cached(true).build();
GLOBAL_SOURCE = Source.newBuilder(LANGUAGE_ID,
getFileAsReader(GraalJSScriptEngineFactory.NODE_DIR + "/@jsscripting-globals.js"),
"@jsscripting-globals.js").cached(true).build();
} catch (IOException e) {
throw new IllegalStateException("Failed to load @jsscripting-globals.js", e);
}
@@ -91,10 +94,9 @@ public class OpenhabGraalJSScriptEngine
private static final Source OPENHAB_JS_SOURCE;
static {
try {
OPENHAB_JS_SOURCE = Source
.newBuilder("js", getFileAsReader(GraalJSScriptEngineFactory.NODE_DIR + "/@openhab-globals.js"),
"@openhab-globals.js")
.cached(true).build();
OPENHAB_JS_SOURCE = Source.newBuilder(LANGUAGE_ID,
getFileAsReader(GraalJSScriptEngineFactory.NODE_DIR + "/@openhab-globals.js"),
"@openhab-globals.js").cached(true).build();
} catch (IOException e) {
throw new IllegalStateException("Failed to load @openhab-globals.js", e);
}
@@ -160,7 +162,7 @@ public class OpenhabGraalJSScriptEngine
this.configuration = configuration;
this.jsRuntimeFeatures = jsScriptServiceUtil.getJSRuntimeFeatures(lock);
delegate = GraalJSScriptEngine.create(ENGINE, Context.newBuilder("js") //
delegate = GraalJSScriptEngine.create(ENGINE, Context.newBuilder(LANGUAGE_ID) //
.allowIO(IOAccess.newBuilder() //
.fileSystem(new DelegatingFileSystem(FileSystems.getDefault().provider()) {
@Override
@@ -476,4 +478,13 @@ public class OpenhabGraalJSScriptEngine
public Condition newCondition() {
return lock.newCondition();
}
/**
* Gets the Graal language of {@link OpenhabGraalJSScriptEngine}.
*
* @return the Graal language of {@link OpenhabGraalJSScriptEngine} or {@code null} if not available
*/
public static @Nullable Language getLanguage() {
return ENGINE.getLanguages().get(LANGUAGE_ID);
}
}