From 9bf55d81ca04d2cd96fea4c5950de9c7e3a61d19 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Thu, 21 Feb 2019 14:14:00 +0300 Subject: [PATCH] Making kts-compiler able to dig out the ClassPath from the intellij `PluginClassLoader` --- .../experimental/jvm/util/jvmClasspathUtil.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt index 0826dbd6131..3a52c561728 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt @@ -43,7 +43,7 @@ internal const val KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY = "kotlin.script.runtime.j private val validClasspathFilesExtensions = setOf("jar", "zip", "java") fun classpathFromClassloader(classLoader: ClassLoader): List? = - generateSequence(classLoader) { it.parent }.toList().flatMap { + allRelatedClassLoaders(classLoader).toList().flatMap { val urls = (it as? URLClassLoader)?.urLs?.asList() ?: try { // e.g. for IDEA platform UrlClassLoader @@ -89,6 +89,24 @@ fun File.hasParentNamed(baseName: String): Boolean = private const val KOTLIN_COMPILER_EMBEDDABLE_JAR = "$KOTLIN_COMPILER_NAME-embeddable.jar" +private fun allRelatedClassLoaders(clsLoader: ClassLoader, visited: MutableSet = HashSet()): Sequence { + if (!visited.add(clsLoader)) return emptySequence() + + val singleParent = clsLoader.parent + if (singleParent != null) + return sequenceOf(clsLoader) + sequenceOf(singleParent).flatMap { allRelatedClassLoaders(it, visited) } + + return try { + val field = clsLoader.javaClass.getDeclaredField("myParents") // com.intellij.ide.plugins.cl.PluginClassLoader + field.isAccessible = true + val arrayOfClassLoaders = field.get(clsLoader) as Array + sequenceOf(clsLoader) + arrayOfClassLoaders.asSequence().flatMap { allRelatedClassLoaders(it, visited) } + } catch (e: Throwable) { + sequenceOf(clsLoader) + } +} + + internal fun List.takeIfContainsAll(vararg keyNames: String): List? = takeIf { classpath -> keyNames.all { key -> classpath.any { it.matchMaybeVersionedFile(key) } }