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