Skip to content

Commit 730a93b

Browse files
committed
Fixed: MissingCoreLibraryException when running script in FIJI #10
1 parent 14c826f commit 730a93b

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package dotty.tools.repl
2+
3+
// This file is based on dotty.tools.repl.ScriptEngine in Scala Compiler
4+
// It is using some package private classes from `dotty.tools.repl`
5+
// Only necessary changes are made, no corrects existing compiler warnings, etc.
6+
7+
import dotty.tools.dotc
8+
import dotty.tools.dotc.core.StdNames.str
9+
10+
import java.io.{Reader, StringWriter}
11+
import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngineFactory, ScriptException, SimpleBindings, ScriptEngine as JScriptEngine}
12+
import scala.language.unsafeNulls
13+
14+
/**
15+
* A JSR 223 (Scripting API) compatible wrapper around the REPL for improved
16+
* interoperability with software that supports it.
17+
*
18+
* It works by instantiating a new script engine through the script engine manager.
19+
* The script engine provides a eval method to evaluate scripts in string form.
20+
* Example use:
21+
*
22+
* val m = new javax.script.ScriptEngineManager()
23+
* val e = m.getEngineByName("scala")
24+
* println(e.eval("42"))
25+
*/
26+
class SciJavaScriptEngine(classPath: String) extends AbstractScriptEngine {
27+
new javax.script.ScriptEngineManager()
28+
private val driver = new ReplDriver(
29+
Array(
30+
"-classpath",
31+
classPath,
32+
"-usejavacp",
33+
"-color:never",
34+
"-Xrepl-disable-display"
35+
),
36+
Console.out,
37+
None
38+
)
39+
private val rendering = new Rendering(Some(getClass.getClassLoader))
40+
private var state: State = driver.initialState
41+
42+
def getFactory: ScriptEngineFactory = new ScriptEngine.Factory
43+
44+
def createBindings: Bindings = new SimpleBindings
45+
46+
/* Evaluate with the given context. */
47+
@throws[ScriptException]
48+
def eval(script: String, context: ScriptContext): Object = {
49+
val vid = state.valIndex
50+
state = driver.run(script)(using state)
51+
val oid = state.objectIndex
52+
Class.forName(s"${Rendering.REPL_WRAPPER_NAME_PREFIX}$oid", true, rendering.classLoader()(using state.context))
53+
.getDeclaredMethods.find(_.getName == s"${str.REPL_RES_PREFIX}$vid")
54+
.map(_.invoke(null))
55+
.getOrElse(null)
56+
}
57+
58+
@throws[ScriptException]
59+
def eval(reader: Reader, context: ScriptContext): Object = eval(stringFromReader(reader), context)
60+
61+
private val buffer = new Array[Char](8192)
62+
63+
def stringFromReader(in: Reader) = {
64+
val out = new StringWriter
65+
var n = in.read(buffer)
66+
while (n > -1) {
67+
out.write(buffer, 0, n)
68+
n = in.read(buffer)
69+
}
70+
in.close
71+
out.toString
72+
}
73+
}
74+
75+
object SciJavaScriptEngine {
76+
import java.util.Arrays
77+
import scala.util.Properties
78+
class Factory(classPath: String) extends ScriptEngineFactory {
79+
def getEngineName = "Scala REPL for SciJava"
80+
def getEngineVersion = "3.0"
81+
def getExtensions = Arrays.asList("scala")
82+
def getLanguageName = "Scala"
83+
def getLanguageVersion = Properties.versionString
84+
def getMimeTypes = Arrays.asList("application/x-scala")
85+
def getNames = Arrays.asList("scala")
86+
87+
def getMethodCallSyntax(obj: String, m: String, args: String*) = s"$obj.$m(${args.mkString(", ")})"
88+
89+
def getOutputStatement(toDisplay: String) = s"""print("$toDisplay")"""
90+
91+
def getParameter(key: String): Object = key match {
92+
case JScriptEngine.ENGINE => getEngineName
93+
case JScriptEngine.ENGINE_VERSION => getEngineVersion
94+
case JScriptEngine.LANGUAGE => getLanguageName
95+
case JScriptEngine.LANGUAGE_VERSION => getLanguageVersion
96+
case JScriptEngine.NAME => getNames.get(0)
97+
case _ => null
98+
}
99+
100+
def getProgram(statements: String*) = statements.mkString("; ")
101+
102+
def getScriptEngine: JScriptEngine = new SciJavaScriptEngine(classPath)
103+
}
104+
}

src/main/scala/org/scijava/plugins/scripting/scala/ScalaAdaptedScriptEngineFactory.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ package org.scijava.plugins.scripting.scala
3131

3232
import org.scijava.plugins.scripting.scala.ScalaAdaptedScriptEngine
3333

34+
import java.net.URLClassLoader
3435
import java.util
3536
import javax.script.{ScriptEngine, ScriptEngineFactory}
3637

@@ -42,7 +43,7 @@ import javax.script.{ScriptEngine, ScriptEngineFactory}
4243
*/
4344
class ScalaAdaptedScriptEngineFactory extends ScriptEngineFactory:
4445

45-
private val factory = new dotty.tools.repl.ScriptEngine.Factory
46+
private val factory = new dotty.tools.repl.SciJavaScriptEngine.Factory(classPath)
4647

4748
/**
4849
* Returns an instance of the `ScalaAdaptedScriptEngine`.
@@ -64,3 +65,12 @@ class ScalaAdaptedScriptEngineFactory extends ScriptEngineFactory:
6465
override def getMethodCallSyntax(obj: String, m: String, args: String*): String =
6566
factory.getMethodCallSyntax(obj, m, args*)
6667
override def getProgram(statements: String*): String = factory.getProgram(statements*)
68+
69+
/**
70+
* Retrieves the current classpath as a string.
71+
*/
72+
def classPath: String = ClassLoader.getSystemClassLoader match
73+
case cl: URLClassLoader =>
74+
cl.getURLs.map(_.getPath).mkString(System.getProperty("path.separator"))
75+
case _ =>
76+
System.getProperty("java.class.path")

0 commit comments

Comments
 (0)