1
+ package org.utbot.common
2
+
3
+ import java.io.IOException
4
+ import java.net.URL
5
+ import java.net.URLClassLoader
6
+ import java.util.*
7
+
8
+ /* *
9
+ * [ClassLoader] implementation, that
10
+ * - first, attempts to load class/resource with [commonParent] class loader
11
+ * - next, attempts to load class/resource from `urls`
12
+ * - finally, attempts to load class/resource with `fallback` class loader
13
+ *
14
+ * More details can be found in [this post](https://medium.com/@isuru89/java-a-child-first-class-loader-cbd9c3d0305).
15
+ */
16
+ class FallbackClassLoader (
17
+ urls : Array <URL >,
18
+ fallback : ClassLoader ,
19
+ private val commonParent : ClassLoader = fallback.parent,
20
+ ) : URLClassLoader(urls, fallback) {
21
+
22
+ @Throws(ClassNotFoundException ::class )
23
+ override fun loadClass (name : String , resolve : Boolean ): Class <* >? {
24
+ // has the class loaded already?
25
+ var loadedClass = findLoadedClass(name)
26
+ if (loadedClass == null ) {
27
+ try {
28
+ loadedClass = commonParent.loadClass(name)
29
+ } catch (ex: ClassNotFoundException ) {
30
+ // class not found in common parent loader... silently skipping
31
+ }
32
+ try {
33
+ // find the class from given jar urls as in first constructor parameter.
34
+ if (loadedClass == null ) {
35
+ loadedClass = findClass(name)
36
+ }
37
+ } catch (e: ClassNotFoundException ) {
38
+ // class is not found in the given urls.
39
+ // Let's try it in fallback classloader.
40
+ // If class is still not found, then this method will throw class not found ex.
41
+ loadedClass = super .loadClass(name, resolve)
42
+ }
43
+ }
44
+ if (resolve) { // marked to resolve
45
+ resolveClass(loadedClass)
46
+ }
47
+ return loadedClass
48
+ }
49
+
50
+ @Throws(IOException ::class )
51
+ override fun getResources (name : String ): Enumeration <URL > {
52
+ val allRes: MutableList <URL > = LinkedList <URL >()
53
+
54
+ // load resources from common parent loader
55
+ val commonParentResources: Enumeration <URL >? = commonParent.getResources(name)
56
+ if (commonParentResources != null ) {
57
+ while (commonParentResources.hasMoreElements()) {
58
+ allRes.add(commonParentResources.nextElement())
59
+ }
60
+ }
61
+
62
+ // load resource from this classloader
63
+ val thisRes: Enumeration <URL >? = findResources(name)
64
+ if (thisRes != null ) {
65
+ while (thisRes.hasMoreElements()) {
66
+ allRes.add(thisRes.nextElement())
67
+ }
68
+ }
69
+
70
+ // then try finding resources from fallback classloaders
71
+ val parentRes: Enumeration <URL >? = super .findResources(name)
72
+ if (parentRes != null ) {
73
+ while (parentRes.hasMoreElements()) {
74
+ allRes.add(parentRes.nextElement())
75
+ }
76
+ }
77
+ return object : Enumeration <URL > {
78
+ var it: Iterator <URL > = allRes.iterator()
79
+ override fun hasMoreElements (): Boolean {
80
+ return it.hasNext()
81
+ }
82
+
83
+ override fun nextElement (): URL {
84
+ return it.next()
85
+ }
86
+ }
87
+ }
88
+
89
+ override fun getResource (name : String ): URL ? {
90
+ var res: URL ? = commonParent.getResource(name)
91
+ if (res == = null ) {
92
+ res = findResource(name)
93
+ }
94
+ if (res == = null ) {
95
+ res = super .getResource(name)
96
+ }
97
+ return res
98
+ }
99
+ }
0 commit comments