Copy (partly) context classpath extraction code from script-util to JSR223 4 Idea, use it there

This commit is contained in:
Ilya Chernikov
2016-12-12 18:10:22 +01:00
parent 632dba8228
commit 038491399b
3 changed files with 63 additions and 5 deletions
@@ -19,6 +19,12 @@ package org.jetbrains.kotlin.jsr223
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_JAVA_RUNTIME_JAR
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_JAVA_SCRIPT_RUNTIME_JAR
import java.io.File
import java.io.FileNotFoundException
import java.net.URL
import java.net.URLClassLoader
import javax.script.ScriptContext
import javax.script.ScriptEngine
@@ -29,9 +35,64 @@ class KotlinJsr223StandardScriptEngineFactory4Idea : KotlinJsr223JvmScriptEngine
KotlinJsr223JvmScriptEngine4Idea(
Disposer.newDisposable(),
this,
listOf(PathUtil.getKotlinPathsForIdeaPlugin().runtimePath, PathUtil.getKotlinPathsForIdeaPlugin().scriptRuntimePath),
scriptCompilationClasspathFromContext(Thread.currentThread().contextClassLoader),
"kotlin.script.templates.standard.ScriptTemplateWithBindings",
{ ctx -> arrayOf(ctx.getBindings(ScriptContext.ENGINE_SCOPE)) },
arrayOf(Map::class.java)
)
}
// TODO: some common parts with the code from script-utils, consider placing in a shared lib
private fun URL.toFile() =
try {
File(toURI().schemeSpecificPart)
}
catch (e: java.net.URISyntaxException) {
if (protocol != "file") null
else File(file)
}
fun classpathFromClassloader(classLoader: ClassLoader): List<File>? =
generateSequence(classLoader) { it.parent }.toList().flatMap { (it as? URLClassLoader)?.urLs?.mapNotNull(URL::toFile) ?: emptyList() }
private fun File.existsOrNull(): File? = existsAndCheckOrNull { true }
private inline fun File.existsAndCheckOrNull(check: (File.() -> Boolean)): File? = if (exists() && check()) this else null
private val kotlinCompilerJar: File by lazy {
// highest prio - explicit property
System.getProperty("kotlin.compiler.jar")?.let(::File)?.existsOrNull()
?: PathUtil.getKotlinPathsForIdeaPlugin().compilerPath
?: throw FileNotFoundException("Cannot find kotlin compiler jar, set kotlin.compiler.jar property to proper location")
}
private fun <T> Iterable<T>.anyOrNull(predicate: (T) -> Boolean) = if (any(predicate)) this else null
private fun File.matchMaybeVersionedFile(baseName: String) =
name == baseName ||
name == baseName.removeSuffix(".jar") || // for classes dirs
name.startsWith(baseName.removeSuffix(".jar") + "-")
private fun contextClasspath(keyName: String, classLoader: ClassLoader): List<File>? =
( classpathFromClassloader(classLoader)?.anyOrNull { it.matchMaybeVersionedFile(keyName) }
)?.toList()
private fun scriptCompilationClasspathFromContext(classLoader: ClassLoader): List<File> =
( System.getProperty("kotlin.script.classpath")?.split(File.pathSeparator)?.map(::File)
?: contextClasspath(KOTLIN_JAVA_RUNTIME_JAR, classLoader)
?: listOf(kotlinRuntimeJar, kotlinScriptRuntimeJar)
)
.map { it?.canonicalFile }
.distinct()
.mapNotNull { it?.existsOrNull() }
private val kotlinRuntimeJar: File? by lazy {
System.getProperty("kotlin.java.runtime.jar")?.let(::File)?.existsOrNull()
?: kotlinCompilerJar.let { File(it.parentFile, KOTLIN_JAVA_RUNTIME_JAR) }.existsOrNull()
}
private val kotlinScriptRuntimeJar: File? by lazy {
System.getProperty("kotlin.script.runtime.jar")?.let(::File)?.existsOrNull()
?: kotlinCompilerJar.let { File(it.parentFile, KOTLIN_JAVA_SCRIPT_RUNTIME_JAR) }.existsOrNull()
}
@@ -73,7 +73,7 @@ private inline fun File.existsAndCheckOrNull(check: (File.() -> Boolean)): File?
private val kotlinCompilerJar: File by lazy {
// highest prio - explicit property
System.getProperty("kotlin.compiler.jar")?.let(::File)?.existsOrNull()
// search classpath from context classloader and `java.calss.path` property
// search classpath from context classloader and `java.class.path` property
?: (classpathFromClass(Thread.currentThread().contextClassLoader, K2JVMCompiler::class)
?: contextClasspath(KOTLIN_COMPILER_JAR, Thread.currentThread().contextClassLoader)
?: classpathFromClasspathProperty()
@@ -1,7 +1,5 @@
package org.jetbrains.kotlin.script.util
import org.jetbrains.kotlin.script.util.resolvers.DirectResolver
import org.jetbrains.kotlin.script.util.resolvers.MavenResolver
import java.io.File
import java.net.URI
import java.net.URL
@@ -9,7 +7,6 @@ import java.net.URLClassLoader
import java.util.jar.Manifest
import kotlin.reflect.KClass
private fun URL.toFile() =
try {
File(toURI().schemeSpecificPart)