Как получить движок сценария Kotlin jsr223 из ScriptEngineManager? - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь написать интерфейс (GUI) для запуска некоторых сценариев Kotlin. Я начинаю с простого теста Junit, чтобы убедиться, что я могу выполнить скрипт. Я даже не могу загрузить двигатель kotlin. Кажется, что мои зависимости (gradle) в порядке, но вы можете проверить это дважды.

compile name: 'kotlin-script-runtime',
    group: 'org.jetbrains.kotlin', version: kotlin_version
compile name: 'kotlin-script-util',
    group: 'org.jetbrains.kotlin', version: kotlin_version
compile name: 'kotlin-compiler-embeddable',
    group: 'org.jetbrains.kotlin', version: kotlin_version

выше: ext.kotlin_version = '1.3.0'

Вот неудачный тест:

@Test
fun testEngine() {
  // attempt to load script engine class before looking for it
  val ktsEngineClassName = "org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngine";
  var clazz: Class<*>? = null;
  // assign the clazz variable inside a closure to catch ClassNotFound
  assertDoesNotThrow({clazz = Class.forName(ktsEngineClassName)}, "could not find $ktsEngineClassName")
  // just to make sure it's there
  assertNotNull(clazz, "could not find $ktsEngineClassName")

  // so far so good, but here's the problem:
  val engineName = "kotlin"
  // load the factory
  val factory = ScriptEngineManager().getEngineByName(engineName)?.factory
  // and test that we got it
  assertNotNull(factory, "didn't find factory for '$engineName'." +
      "\navailable: ${ScriptEngineManager().engineFactories}")
}

Этот последний assertNotNull завершается ошибкой со следующим выводом:

org.opentest4j.AssertionFailedError: didn't find factory for 'kotlin'.
available: [jdk.nashorn.api.scripting.NashornScriptEngineFactory@1a41b1fc] ==> expected: not <null>

Как видите, хотя класс обработчика сценариев, похоже, успешно загружается через Class.forName, имя kotlin не зарегистрировано, и список доступных обработчиков содержит только Nashorn. Как мне убедиться, что двигатель зарегистрирован?

1 Ответ

0 голосов
/ 31 октября 2018

Похоже, что движок сценариев kotlin отсутствует в загрузчике классов по умолчанию, поэтому вам необходимо указать загрузчик классов при создании экземпляра ScriptEngineManager:

ScriptEngineManager (clazz.getClassLoader ()) getEngineByName (engineName) ?. завод

UPDATE

В Java 8, если вы посмотрите на $ JAVA_HOME / jre / lib / ext / nashorn.jar в пути META_INF / services , есть файл с именем javax .script.ScriptEngineFactory . Содержание:

jdk.nashorn.api.scripting.NashornScriptEngineFactory

Поэтому, когда ScriptEngineManager ищет реализации ScriptEngine, он сканирует путь к классам для записей с именем /META-INF/services/javax.script.ScriptEngineFactory и загружает имена классов из каждой найденной.

Обычно фляга, содержащая ваш целевой механизм скриптов, будет содержать свой собственный файл сервисов, но, если ваш движок скриптов kotlin уже находится в пути к классам, я думаю, вы можете просто создать ресурс classpath с именем /META-INF/services/javax.script.ScriptEngineFactory с простым текстом контекст

org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory

и тебе надо идти. Кроме того, вам не понадобится код, который вы указали в своем примере над комментарием // so far so good, but here's the problem:.

...