diff --git a/src/babashka/impl/classpath.clj b/src/babashka/impl/classpath.clj index a1846656..a90e5126 100644 --- a/src/babashka/impl/classpath.clj +++ b/src/babashka/impl/classpath.clj @@ -7,31 +7,37 @@ (set! *warn-on-reflection* true) (defprotocol IResourceResolver - (getResource [this path])) + (getResource [this path opts])) (deftype DirectoryResolver [path] IResourceResolver - (getResource [this resource-path] + (getResource [this resource-path {:keys [:url?]}] (let [f (io/file path resource-path)] (when (.exists f) - {:file (.getCanonicalPath f) - :source (slurp f)})))) + (if url? + (java.net.URL. (str "file:" + (.getCanonicalPath f))) + {:file (.getCanonicalPath f) + :source (slurp f)}))))) (defn path-from-jar - [^java.io.File jar-file path] + [^java.io.File jar-file path {:keys [:url?]}] (with-open [jar (JarFile. jar-file)] (let [entries (enumeration-seq (.entries jar)) entry (some (fn [^JarFile$JarFileEntry x] (let [nm (.getName x)] (when (and (not (.isDirectory x)) (= path nm)) - {:file path - :source (slurp (.getInputStream jar x))}))) entries)] + (if url? + (java.net.URL. + (str "jar:file:" (.getCanonicalPath jar-file) "!/" path)) + {:file path + :source (slurp (.getInputStream jar x))})))) entries)] entry))) (deftype JarFileResolver [path] IResourceResolver - (getResource [this resource-path] - (path-from-jar path resource-path))) + (getResource [this resource-path opts] + (path-from-jar path resource-path opts))) (defn part->entry [part] (if (str/ends-with? part ".jar") @@ -40,25 +46,25 @@ (deftype Loader [entries] IResourceResolver - (getResource [this resource-path] - (some #(getResource % resource-path) entries))) + (getResource [this resource-path opts] + (some #(getResource % resource-path opts) entries))) (defn loader [^String classpath] (let [parts (.split classpath (System/getProperty "path.separator")) entries (map part->entry parts)] (Loader. entries))) -(defn source-for-namespace [loader namespace] +(defn source-for-namespace [loader namespace opts] (let [ns-str (name namespace) ^String ns-str (munge ns-str) path (.replace ns-str "." (System/getProperty "file.separator")) paths (map #(str path %) [".bb" ".clj" ".cljc"])] - (some #(getResource loader %) paths))) + (some #(getResource loader % opts) paths))) ;;;; Scratch (comment (def l (loader "src:/Users/borkdude/.m2/repository/cheshire/cheshire/5.9.0/cheshire-5.9.0.jar")) - (source-for-namespace l 'babashka.impl.cheshire) - (:file (source-for-namespace l 'cheshire.core)) + (source-for-namespace l 'babashka.impl.cheshire nil) + (:file (source-for-namespace l 'cheshire.core nil)) ) diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 7f34a985..8bdf6cc4 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -275,17 +275,20 @@ Everything after that is bound to *command-line-args*.")) (cp/loader classpath)) load-fn (when classpath (fn [{:keys [:namespace]}] - (let [res (cp/source-for-namespace loader namespace)] + (let [res (cp/source-for-namespace loader namespace nil)] (when uberscript (swap! uberscript-sources conj (:source res))) res))) _ (when file (vars/bindRoot vars/file-var (.getCanonicalPath (io/file file)))) ctx {:aliases aliases - :namespaces (assoc namespaces 'clojure.core - (assoc core-extras - '*command-line-args* - (sci/new-dynamic-var '*command-line-args* command-line-args) - '*file* vars/file-var - '*warn-on-reflection* reflection-var)) + :namespaces (-> namespaces + (assoc 'clojure.core + (assoc core-extras + '*command-line-args* + (sci/new-dynamic-var '*command-line-args* command-line-args) + '*file* vars/file-var + '*warn-on-reflection* reflection-var)) + (assoc-in ['clojure.java.io 'resource] + #(when classpath (cp/getResource loader % {:url? true})))) :bindings bindings :env env :features #{:bb} diff --git a/test/babashka/classpath_test.clj b/test/babashka/classpath_test.clj index 24048ade..dd20b197 100644 --- a/test/babashka/classpath_test.clj +++ b/test/babashka/classpath_test.clj @@ -2,7 +2,8 @@ (:require [babashka.test-utils :as tu] [clojure.edn :as edn] - [clojure.test :as t :refer [deftest is]])) + [clojure.test :as t :refer [deftest is]] + [clojure.java.io :as io])) (defn bb [input & args] (edn/read-string (apply tu/bb (when (some? input) (str input)) (map str args)))) @@ -41,3 +42,10 @@ (require '[ns-with-error]) (catch Exception nil)) (nil? (resolve 'ns-with-error/x))")))) + +(deftest resource-test + (let [tmp-file (java.io.File/createTempFile "icon" ".png")] + (.deleteOnExit tmp-file) + (bb nil "--classpath" "logo" "-e" (format "(io/copy (io/input-stream (io/resource \"icon.png\")) (io/file \"%s\"))" (.getPath tmp-file))) + (is (= (.length (io/file "logo" "icon.png")) + (.length tmp-file)))))