Compatibility with clojure.tools.namespace.repl/refresh and clojure.java.classpath (#1479)

This commit is contained in:
Michiel Borkent 2023-02-01 21:53:52 +01:00 committed by GitHub
parent bbd1940844
commit 76e779d0d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 109 additions and 59 deletions

View file

@ -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)

View file

@ -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"}

View file

@ -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

View 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);
}
}

View file

@ -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"]

View file

@ -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"}

View file

@ -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 %))))

View file

@ -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

View file

@ -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*]

View file

@ -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"))))

View file

@ -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")