All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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