
name.remal.java.lang.ClassLoader.kt Maven / Gradle / Ivy
package name.remal
import name.remal.reflection.ClassLoaderUtils
import java.io.File
import java.lang.Thread.currentThread
import java.net.URL
import java.net.URLClassLoader
import java.nio.file.Path
fun ClassLoader.getPackageOrNull(packageName: String) = ClassLoaderUtils.getPackageOrNull(this, packageName)
fun ClassLoader.tryLoadClass(className: String, initialize: Boolean = true): Class<*>? = try {
Class.forName(className, initialize, this)
} catch (ignored: ClassNotFoundException) {
null
}
fun ClassLoader.addURL(vararg urls: URL) = ClassLoaderUtils.addURLsToClassLoader(this, *urls)
fun ClassLoader.addURL(vararg files: File) = addURL(*files.map { it.toURI().toURL() }.toTypedArray())
fun ClassLoader.addURL(vararg paths: Path) = addURL(*paths.map { it.toUri().toURL() }.toTypedArray())
fun ClassLoader.forInstantiated(type: Class, implementationType: Class, action: (T) -> R): R {
if (!type.isAssignableFrom(implementationType) || type == implementationType) throw IllegalArgumentException("$implementationType is not subtype of $type");
val sourceURL = implementationType.protectionDomain?.codeSource?.location ?: throw IllegalStateException("$implementationType: null == protectionDomain?.codeSource?.location")
object : URLClassLoader(arrayOf(sourceURL), this) {
override fun loadClass(name: String, resolve: Boolean): Class<*> {
synchronized(getClassLoadingLock(name)) {
var loadedClass: Class<*>? = findLoadedClass(name)
if (null == loadedClass) loadedClass = loadFromSystem(name)
if (null == loadedClass) {
if (implementationType.name == name) {
loadedClass = loadFromThis(name)
} else {
loadedClass = loadFromParent(name)
}
}
if (null == loadedClass) throw ClassNotFoundException(name)
if (resolve) resolveClass(loadedClass)
return loadedClass
}
}
private fun loadFromSystem(name: String): Class<*>? {
try {
return findSystemClass(name)
} catch (ignored: ClassNotFoundException) {
return null
}
}
private fun loadFromParent(name: String): Class<*>? {
try {
return parent.loadClass(name)
} catch (ignored: ClassNotFoundException) {
return null
}
}
private fun loadFromThis(name: String): Class<*>? {
try {
return findClass(name)
} catch (ignored: ClassNotFoundException) {
return null
}
}
}
.use { classLoader ->
val prevContextClassLoader = currentThread().contextClassLoader
currentThread().contextClassLoader = classLoader
try {
val implementation: T = classLoader.loadClass(implementationType.name).newInstance().uncheckedCast()
return action(implementation)
} finally {
currentThread().contextClassLoader = prevContextClassLoader
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy