Allow eval-in-project to exit the VM.

Ugh; ant's permissions are hairy.
This commit is contained in:
Phil Hagelberg 2010-05-19 23:13:18 -10:00
parent c84b717705
commit b969b6cf9e
2 changed files with 45 additions and 20 deletions

View file

@ -7,12 +7,33 @@
[clojure.contrib.io :only [file]]
[clojure.contrib.find-namespaces :only [find-namespaces-in-dir]])
(:refer-clojure :exclude [compile])
(:import org.apache.tools.ant.taskdefs.Java
java.lang.management.ManagementFactory
(org.apache.tools.ant.types Environment$Variable)))
(:import [org.apache.tools.ant.taskdefs Java]
[java.lang.management ManagementFactory]
[org.apache.tools.ant.types Environment$Variable
Permissions Permissions$Permission]))
(declare compile)
(def perm-list [{:class "java.lang.RuntimePermission"
:name "*"}
{:class "java.lang.reflect.ReflectPermission"
:name "*"}
{:class "java.io.FilePermission"
:name "<<ALL FILES>>"
:actions "read,write,delete,execute"}
{:class "java.util.PropertyPermission"
:name "*"
:actions "read,write"}])
;; This is ridiculous, but you can't exit the VM without it.
(defn add-perms [java]
(let [perms (.createPermissions java)]
(doseq [p perm-list]
(.addConfiguredGrant perms (doto (Permissions$Permission.)
(.setClass (:class p))
(.setName (:name p))
(.setActions (str (:actions p))))))))
(defn compilable-namespaces
"Returns a seq of the namespaces that are compilable, regardless of whether
their class files are present and up-to-date."
@ -84,6 +105,22 @@
(concat (.getInputArguments (ManagementFactory/getRuntimeMXBean))
(:jvm-opts project)))
(defn set-args [project java form native-path]
(when (or (:fork project) (:jvm-opts project)
(= :macosx (get-os)) native-path)
(.setFork java true)
(doseq [arg (get-jvm-args project)]
(when-not (re-matches #"^-Xbootclasspath.+" arg)
(.setValue (.createJvmarg java) arg))))
(.setClassname java "clojure.main")
(.setValue (.createArg java) "-e")
(let [cp (str (.getClasspath (.getCommandLine java)))
form `(do (def ~'*classpath* ~cp)
(set! ~'*warn-on-reflection*
~(:warn-on-reflection project))
~form)]
(.setValue (.createArg java) (prn-str form))))
(defn eval-in-project
"Executes form in an isolated classloader with the classpath and compile path
set correctly for the project. Pass in a handler function to have it called
@ -112,23 +149,11 @@
:default native-path)))))
(.setClasspath java (apply make-path (get-classpath project)))
(.setFailonerror java true)
(when (or (:fork project) (:jvm-opts project)
(= :macosx (get-os)) native-path)
(.setFork java true)
(doseq [arg (get-jvm-args project)]
(when-not (re-matches #"^-Xbootclasspath.+" arg)
(.setValue (.createJvmarg java) arg))))
(.setClassname java "clojure.main")
(.setValue (.createArg java) "-e")
(let [cp (str (.getClasspath (.getCommandLine java)))
form `(do (def ~'*classpath* ~cp)
(set! ~'*warn-on-reflection*
~(:warn-on-reflection project))
~form)]
(.setValue (.createArg java) (prn-str form)))
(add-perms java)
(set-args project java form native-path)
;; to allow plugins and other tasks to customize
(when handler (handler java))
(.executeJava java)))
(.execute java)))
(defn compile
"Ahead-of-time compile the project. Looks for all namespaces under src/

View file

@ -18,14 +18,14 @@ Leiningen TODOs
** DONE upgrade task (patch submitted)
** DONE doc generation (autodoc plugin)
* For 1.2.0
** TODO System/exit appropriately when testing based on pass/fail (abedra)
*** Needs to set permissions with the ant API's Java task
** TODO repl task exits on some projects (sample) (patch for this?)
** TODO document all known project.clj keys
** TODO walk up the filesystem to find project.clj
** TODO a list of dirs to include in the jar when building
** TODO set arbitrary jar metadata
** TODO specify min. lein version in project.clj
** DONE System/exit appropriately when testing based on pass/fail (abedra)
*** Needs to set permissions with the ant API's Java task
** DONE allow *warn-on-reflection* to be turned on in project.clj
** DONE make org.clojure implied for clojure/contrib deps
** DONE better way to force setFork in eval-in-project