简体   繁体   中英

Is it possible to have Nashorn load scripts from classpath?

Is it possible to have Nashorn's load method use the project's classpath when resolving URIs?

Here's what I'm attempting to do:

(defn create-engine
  "Creates a new nashorn script engine and loads dependencies into its context."
  [dependencies]
  (let [nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")
        scripts (map #(str "load('" % "');") dependencies)]
    (.eval nashorn "var global = this;")
    (doseq [script scripts] (.eval nashorn script))
    nashorn))

(def app "public/javascripts/app.js") ; in /resouces, on classpath


; resulting exception:
clojure.lang.Compiler$CompilerException: 
javax.script.ScriptException: TypeError: 
Cannot load script from public/javascripts/app.js in <eval> at line number 1

Nashorn's load() method actually supports taking a URL prefixed with classpath: . It will load the file following that prefix from the classpath. Check out the source - http://cr.openjdk.java.net/~sundar/8025629/webrev.01/src/jdk/nashorn/internal/runtime/Context.java.html line 502.

Absolute path should always start with a slash, "/public/javascripts/app.js" , but I'm not sure if load() loads off the classpath, if it doesn't you may have to use eval(Reader) method and construct the reader yourself

EDIT:

You need to use the opening slash for classpath resources if the path is absolute within the jar. No slash means relative to the particular class you're calling this from. You should get an InputStream for the resource and eval a reader, in Java it would look like this:

nashorn.eval (new InputStreamReader (getClass().getResourceAsStream("/public/javascripts/app.js")));

I don't want to translate this to clojure since that's bound to end in failure.

EDIT2:

Well then here's an attempt then:

(defn create-engine
  "Creates a new nashorn script engine and loads dependencies into its context."
  [dependencies]
  (let [nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")]
    (.eval nashorn "var global = this;")
    (doseq [dependency dependencies] (.eval nashorn (new InputStreamReader (.getResourceAsStream String dependency))))
    nashorn))

I shall not be held responsible if this starts the nuclear war or something

You should use clojure.java.io/resource

(def nashorn (.. (javax.script.ScriptEngineManager.) (getEngineByName "nashorn")))
(.eval nashorn (clojure.java.io/reader (clojure.java.io/resource "jvm-npm.js")))

Make sure the resource folder is configured in your lein project:

:resource-paths ["src/resources"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM