Extract urls from any classloader that has getUrls(): List<URL> 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).
This commit is contained in:
Ilya Chernikov
2018-08-30 21:34:49 +03:00
parent fd0eb6ee34
commit d785b7e4c5
@@ -4,6 +4,7 @@ import org.jetbrains.kotlin.script.util.impl.getResourcePathForClass
import org.jetbrains.kotlin.script.util.impl.toFile import org.jetbrains.kotlin.script.util.impl.toFile
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.net.URL
import java.net.URLClassLoader import java.net.URLClassLoader
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.script.templates.standard.ScriptTemplateWithArgs import kotlin.script.templates.standard.ScriptTemplateWithArgs
@@ -29,13 +30,23 @@ private val validClasspathFilesExtensions = setOf("jar", "zip", "java")
fun classpathFromClassloader(classLoader: ClassLoader): List<File>? = fun classpathFromClassloader(classLoader: ClassLoader): List<File>? =
generateSequence(classLoader) { it.parent }.toList().flatMap { generateSequence(classLoader) { it.parent }.toList().flatMap {
(it as? URLClassLoader)?.urLs?.mapNotNull { 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<Any?>
result?.filterIsInstance<URL>()
} catch (e: Throwable) {
null
}
urls?.mapNotNull {
// taking only classpath elements pointing to dirs (presumably with classes) or jars, because this classpath is intended for // 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 // 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 } } it.toFile()?.takeIf { el -> el.isDirectory || validClasspathFilesExtensions.any { el.extension == it } }
} }
?: emptyList() ?: emptyList()
} }.distinct().takeIf { it.isNotEmpty() }
fun classpathFromClasspathProperty(): List<File>? = fun classpathFromClasspathProperty(): List<File>? =
System.getProperty("java.class.path") System.getProperty("java.class.path")