diff --git a/pom.xml b/pom.xml
index 49f29bd..461a0b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -87,6 +87,11 @@ Wisconsin-Madison.
org/jetbrains/kotlin/daemon/common/*,kotlinx/coroutines/**
+ 1.4.30
+
+
+
+ false
@@ -111,20 +116,13 @@ Wisconsin-Madison.
org.jetbrains.kotlin
- kotlin-script-util
+ kotlin-stdlib
${kotlin.version}
org.jetbrains.kotlin
- kotlin-script-runtime
+ kotlin-scripting-jsr223
${kotlin.version}
- runtime
-
-
- org.jetbrains.kotlin
- kotlin-scripting-compiler-embeddable
- ${kotlin.version}
- runtime
diff --git a/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java b/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java
deleted file mode 100644
index d2ab486..0000000
--- a/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * #%L
- * JSR-223-compliant Kotlin scripting language plugin.
- * %%
- * Copyright (C) 2016 - 2019 Board of Regents of the University of
- * Wisconsin-Madison.
- * %%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * #L%
- */
-
-package org.scijava.plugins.scripting.kotlin;
-
-import java.util.Arrays;
-import java.util.List;
-
-import javax.script.ScriptEngine;
-
-import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory;
-import org.scijava.plugin.Plugin;
-import org.scijava.script.AdaptedScriptLanguage;
-import org.scijava.script.ScriptLanguage;
-
-/**
- * A SciJava {@link ScriptLanguage} for Kotlin.
- *
- * @author Curtis Rueden
- * @see ScriptEngine
- */
-@Plugin(type = ScriptLanguage.class, name = "Kotlin")
-public class KotlinScriptLanguage extends AdaptedScriptLanguage {
-
- public KotlinScriptLanguage() {
- super(new KotlinJsr223JvmLocalScriptEngineFactory());
- }
-
- @Override
- public List getNames() {
- // NB: The wrapped ScriptEngineFactory does not include Kotlin in its list.
- return Arrays.asList("kotlin", "Kotlin");
- }
-
- @Override
- public List getExtensions() {
- // NB: The wrapped ScriptEngineFactory does not include .kt in its list.
- return Arrays.asList("kt", "kts");
- }
-}
diff --git a/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt
new file mode 100644
index 0000000..e777e68
--- /dev/null
+++ b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt
@@ -0,0 +1,111 @@
+/*
+ * #%L
+ * JSR-223-compliant Kotlin scripting language plugin.
+ * %%
+ * Copyright (C) 2016 - 2019 Board of Regents of the University of
+ * Wisconsin-Madison.
+ * %%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * #L%
+ */
+package org.scijava.plugins.scripting.kotlin
+
+import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase
+import org.scijava.plugin.Plugin
+import org.scijava.script.AdaptedScriptLanguage
+import org.scijava.script.ScriptLanguage
+import java.io.Reader
+import javax.script.*
+
+/**
+ * A SciJava [ScriptLanguage] for Kotlin.
+ *
+ * @author Curtis Rueden
+ * @author Philipp Hanslovsky
+ * @see ScriptEngine
+ */
+@Plugin(type = ScriptLanguage::class, name = "Kotlin")
+class KotlinScriptLanguage : AdaptedScriptLanguage(Factory()) {
+ // NB: The wrapped ScriptEngineFactory does not include Kotlin in its list.
+ override fun getNames() = listOf("kotlin", "Kotlin")
+
+ // NB: The wrapped ScriptEngineFactory does not include .kt in its list.
+ override fun getExtensions() = listOf("kt", "kts")
+
+ class Factory : KotlinJsr223JvmScriptEngineFactoryBase() {
+ override fun getScriptEngine(): ScriptEngine {
+ return SynchronizedScriptEngine(ScriptEngineManager().getEngineByExtension("kts"))
+ }
+ }
+
+ class SynchronizedScriptEngine(private val delegate: ScriptEngine) : ScriptEngine {
+ @Synchronized
+ @Throws(ScriptException::class)
+ override fun eval(s: String, scriptContext: ScriptContext): Any? = delegate.eval(s, scriptContext)
+
+ @Synchronized
+ @Throws(ScriptException::class)
+ override fun eval(reader: Reader, scriptContext: ScriptContext): Any? = delegate.eval(reader, scriptContext)
+
+ @Synchronized
+ @Throws(ScriptException::class)
+ override fun eval(s: String): Any? = delegate.eval(s)
+
+ @Synchronized
+ @Throws(ScriptException::class)
+ override fun eval(reader: Reader): Any? = delegate.eval(reader)
+
+ @Synchronized
+ @Throws(ScriptException::class)
+ override fun eval(s: String, bindings: Bindings): Any? = delegate.eval(s, bindings)
+
+ @Synchronized
+ @Throws(ScriptException::class)
+ override fun eval(reader: Reader, bindings: Bindings): Any? = delegate.eval(reader, bindings)
+
+ @Synchronized
+ override fun put(s: String, o: Any) = delegate.put(s, o)
+
+ @Synchronized
+ override fun get(s: String): Any? = delegate[s]
+
+ @Synchronized
+ override fun getBindings(i: Int): Bindings? = delegate.getBindings(i)
+
+ @Synchronized
+ override fun setBindings(bindings: Bindings, i: Int) = delegate.setBindings(bindings, i)
+
+ @Synchronized
+ override fun createBindings(): Bindings = delegate.createBindings()
+
+ @Synchronized
+ override fun getContext(): ScriptContext = delegate.context
+
+ @Synchronized
+ override fun setContext(scriptContext: ScriptContext) {
+ delegate.context = scriptContext
+ }
+
+ @Synchronized
+ override fun getFactory(): ScriptEngineFactory = delegate.factory
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java b/src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java
deleted file mode 100644
index c99da98..0000000
--- a/src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * #%L
- * JSR-223-compliant Kotlin scripting language plugin.
- * %%
- * Copyright (C) 2016 - 2019 Board of Regents of the University of
- * Wisconsin-Madison.
- * %%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * #L%
- */
-
-package org.scijava.plugins.scripting.kotlin;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-
-import org.junit.Test;
-import org.scijava.Context;
-import org.scijava.script.AbstractScriptLanguageTest;
-import org.scijava.script.ScriptLanguage;
-import org.scijava.script.ScriptModule;
-import org.scijava.script.ScriptService;
-
-/**
- * Kotlin unit tests.
- *
- * @author Curtis Rueden
- */
-public class KotlinTest extends AbstractScriptLanguageTest {
-
- @Test
- public void testDiscovery() {
- assertDiscovered(KotlinScriptLanguage.class);
- }
-
- @Test
- public void testBasic() throws InterruptedException, ExecutionException,
- IOException, ScriptException
- {
- final Context context = new Context(ScriptService.class);
- final ScriptService scriptService = context.getService(ScriptService.class);
- final String script = "1 + 2";
- final ScriptModule m = scriptService.run("add.kt", script, true).get();
- final Object result = m.getReturnValue();
- assertEquals("3", result.toString());
- }
-
- @Test
- public void testLocals() throws ScriptException {
- final Context context = new Context(ScriptService.class);
- final ScriptService scriptService = context.getService(ScriptService.class);
-
- final ScriptLanguage language = scriptService.getLanguageByExtension("kt");
- final ScriptEngine engine = language.getScriptEngine();
- assertTrue(engine.getFactory().getNames().contains("kotlin"));
-
- engine.put("hello", 17);
- assertEquals("17", engine.eval("bindings[\"hello\"]").toString());
- assertEquals("17", engine.get("hello").toString());
-
- engine.put("foo", "bar");
- assertEquals("bar", engine.eval("bindings[\"foo\"]").toString());
- assertEquals("bar", engine.get("foo").toString());
- // FIXME: You cannot modify or insert a variable in the bindings!
-// engine.eval("bindings[\"foo\"] = \"great\"");
-// assertEquals("great", engine.eval("bindings[\"foo\"]").toString());
-// assertEquals("great", engine.get("foo").toString());
-
- final Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
- bindings.clear();
- assertNull(engine.get("hello"));
- }
-
- // FIXME: Calling methods on injected instance vars fails with
- // "unresolved reference". Nor can we store values into the bindings map!
-// @Test
-// public void testParameters() throws InterruptedException, ExecutionException,
-// IOException, ScriptException
-// {
-// final Context context = new Context(ScriptService.class);
-// final ScriptService scriptService = context.getService(ScriptService.class);
-//
-// final String script = "" + //
-// "// @ScriptService ss\n" + //
-// "// @OUTPUT String language\n" + //
-// "// @OUTPUT ScriptService ssOut\n" + //
-// "println(\"==> \" + bindings[\"ss\"])\n" + //
-// "bindings[\"ssOut\"] = bindings[\"ss\"]\n";
-//// "println(\"==> \" + ss.canHandleFile(\"/Users/curtis\"))\n";
-//// "val language = " + //
-//// "bindings[\"ss\"].getLanguageByName(\"kotlin\").getLanguageName()\n";
-// final ScriptModule m = scriptService.run("hello.kt", script, true).get();
-//
-// final Object actual = m.getOutput("ssOut");
-// final Object expected =
-// scriptService.getLanguageByName("kotlin");
-// assertEquals(expected, actual);
-// }
-
-}
diff --git a/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt
new file mode 100644
index 0000000..08b6c5c
--- /dev/null
+++ b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt
@@ -0,0 +1,93 @@
+/*
+ * #%L
+ * JSR-223-compliant Kotlin scripting language plugin.
+ * %%
+ * Copyright (C) 2016 - 2019 Board of Regents of the University of
+ * Wisconsin-Madison.
+ * %%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * #L%
+ */
+package org.scijava.plugins.scripting.kotlin
+
+import org.junit.Assert
+import org.junit.BeforeClass
+import org.junit.Test
+import org.scijava.Context
+import org.scijava.script.AbstractScriptLanguageTest
+import org.scijava.script.ScriptLanguage
+import org.scijava.script.ScriptService
+import java.io.IOException
+import java.util.concurrent.ExecutionException
+import javax.script.ScriptContext
+import javax.script.ScriptEngine
+import javax.script.ScriptException
+import kotlin.math.E
+
+/**
+ * Kotlin unit tests.
+ *
+ * @author Curtis Rueden
+ * @author Philipp Hanslovsky
+ */
+class KotlinTest : AbstractScriptLanguageTest() {
+
+ @Test
+ fun testDiscovery() = assertDiscovered(KotlinScriptLanguage::class.java)
+
+ @Test
+ @Throws(InterruptedException::class, ExecutionException::class, IOException::class, ScriptException::class)
+ fun `test basic script engine eval`() = Assert.assertEquals(3, engine.eval("1 + 2"))
+
+ @Test
+ @Throws(ScriptException::class)
+ fun `test basic engine eval with bindings`() {
+ engine.put("Hello", ", SciJava!")
+ Assert.assertEquals(", SciJava!", engine.eval("Hello"))
+ Assert.assertEquals(", SciJava!", engine["Hello"])
+
+ val bindings = engine.createBindings()
+ bindings["base"] = E
+ val script = "import kotlin.math.*; base.pow(0)"
+ Assert.assertThrows(ScriptException::class.java) { engine.eval(script) }
+ Assert.assertEquals(1.0, engine.eval(script, bindings) as Double, 0.0)
+
+ // clear bindings and access variable Hello to cause ScriptException
+ engine.getBindings(ScriptContext.ENGINE_SCOPE)?.clear()
+ Assert.assertNull(engine["Hello"])
+ }
+
+
+ companion object {
+ @BeforeClass
+ @JvmStatic
+ fun initKotlinLang() {
+ val context = Context(ScriptService::class.java)
+ val scriptService: ScriptService = context.getService(ScriptService::class.java)
+ _kotlinLang = scriptService.getLanguageByName("Kotlin")
+ _engine = _kotlinLang.scriptEngine
+ }
+ private lateinit var _kotlinLang: ScriptLanguage
+ private lateinit var _engine: ScriptEngine
+ val engine get() = _engine
+ }
+}
\ No newline at end of file