Compatibility with clojure.tools.namespace.repl/refresh and clojure.java.classpath (#1479)
This commit is contained in:
parent
bbd1940844
commit
76e779d0d3
17 changed files with 109 additions and 59 deletions
|
|
@ -10,6 +10,7 @@ A preview of the next release can be installed from
|
|||
## Unreleased
|
||||
|
||||
- [#1473](https://github.com/babashka/babashka/issues/1473): make relative paths in bb.edn resolve relative to it ([@lispyclouds](https://github.com/lispyclouds))
|
||||
- Compatibility with `clojure.tools.namespace.repl/refresh` and `clojure.java.classpath`
|
||||
|
||||
## 1.1.172 (2023-01-23)
|
||||
|
||||
|
|
|
|||
4
deps.edn
4
deps.edn
|
|
@ -17,10 +17,10 @@
|
|||
"depstar/src" "process/src"
|
||||
"deps.clj/src" "deps.clj/resources"
|
||||
"resources" "sci/resources"
|
||||
"reify/src"],
|
||||
"impl-java/src"],
|
||||
:deps {org.clojure/clojure {:mvn/version "1.11.1"},
|
||||
org.babashka/sci {:local/root "sci"}
|
||||
org.babashka/babashka.impl.reify {:mvn/version "0.1.5"}
|
||||
org.babashka/babashka.impl.java {:mvn/version "0.1.6"}
|
||||
org.babashka/sci.impl.types {:mvn/version "0.0.2"}
|
||||
babashka/babashka.curl {:local/root "babashka.curl"}
|
||||
babashka/fs {:local/root "fs"}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
(:require [build.reify2 :as reify2]
|
||||
[clojure.tools.build.api :as b]))
|
||||
|
||||
(def lib 'org.babashka/babashka.impl.reify)
|
||||
(def version "0.1.5")
|
||||
(def lib 'org.babashka/babashka.impl.java)
|
||||
(def version "0.1.6")
|
||||
(def class-dir "target/classes")
|
||||
(def basis (b/create-basis {:project "deps.edn"}))
|
||||
(def jar-file (format "target/%s-%s.jar" (name lib) version))
|
||||
|
|
@ -14,7 +14,13 @@
|
|||
(defn gen-classes [_]
|
||||
(reify2/gen-classes nil))
|
||||
|
||||
(defn compile-java [_]
|
||||
(b/javac {:src-dirs ["src-java"]
|
||||
:class-dir class-dir
|
||||
:basis basis}))
|
||||
|
||||
(defn jar [_]
|
||||
(compile-java nil)
|
||||
(gen-classes nil)
|
||||
(b/write-pom {:class-dir class-dir
|
||||
:lib lib
|
||||
16
impl-java/src-java/babashka/impl/URLClassLoader.java
Normal file
16
impl-java/src-java/babashka/impl/URLClassLoader.java
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package babashka.impl;
|
||||
|
||||
public class URLClassLoader extends java.net.URLClassLoader {
|
||||
|
||||
public URLClassLoader(java.net.URL[] urls) {
|
||||
super(urls);
|
||||
}
|
||||
|
||||
public URLClassLoader(java.net.URL[] urls, java.net.URLClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
public void _addURL(java.net.URL url) {
|
||||
super.addURL(url);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
"babashka.core/src"
|
||||
"babashka.nrepl/src" "depstar/src" "process/src"
|
||||
"deps.clj/src" "deps.clj/resources"
|
||||
"reify/src"]
|
||||
"impl-java/src"]
|
||||
;; for debugging Reflector.java code:
|
||||
;; :java-source-paths ["sci/reflector/src-java"]
|
||||
:java-source-paths ["src-java"]
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
[nrepl/bencode "1.1.0"]
|
||||
[borkdude/sci.impl.reflector "0.0.1"]
|
||||
[org.babashka/sci.impl.types "0.0.2"]
|
||||
[org.babashka/babashka.impl.reify "0.1.5"]
|
||||
[org.babashka/babashka.impl.java "0.1.6"]
|
||||
[org.clojure/core.async "1.6.673"]
|
||||
[org.clojure/test.check "1.1.1"]
|
||||
[com.github.clj-easy/graal-build-time "0.1.0"]
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
"depstar/src" "process/src"
|
||||
"deps.clj/src" "deps.clj/resources"
|
||||
"resources" "sci/resources"
|
||||
"reify/src"],
|
||||
"impl-java/src"],
|
||||
:deps {org.clojure/clojure {:mvn/version "1.11.1"},
|
||||
org.babashka/sci {:local/root "sci"}
|
||||
org.babashka/babashka.impl.reify {:mvn/version "0.1.5"}
|
||||
org.babashka/babashka.impl.java {:mvn/version "0.1.6"}
|
||||
org.babashka/sci.impl.types {:mvn/version "0.0.2"}
|
||||
babashka/babashka.curl {:local/root "babashka.curl"}
|
||||
babashka/fs {:local/root "fs"}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,9 @@
|
|||
clojure.lang.RT
|
||||
{:methods [{:name "aget"}
|
||||
{:name "aset"}
|
||||
{:name "aclone"}]}
|
||||
{:name "aclone"}
|
||||
;; we expose this via the Compiler/LOADER dynamic var
|
||||
{:name "baseLoader"}]}
|
||||
clojure.lang.Compiler
|
||||
{:fields [{:name "specials"}
|
||||
{:name "CHAR_MAP"}]}
|
||||
|
|
@ -140,7 +142,18 @@
|
|||
{:methods [{:name "hasNext"}
|
||||
{:name "next"}]}
|
||||
java.util.TimeZone
|
||||
{:methods [{:name "getTimeZone"}]}})
|
||||
{:methods [{:name "getTimeZone"}]}
|
||||
java.net.URLClassLoader
|
||||
{:methods [{:name "close"}
|
||||
{:name "findResource"}
|
||||
{:name "findResources"}
|
||||
{:name "getResourceAsStream"}
|
||||
{:name "getURLs"}]}
|
||||
java.lang.ClassLoader
|
||||
{:methods [{:name "getResource"}
|
||||
{:name "getResources"}
|
||||
{:name "getResourceAsStream"}
|
||||
{:name "getParent"}]}})
|
||||
|
||||
(def custom-map
|
||||
(cond->
|
||||
|
|
@ -561,7 +574,6 @@
|
|||
java.lang.LinkageError
|
||||
java.lang.ThreadDeath
|
||||
java.lang.VirtualMachineError
|
||||
java.net.URLClassLoader
|
||||
java.sql.Timestamp
|
||||
java.util.concurrent.TimeoutException
|
||||
java.util.Collection
|
||||
|
|
@ -630,6 +642,10 @@
|
|||
(instance? sci.impl.types.IReified v)
|
||||
(first (t/getInterfaces v))
|
||||
;; fix for #1061
|
||||
(instance? java.net.URLClassLoader v)
|
||||
java.net.URLClassLoader
|
||||
(instance? java.lang.ClassLoader v)
|
||||
java.lang.ClassLoader
|
||||
(instance? java.io.Closeable v)
|
||||
java.io.Closeable
|
||||
(instance? java.nio.file.attribute.BasicFileAttributes v)
|
||||
|
|
@ -765,8 +781,9 @@
|
|||
(sort-by :name)
|
||||
(vec)))
|
||||
|
||||
(defn all-classes []
|
||||
(defn all-classes
|
||||
"Returns every java.lang.Class instance Babashka supports."
|
||||
[]
|
||||
(->> (reflection-file-entries)
|
||||
(map :name)
|
||||
(map #(Class/forName %))))
|
||||
|
|
|
|||
|
|
@ -10,30 +10,46 @@
|
|||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(defprotocol IResourceResolver
|
||||
(getResource [this paths opts]))
|
||||
|
||||
(deftype Loader [class-loader]
|
||||
IResourceResolver
|
||||
(getResource [_ resource-paths url?]
|
||||
(some (fn [resource]
|
||||
(when-let [^java.net.URL res (.findResource ^java.net.URLClassLoader class-loader resource)]
|
||||
(if url?
|
||||
res
|
||||
{:file (if (= "jar" (.getProtocol res))
|
||||
resource
|
||||
(.getFile res))
|
||||
:source (slurp res)})))
|
||||
resource-paths)))
|
||||
(defn getResource [^babashka.impl.URLClassLoader class-loader resource-paths url?]
|
||||
(some (fn [resource]
|
||||
(when-let [^java.net.URL res (.findResource class-loader resource)]
|
||||
(if url?
|
||||
res
|
||||
{:file (if (= "jar" (.getProtocol res))
|
||||
resource
|
||||
(.getFile res))
|
||||
:source (slurp res)})))
|
||||
resource-paths))
|
||||
|
||||
(def path-sep (System/getProperty "path.separator"))
|
||||
|
||||
(defn ->url [^String s]
|
||||
(defn ->url ^java.net.URL [^String s]
|
||||
(.toURL (java.io.File. s)))
|
||||
|
||||
(defn loader [^String classpath]
|
||||
(let [parts (.split classpath path-sep)]
|
||||
(Loader. (java.net.URLClassLoader/newInstance (into-array java.net.URL (map ->url parts))))))
|
||||
(defn new-loader ^babashka.impl.URLClassLoader
|
||||
([paths]
|
||||
(babashka.impl.URLClassLoader. (into-array java.net.URL (map ->url paths)))))
|
||||
|
||||
(def ^babashka.impl.URLClassLoader the-url-loader (delay (new-loader [])))
|
||||
|
||||
(defn add-classpath
|
||||
"Adds extra-classpath, a string as for example returned by clojure
|
||||
-Spath, to the current classpath."
|
||||
[^String extra-classpath]
|
||||
(let [paths (.split extra-classpath path-sep)
|
||||
paths (map ->url paths)
|
||||
loader @the-url-loader]
|
||||
(run! (fn [path]
|
||||
(._addURL ^babashka.impl.URLClassLoader loader path)
|
||||
loader)
|
||||
paths)
|
||||
;; (run! prn (.getURLs the-url-loader))
|
||||
(System/setProperty "java.class.path"
|
||||
(let [system-cp (System/getProperty "java.class.path")]
|
||||
(-> (cond-> system-cp
|
||||
(not (str/blank? system-cp)) (str path-sep))
|
||||
(str extra-classpath)))))
|
||||
nil)
|
||||
|
||||
(defn resource-paths [namespace]
|
||||
(let [ns-str (name namespace)
|
||||
|
|
@ -55,21 +71,6 @@
|
|||
(.getValue "Main-Class")
|
||||
(demunge))))
|
||||
|
||||
(def cp-state (atom nil))
|
||||
|
||||
(defn add-classpath
|
||||
"Adds extra-classpath, a string as for example returned by clojure
|
||||
-Spath, to the current classpath."
|
||||
[extra-classpath]
|
||||
(swap! cp-state
|
||||
(fn [{:keys [:cp]}]
|
||||
(let [new-cp
|
||||
(if-not cp extra-classpath
|
||||
(str cp path-sep extra-classpath))]
|
||||
{:loader (loader new-cp)
|
||||
:cp new-cp})))
|
||||
nil)
|
||||
|
||||
(defn split-classpath
|
||||
"Returns the classpath as a seq of strings, split by the platform
|
||||
specific path separator."
|
||||
|
|
@ -78,10 +79,12 @@
|
|||
(defn get-classpath
|
||||
"Returns the current classpath as set by --classpath, BABASHKA_CLASSPATH and add-classpath."
|
||||
[]
|
||||
(:cp @cp-state))
|
||||
(let [cp (System/getProperty "java.class.path")]
|
||||
(when-not (str/blank? cp)
|
||||
cp)))
|
||||
|
||||
(defn resource
|
||||
(^URL [path] (when-let [st @cp-state] (resource (:loader st) path)))
|
||||
(^URL [path] (resource @the-url-loader path))
|
||||
(^URL [loader path]
|
||||
(if (str/starts-with? path "/") nil ;; non-relative paths always return nil
|
||||
(getResource loader [path] true))))
|
||||
|
|
@ -101,4 +104,3 @@
|
|||
(def l (loader cp))
|
||||
(source-for-namespace l 'babashka.impl.cheshire nil)
|
||||
(time (:file (source-for-namespace l 'cheshire.core nil)))) ;; 20ms -> 2.25ms
|
||||
|
||||
|
|
|
|||
|
|
@ -781,7 +781,8 @@ Use bb run --help to show this help output.
|
|||
env-os-arch-present? (not= env-os-arch sys-os-arch))))
|
||||
|
||||
(defn exec [cli-opts]
|
||||
(binding [*unrestricted* true]
|
||||
(with-bindings {#'*unrestricted* true
|
||||
clojure.lang.Compiler/LOADER @cp/the-url-loader}
|
||||
(sci/binding [core/warn-on-reflection @core/warn-on-reflection
|
||||
core/unchecked-math @core/unchecked-math
|
||||
core/data-readers @core/data-readers
|
||||
|
|
@ -837,8 +838,7 @@ Use bb run --help to show this help output.
|
|||
_ (when jar
|
||||
(cp/add-classpath jar))
|
||||
load-fn (fn [{:keys [:namespace :reload]}]
|
||||
(let [{:keys [loader]}
|
||||
@cp/cp-state]
|
||||
(let [loader @cp/the-url-loader]
|
||||
(or
|
||||
(when ;; ignore built-in namespaces when uberscripting, unless with :reload
|
||||
(and uberscript
|
||||
|
|
@ -884,7 +884,7 @@ Use bb run --help to show this help output.
|
|||
nil))))
|
||||
main (if (and jar (not main))
|
||||
(when-let [res (cp/getResource
|
||||
(cp/loader jar)
|
||||
(cp/new-loader [jar])
|
||||
["META-INF/MANIFEST.MF"] {:url? true})]
|
||||
(cp/main-ns res))
|
||||
main)
|
||||
|
|
@ -934,7 +934,7 @@ Use bb run --help to show this help output.
|
|||
:debug debug
|
||||
:preloads preloads
|
||||
:init init
|
||||
:loader (:loader @cp/cp-state)}))))
|
||||
:loader @cp/the-url-loader}))))
|
||||
expression (str/join " " expressions) ;; this might mess with the locations...
|
||||
exit-code
|
||||
;; handle preloads
|
||||
|
|
@ -948,7 +948,7 @@ Use bb run --help to show this help output.
|
|||
:debug debug
|
||||
:preloads preloads
|
||||
:init init
|
||||
:loader (:loader @cp/cp-state)})))))
|
||||
:loader @cp/the-url-loader})))))
|
||||
nil))
|
||||
exit-code
|
||||
;; handle --init
|
||||
|
|
@ -961,7 +961,7 @@ Use bb run --help to show this help output.
|
|||
:debug debug
|
||||
:preloads preloads
|
||||
:init init
|
||||
:loader (:loader @cp/cp-state)}))))
|
||||
:loader @cp/the-url-loader}))))
|
||||
nil))
|
||||
;; socket REPL is start asynchronously. when no other args are
|
||||
;; provided, a normal REPL will be started as well, which causes the
|
||||
|
|
@ -1020,7 +1020,7 @@ Use bb run --help to show this help output.
|
|||
(error-handler e {:expression expression
|
||||
:debug debug
|
||||
:preloads preloads
|
||||
:loader (:loader @cp/cp-state)}))))
|
||||
:loader @cp/the-url-loader}))))
|
||||
clojure [nil (if-let [proc (bdeps/clojure command-line-args)]
|
||||
(-> @proc :exit)
|
||||
0)]
|
||||
|
|
@ -1080,7 +1080,7 @@ Use bb run --help to show this help output.
|
|||
abs-path #(-> % io/file .getAbsolutePath)
|
||||
bb-edn-file (cond
|
||||
config (when (fs/exists? config) (abs-path config))
|
||||
jar (some-> jar cp/loader (cp/resource "META-INF/bb.edn") .toString)
|
||||
jar (some-> [jar] cp/new-loader (cp/resource "META-INF/bb.edn") .toString)
|
||||
:else (when (fs/exists? "bb.edn") (abs-path "bb.edn")))
|
||||
bb-edn (when (or bb-edn-file merge-deps)
|
||||
(when bb-edn-file (System/setProperty "babashka.config" bb-edn-file))
|
||||
|
|
@ -1099,6 +1099,7 @@ Use bb run --help to show this help output.
|
|||
(vreset! common/bb-edn edn)))
|
||||
;; _ (.println System/err (str bb-edn))
|
||||
min-bb-version (:min-bb-version bb-edn)]
|
||||
(System/setProperty "java.class.path" "")
|
||||
(when min-bb-version
|
||||
(when-not (satisfies-min-version? min-bb-version)
|
||||
(binding [*out* *err*]
|
||||
|
|
|
|||
|
|
@ -70,3 +70,10 @@
|
|||
(str/trim
|
||||
(tu/bb nil "--classpath" "test-resources/babashka/src_for_classpath_test/foo.jar"
|
||||
"(pos? (count (slurp (io/resource \"foo.clj\")))) "))))))
|
||||
|
||||
(deftest classloader-test
|
||||
(let [url
|
||||
(tu/bb nil "--classpath" "test-resources/babashka/src_for_classpath_test/foo.jar"
|
||||
"(first (map str (.getURLs (clojure.lang.RT/baseLoader))))")]
|
||||
(is (str/includes? url "file:"))
|
||||
(is (str/includes? url "foo.jar"))))
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
(System/exit 1)))))
|
||||
|
||||
(defn bb-jvm [input-or-opts & args]
|
||||
(reset! cp/cp-state nil)
|
||||
(alter-var-root #'cp/the-url-loader (constantly (delay (cp/new-loader []))))
|
||||
(reset! main/env {})
|
||||
(vreset! common/bb-edn nil)
|
||||
(System/clearProperty "babashka.config")
|
||||
|
|
|
|||
Loading…
Reference in a new issue