-
Notifications
You must be signed in to change notification settings - Fork 0
/
classloader.clj
59 lines (44 loc) · 1.79 KB
/
classloader.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
(ns finite-cache.classloader
(:require [dynapath.util :as dynapath])
(:import (clojure.lang DynamicClassLoader RT)
(java.net URL)))
(defonce url-mapping (atom #{}))
(defonce shared-context-classloader
(delay
(or
(when-let [base-loader (RT/baseLoader)]
(when (instance? DynamicClassLoader base-loader)
base-loader))
(DynamicClassLoader. (.getContextClassLoader (Thread/currentThread))))))
(defn- has-classloader-as-ancestor?
[^ClassLoader classloader, ^ClassLoader ancestor]
(cond
(identical? classloader ancestor) true
classloader (recur (.getParent classloader) ancestor)
:else false))
(defn- has-shared-context-classloader-as-ancestor?
[^ClassLoader classloader]
(has-classloader-as-ancestor? classloader @shared-context-classloader))
(defn ^ClassLoader the-classloader
[]
(or
(let [current-thread-context-classloader (.getContextClassLoader (Thread/currentThread))]
(when (has-shared-context-classloader-as-ancestor? current-thread-context-classloader)
current-thread-context-classloader))
(let [shared-classloader @shared-context-classloader]
(.setContextClassLoader (Thread/currentThread) shared-classloader)
shared-classloader)))
(defn- classloader-hierarchy
[^ClassLoader classloader]
(reverse (take-while some? (iterate #(.getParent ^ClassLoader %) classloader))))
(defn the-top-level-classloader
(^DynamicClassLoader []
(the-top-level-classloader (the-classloader)))
(^DynamicClassLoader [^DynamicClassLoader classloader]
(some #(when (instance? DynamicClassLoader %) %)
(classloader-hierarchy classloader))))
(defn add-to-classpath!
[^URL url]
(when-not (@url-mapping url)
(swap! url-mapping conj url)
(assert (dynapath/add-classpath-url (the-top-level-classloader) url))))