From d785b7e4c5dba285f66f955abe6ff33694fe6bfb Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 30 Aug 2018 21:34:49 +0300 Subject: [PATCH] Extract urls from any classloader that has getUrls(): List method via reflection, e.g. IDEA platform UrlClassloader. This fix allow kotlin JSR223 host for IDEA to extract classpath from the environment properly (with appropriate fix on IDEA side as well). --- .../jetbrains/kotlin/script/util/context.kt | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/context.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/context.kt index 1cac726e1cf..300707e4c93 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/context.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/context.kt @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.script.util.impl.getResourcePathForClass import org.jetbrains.kotlin.script.util.impl.toFile import java.io.File import java.io.FileNotFoundException +import java.net.URL import java.net.URLClassLoader import kotlin.reflect.KClass import kotlin.script.templates.standard.ScriptTemplateWithArgs @@ -28,14 +29,24 @@ 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 { - (it as? URLClassLoader)?.urLs?.mapNotNull { - // taking only classpath elements pointing to dirs (presumably with classes) or jars, because this classpath is intended for - // usage with the kotlin compiler, which cannot process other types of entries, e.g. jni libs - it.toFile()?.takeIf { el -> el.isDirectory || validClasspathFilesExtensions.any { el.extension == it } } + generateSequence(classLoader) { it.parent }.toList().flatMap { + val urls = (it as? URLClassLoader)?.urLs?.asList() + ?: try { + // e.g. for IDEA platform UrlClassLoader + val getUrls = it::class.java.getMethod("getUrls") + getUrls.isAccessible = true + val result = getUrls.invoke(it) as? List + result?.filterIsInstance() + } catch (e: Throwable) { + null } - ?: emptyList() + urls?.mapNotNull { + // taking only classpath elements pointing to dirs (presumably with classes) or jars, because this classpath is intended for + // usage with the kotlin compiler, which cannot process other types of entries, e.g. jni libs + it.toFile()?.takeIf { el -> el.isDirectory || validClasspathFilesExtensions.any { el.extension == it } } } + ?: emptyList() + }.distinct().takeIf { it.isNotEmpty() } fun classpathFromClasspathProperty(): List? = System.getProperty("java.class.path")