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

kotlin.script.experimental.jvm.impl.KJvmCompiledModule.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package kotlin.script.experimental.jvm.impl

import java.io.File
import java.io.InputStream
import java.net.URL
import java.net.URLClassLoader
import java.util.*

interface KJvmCompiledModule {
    fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader
}

interface KJvmCompiledModuleInMemory : KJvmCompiledModule {
    val compilerOutputFiles: Map
}

class KJvmCompiledModuleFromClassPath(val classpath: Collection) : KJvmCompiledModule {

    override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader =
        URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), baseClassLoader)
}

class KJvmCompiledModuleFromClassLoader(val moduleClassLoader: ClassLoader) : KJvmCompiledModule {

    override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader =
        if (baseClassLoader == null) moduleClassLoader
        else DualClassLoader(moduleClassLoader, baseClassLoader)
}

internal class DualClassLoader(fallbackLoader: ClassLoader, parentLoader: ClassLoader?) :
    ClassLoader(singleClassLoader(fallbackLoader, parentLoader) ?: parentLoader) {

    internal class Wrapper(parent: ClassLoader) : ClassLoader(parent) {
        fun openFindResources(name: String): Enumeration = super.findResources(name)
        fun openFindResource(name: String): URL? = super.findResource(name)
    }

    companion object {
        private fun singleClassLoader(fallbackLoader: ClassLoader, parentLoader: ClassLoader?): ClassLoader? {
            tailrec fun ClassLoader.isAncestorOf(other: ClassLoader?): Boolean = when {
                other == null -> false
                this === other -> true
                else -> isAncestorOf(other.parent)
            }

            return when {
                parentLoader == null -> fallbackLoader
                parentLoader.isAncestorOf(fallbackLoader) -> fallbackLoader
                fallbackLoader.isAncestorOf(parentLoader) -> parentLoader
                else -> null
            }
        }
    }

    internal val fallbackClassLoader: Wrapper? =
        if (/* optimization */ parentLoader == null || singleClassLoader(fallbackLoader, parentLoader) != null) null
        else Wrapper(fallbackLoader)

    override fun findClass(name: String): Class<*> = try {
        super.findClass(name)
    } catch (e: ClassNotFoundException) {
        fallbackClassLoader?.loadClass(name) ?: throw e
    }

    override fun getResourceAsStream(name: String): InputStream? =
        super.getResourceAsStream(name) ?: fallbackClassLoader?.getResourceAsStream(name)

    override fun findResources(name: String): Enumeration =
        if (fallbackClassLoader == null) super.findResources(name)
        else Collections.enumeration(super.findResources(name).toList() + fallbackClassLoader.openFindResources(name).asSequence())

    override fun findResource(name: String): URL? =
        super.findResource(name) ?: fallbackClassLoader?.openFindResource(name)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy