-
Notifications
You must be signed in to change notification settings - Fork 9
/
jdk_sources.clj
107 lines (96 loc) · 3.44 KB
/
jdk_sources.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(ns cider.enrich-classpath.jdk-sources
(:require
[cider.enrich-classpath.jdk :as jdk]
[cider.enrich-classpath.locks :refer [locking-file]]
[cider.enrich-classpath.logging :refer [warn]]
[cider.enrich-classpath.xdg :as xdg]
[clojure.java.io :as io]
[clojure.string :as string])
(:import
(java.io File FileOutputStream)
(java.net JarURLConnection URL)
(java.util.zip ZipInputStream)))
(defmacro while-let
{:style/indent 1}
[[sym expr] & body]
`(loop [~sym ~expr]
(when ~sym
~@body
(recur ~expr))))
(defn jdk-find [f]
(let [home (io/file (System/getProperty "java.home"))
parent (.getParentFile home)
paths [(io/file home f)
(io/file home "lib" f)
(io/file parent f)
(io/file parent "lib" f)]
v (some->> paths
(filter #(.canRead ^File %))
first
str)]
(when-not v
(warn :cider.enrich-classpath/no-jdk-sources-found))
v))
(def base-prefix "mx.cider")
(defn external-resource ^URL [path]
(when-let [obj (io/resource path)]
(when-not (string/includes? (str obj) base-prefix)
obj)))
(defn java-path->zip-path [path]
(some-> (external-resource path)
^JarURLConnection (. openConnection)
.getJarFileURL
io/as-file
str))
(def jdk-sources
(delay
(or (java-path->zip-path "java.base/java/lang/Object.java") ;; JDK9+
(java-path->zip-path "java/lang/Object.java") ;; JDK8-
(jdk-find "src.zip"))))
(def zip-separator
;; NOTE - does not necessarily equal `File/separator`:
#"/")
(defn uncompress [^String prefix-path target]
(let [zis (-> target io/input-stream ZipInputStream.)]
(while-let [entry (-> zis .getNextEntry)]
(let [size (-> entry .getSize)
bytes (byte-array 1024)
dest (->> entry .getName (io/file prefix-path))
dir (-> entry .getName (string/split zip-separator) butlast)
_ (->> (string/join File/separator dir)
(File. prefix-path)
.mkdirs)
output (FileOutputStream. dest)]
(try
(loop [len (-> zis (.read bytes))]
(when (pos? len)
(-> output (.write bytes 0 len))
(recur (-> zis (.read bytes)))))
(finally
(-> output .close)))))))
(defn uncompressed-sources-dir []
(let [id (jdk/digits-str)]
(-> xdg/cache-root
(io/file base-prefix "unzipped-jdk-sources" id)
str)))
(defn unzipped-jdk-source []
(let [dir (uncompressed-sources-dir)
file (-> dir io/file (doto .mkdirs))
lockfile (io/file file ".lock")]
(locking-file (str lockfile)
(fn [_ _]
(when (->> file
file-seq
(remove (some-fn #{file lockfile}
(fn [^File candidate]
;; files such as .DS_Store:
(-> candidate .getName (string/starts-with? ".")))))
empty?)
(when-let [choice @jdk-sources]
(-> file .mkdirs)
(uncompress dir choice)))))
dir))
(defn resources-to-add []
(cond-> []
(and @jdk-sources jdk/jdk8?) (conj (unzipped-jdk-source))
@jdk-sources (conj @jdk-sources)))