Move context classpath utils from script-util to scripting-jvm
since it is the right place to have it in the new structure. Solves the problem that script-util classes not found then script definition with context classpath is loaded by the scripting compiler plugin, since script-util is not packed into embeddable plugin. The old context utils are deprecated and in fact wrap the new utils. #KT-26828 fixed (in fact - partially, see another related commit)
This commit is contained in:
+1
-1
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo
|
|||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil.isInContent
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil.isInContent
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.script.*
|
import org.jetbrains.kotlin.script.*
|
||||||
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContextOrStlib
|
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.KotlinScriptDefinitionAdapterFromNewAPI
|
import org.jetbrains.kotlin.scripting.compiler.plugin.KotlinScriptDefinitionAdapterFromNewAPI
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
@@ -58,6 +57,7 @@ import kotlin.script.experimental.host.configurationDependencies
|
|||||||
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
|
||||||
import kotlin.script.experimental.jvm.JvmDependency
|
import kotlin.script.experimental.jvm.JvmDependency
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStlib
|
||||||
import kotlin.script.experimental.location.ScriptExpectedLocation
|
import kotlin.script.experimental.location.ScriptExpectedLocation
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ dependencies {
|
|||||||
compile(project(":kotlin-script-runtime"))
|
compile(project(":kotlin-script-runtime"))
|
||||||
compile(project(":kotlin-stdlib"))
|
compile(project(":kotlin-stdlib"))
|
||||||
compile(project(":kotlin-scripting-common"))
|
compile(project(":kotlin-scripting-common"))
|
||||||
compile(project(":kotlin-script-util"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
* that can be found in the license/LICENSE.txt file.
|
* that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.script.util.impl
|
package kotlin.script.experimental.jvm.impl
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package kotlin.script.experimental.jvm
|
package kotlin.script.experimental.jvm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContext
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext
|
||||||
import kotlin.script.experimental.util.PropertiesCollection
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
data class JvmDependency(val classpath: List<File>) : ScriptDependency {
|
data class JvmDependency(val classpath: List<File>) : ScriptDependency {
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.util
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.net.URL
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.script.experimental.jvm.impl.getResourcePathForClass
|
||||||
|
import kotlin.script.experimental.jvm.impl.toFile
|
||||||
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
|
// TODO: consider moving all these utilites to the build-common or some other shared compiler API module
|
||||||
|
|
||||||
|
internal const val KOTLIN_JAVA_STDLIB_JAR = "kotlin-stdlib.jar"
|
||||||
|
internal const val KOTLIN_JAVA_REFLECT_JAR = "kotlin-reflect.jar"
|
||||||
|
internal const val KOTLIN_JAVA_SCRIPT_RUNTIME_JAR = "kotlin-script-runtime.jar"
|
||||||
|
internal const val KOTLIN_COMPILER_NAME = "kotlin-compiler"
|
||||||
|
internal const val KOTLIN_COMPILER_JAR = "$KOTLIN_COMPILER_NAME.jar"
|
||||||
|
|
||||||
|
internal const val KOTLIN_SCRIPT_CLASSPATH_PROPERTY = "kotlin.script.classpath"
|
||||||
|
internal const val KOTLIN_COMPILER_CLASSPATH_PROPERTY = "kotlin.compiler.classpath"
|
||||||
|
internal const val KOTLIN_COMPILER_JAR_PROPERTY = "kotlin.compiler.jar"
|
||||||
|
internal const val KOTLIN_STDLIB_JAR_PROPERTY = "kotlin.java.stdlib.jar"
|
||||||
|
// obsolete name, but maybe still used in the wild
|
||||||
|
// TODO: consider removing
|
||||||
|
internal const val KOTLIN_RUNTIME_JAR_PROPERTY = "kotlin.java.runtime.jar"
|
||||||
|
internal const val KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY = "kotlin.script.runtime.jar"
|
||||||
|
|
||||||
|
private val validClasspathFilesExtensions = setOf("jar", "zip", "java")
|
||||||
|
|
||||||
|
fun classpathFromClassloader(classLoader: ClassLoader): List<File>? =
|
||||||
|
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<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
|
||||||
|
// 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<File>? =
|
||||||
|
System.getProperty("java.class.path")
|
||||||
|
?.split(String.format("\\%s", File.pathSeparatorChar).toRegex())
|
||||||
|
?.dropLastWhile(String::isEmpty)
|
||||||
|
?.map(::File)
|
||||||
|
|
||||||
|
fun classpathFromClass(classLoader: ClassLoader, klass: KClass<out Any>): List<File>? =
|
||||||
|
classpathFromFQN(classLoader, klass.qualifiedName!!)
|
||||||
|
|
||||||
|
fun classpathFromFQN(classLoader: ClassLoader, fqn: String): List<File>? {
|
||||||
|
val clp = "${fqn.replace('.', '/')}.class"
|
||||||
|
val url = classLoader.getResource(clp)
|
||||||
|
return url?.toURI()?.path?.removeSuffix(clp)?.let {
|
||||||
|
listOf(File(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun File.matchMaybeVersionedFile(baseName: String) =
|
||||||
|
name == baseName ||
|
||||||
|
name == baseName.removeSuffix(".jar") || // for classes dirs
|
||||||
|
Regex(Regex.escape(baseName.removeSuffix(".jar")) + "(-\\d.*)?\\.jar").matches(name)
|
||||||
|
|
||||||
|
fun File.hasParentNamed(baseName: String): Boolean =
|
||||||
|
nameWithoutExtension == baseName || parentFile?.hasParentNamed(baseName) ?: false
|
||||||
|
|
||||||
|
private const val KOTLIN_COMPILER_EMBEDDABLE_JAR = "$KOTLIN_COMPILER_NAME-embeddable.jar"
|
||||||
|
|
||||||
|
internal fun List<File>.takeIfContainsAll(vararg keyNames: String): List<File>? =
|
||||||
|
takeIf { classpath ->
|
||||||
|
keyNames.all { key -> classpath.any { it.matchMaybeVersionedFile(key) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun List<File>.filterIfContainsAll(vararg keyNames: String): List<File>? {
|
||||||
|
val res = hashMapOf<String, File>()
|
||||||
|
for (cpentry in this) {
|
||||||
|
for (prefix in keyNames) {
|
||||||
|
if (cpentry.matchMaybeVersionedFile(prefix) ||
|
||||||
|
(cpentry.isDirectory && cpentry.hasParentNamed(prefix))
|
||||||
|
) {
|
||||||
|
res[prefix] = cpentry
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return if (keyNames.all { res.containsKey(it) }) res.values.toList()
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun List<File>.takeIfContainsAny(vararg keyNames: String): List<File>? =
|
||||||
|
takeIf { classpath ->
|
||||||
|
keyNames.any { key -> classpath.any { it.matchMaybeVersionedFile(key) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scriptCompilationClasspathFromContextOrNull(
|
||||||
|
vararg keyNames: String,
|
||||||
|
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
||||||
|
wholeClasspath: Boolean = false
|
||||||
|
): List<File>? {
|
||||||
|
fun List<File>.takeAndFilter() = when {
|
||||||
|
isEmpty() -> null
|
||||||
|
wholeClasspath -> takeIfContainsAll(*keyNames)
|
||||||
|
else -> filterIfContainsAll(*keyNames)
|
||||||
|
}
|
||||||
|
return System.getProperty(KOTLIN_SCRIPT_CLASSPATH_PROPERTY)?.split(File.pathSeparator)?.map(::File)
|
||||||
|
?: classpathFromClassloader(classLoader)?.takeAndFilter()
|
||||||
|
?: classpathFromClasspathProperty()?.takeAndFilter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scriptCompilationClasspathFromContextOrStlib(
|
||||||
|
vararg keyNames: String,
|
||||||
|
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
||||||
|
wholeClasspath: Boolean = false
|
||||||
|
): List<File> =
|
||||||
|
scriptCompilationClasspathFromContextOrNull(
|
||||||
|
*keyNames,
|
||||||
|
classLoader = classLoader,
|
||||||
|
wholeClasspath = wholeClasspath
|
||||||
|
)
|
||||||
|
?: KotlinJars.kotlinScriptStandardJars
|
||||||
|
|
||||||
|
fun scriptCompilationClasspathFromContext(
|
||||||
|
vararg keyNames: String,
|
||||||
|
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
||||||
|
wholeClasspath: Boolean = false
|
||||||
|
): List<File> =
|
||||||
|
scriptCompilationClasspathFromContextOrNull(
|
||||||
|
*keyNames,
|
||||||
|
classLoader = classLoader,
|
||||||
|
wholeClasspath = wholeClasspath
|
||||||
|
)
|
||||||
|
?: throw Exception("Unable to get script compilation classpath from context, please specify explicit classpath via \"$KOTLIN_SCRIPT_CLASSPATH_PROPERTY\" property")
|
||||||
|
|
||||||
|
object KotlinJars {
|
||||||
|
|
||||||
|
private val explicitCompilerClasspath: List<File>? by lazy {
|
||||||
|
System.getProperty(KOTLIN_COMPILER_CLASSPATH_PROPERTY)?.split(File.pathSeparator)?.map(::File)
|
||||||
|
?: System.getProperty(KOTLIN_COMPILER_JAR_PROPERTY)?.let(::File)?.takeIf(File::exists)?.let { listOf(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val compilerClasspath: List<File> by lazy {
|
||||||
|
val kotlinCompilerJars = listOf(
|
||||||
|
KOTLIN_COMPILER_JAR,
|
||||||
|
KOTLIN_COMPILER_EMBEDDABLE_JAR
|
||||||
|
)
|
||||||
|
val kotlinLibsJars = listOf(
|
||||||
|
KOTLIN_JAVA_STDLIB_JAR,
|
||||||
|
KOTLIN_JAVA_REFLECT_JAR,
|
||||||
|
KOTLIN_JAVA_SCRIPT_RUNTIME_JAR
|
||||||
|
)
|
||||||
|
val kotlinBaseJars = kotlinCompilerJars + kotlinLibsJars
|
||||||
|
|
||||||
|
val classpath = explicitCompilerClasspath
|
||||||
|
// search classpath from context classloader and `java.class.path` property
|
||||||
|
?: (classpathFromFQN(
|
||||||
|
Thread.currentThread().contextClassLoader,
|
||||||
|
"org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
|
||||||
|
)
|
||||||
|
?: classpathFromClassloader(Thread.currentThread().contextClassLoader)?.takeIf { it.isNotEmpty() }
|
||||||
|
?: classpathFromClasspathProperty()
|
||||||
|
)?.filter { f -> kotlinBaseJars.any { f.matchMaybeVersionedFile(it) } }?.takeIf { it.isNotEmpty() }
|
||||||
|
// if autodetected, additionaly check for presense of the compiler jars
|
||||||
|
if (classpath == null || (explicitCompilerClasspath == null && classpath.none { f -> kotlinCompilerJars.any { f.matchMaybeVersionedFile(it) } })) {
|
||||||
|
throw FileNotFoundException("Cannot find kotlin compiler jar, set kotlin.compiler.classpath property to proper location")
|
||||||
|
}
|
||||||
|
classpath!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLib(propertyName: String, jarName: String, markerClass: KClass<*>): File? =
|
||||||
|
System.getProperty(propertyName)?.let(::File)?.takeIf(File::exists)
|
||||||
|
?: explicitCompilerClasspath?.firstOrNull { it.matchMaybeVersionedFile(jarName) }?.takeIf(File::exists)
|
||||||
|
?: getResourcePathForClass(markerClass.java).takeIf(File::exists)
|
||||||
|
|
||||||
|
val stdlibOrNull: File? by lazy {
|
||||||
|
System.getProperty(KOTLIN_STDLIB_JAR_PROPERTY)?.let(::File)?.takeIf(File::exists)
|
||||||
|
?: getLib(
|
||||||
|
KOTLIN_RUNTIME_JAR_PROPERTY,
|
||||||
|
KOTLIN_JAVA_STDLIB_JAR,
|
||||||
|
JvmStatic::class
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val stdlib: File by lazy {
|
||||||
|
stdlibOrNull
|
||||||
|
?: throw Exception("Unable to find kotlin stdlib, please specify it explicitly via \"$KOTLIN_STDLIB_JAR_PROPERTY\" property")
|
||||||
|
}
|
||||||
|
|
||||||
|
val scriptRuntimeOrNull: File? by lazy {
|
||||||
|
getLib(
|
||||||
|
KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY,
|
||||||
|
KOTLIN_JAVA_SCRIPT_RUNTIME_JAR,
|
||||||
|
ScriptTemplateWithArgs::class
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val scriptRuntime: File by lazy {
|
||||||
|
scriptRuntimeOrNull
|
||||||
|
?: throw Exception("Unable to find kotlin script runtime, please specify it explicitly via \"$KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY\" property")
|
||||||
|
}
|
||||||
|
|
||||||
|
val kotlinScriptStandardJars get() = listOf(
|
||||||
|
stdlibOrNull,
|
||||||
|
scriptRuntimeOrNull
|
||||||
|
).filterNotNull()
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":kotlin-stdlib"))
|
compile(project(":kotlin-stdlib"))
|
||||||
compile(project(":kotlin-script-runtime"))
|
compile(project(":kotlin-script-runtime"))
|
||||||
|
compile(project(":kotlin-scripting-jvm"))
|
||||||
compileOnly(project(":compiler:cli"))
|
compileOnly(project(":compiler:cli"))
|
||||||
compileOnly(project(":compiler:daemon-common"))
|
compileOnly(project(":compiler:daemon-common"))
|
||||||
compile(projectRuntimeJar(":kotlin-daemon-client"))
|
compile(projectRuntimeJar(":kotlin-daemon-client"))
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":kotlin-stdlib"))
|
compile(project(":kotlin-stdlib"))
|
||||||
compile(project(":kotlin-script-runtime"))
|
compile(project(":kotlin-script-runtime"))
|
||||||
|
compile(project(":kotlin-scripting-jvm"))
|
||||||
compileOnly(project(":compiler:cli"))
|
compileOnly(project(":compiler:cli"))
|
||||||
compileOnly(project(":compiler:daemon-common"))
|
compileOnly(project(":compiler:daemon-common"))
|
||||||
compile(projectRuntimeJar(":kotlin-daemon-client"))
|
compile(projectRuntimeJar(":kotlin-daemon-client"))
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":kotlin-stdlib"))
|
compile(project(":kotlin-stdlib"))
|
||||||
compile(project(":kotlin-script-runtime"))
|
compile(project(":kotlin-script-runtime"))
|
||||||
|
compile(project(":kotlin-scripting-jvm"))
|
||||||
compileOnly(project(":compiler:cli"))
|
compileOnly(project(":compiler:cli"))
|
||||||
compileOnly(project(":compiler:daemon-common"))
|
compileOnly(project(":compiler:daemon-common"))
|
||||||
compile(projectRuntimeJar(":kotlin-daemon-client"))
|
compile(projectRuntimeJar(":kotlin-daemon-client"))
|
||||||
|
|||||||
+31
-154
@@ -1,184 +1,61 @@
|
|||||||
package org.jetbrains.kotlin.script.util
|
package org.jetbrains.kotlin.script.util
|
||||||
|
|
||||||
import org.jetbrains.kotlin.script.util.impl.getResourcePathForClass
|
|
||||||
import org.jetbrains.kotlin.script.util.impl.toFile
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileNotFoundException
|
|
||||||
import java.net.URL
|
|
||||||
import java.net.URLClassLoader
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
import kotlin.script.experimental.jvm.util.matchMaybeVersionedFile as newMatchMaybeVersionedFile
|
||||||
|
import kotlin.script.experimental.jvm.util.hasParentNamed as newHasParentName
|
||||||
// TODO: consider moving all these utilites to the build-common or some other shared compiler API module
|
|
||||||
|
|
||||||
internal const val KOTLIN_JAVA_STDLIB_JAR = "kotlin-stdlib.jar"
|
|
||||||
internal const val KOTLIN_JAVA_REFLECT_JAR = "kotlin-reflect.jar"
|
|
||||||
internal const val KOTLIN_JAVA_SCRIPT_RUNTIME_JAR = "kotlin-script-runtime.jar"
|
|
||||||
internal const val KOTLIN_COMPILER_NAME = "kotlin-compiler"
|
|
||||||
internal const val KOTLIN_COMPILER_JAR = "$KOTLIN_COMPILER_NAME.jar"
|
|
||||||
|
|
||||||
internal const val KOTLIN_SCRIPT_CLASSPATH_PROPERTY = "kotlin.script.classpath"
|
|
||||||
internal const val KOTLIN_COMPILER_CLASSPATH_PROPERTY = "kotlin.compiler.classpath"
|
|
||||||
internal const val KOTLIN_COMPILER_JAR_PROPERTY = "kotlin.compiler.jar"
|
|
||||||
internal const val KOTLIN_STDLIB_JAR_PROPERTY = "kotlin.java.stdlib.jar"
|
|
||||||
// obsolete name, but maybe still used in the wild
|
|
||||||
// TODO: consider removing
|
|
||||||
internal const val KOTLIN_RUNTIME_JAR_PROPERTY = "kotlin.java.runtime.jar"
|
|
||||||
internal const val KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY = "kotlin.script.runtime.jar"
|
|
||||||
|
|
||||||
private val validClasspathFilesExtensions = setOf("jar", "zip", "java")
|
|
||||||
|
|
||||||
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
fun classpathFromClassloader(classLoader: ClassLoader): List<File>? =
|
fun classpathFromClassloader(classLoader: ClassLoader): List<File>? =
|
||||||
generateSequence(classLoader) { it.parent }.toList().flatMap {
|
kotlin.script.experimental.jvm.util.classpathFromClassloader(classLoader)
|
||||||
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
|
|
||||||
// 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() }
|
|
||||||
|
|
||||||
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
fun classpathFromClasspathProperty(): List<File>? =
|
fun classpathFromClasspathProperty(): List<File>? =
|
||||||
System.getProperty("java.class.path")
|
kotlin.script.experimental.jvm.util.classpathFromClasspathProperty()
|
||||||
?.split(String.format("\\%s", File.pathSeparatorChar).toRegex())
|
|
||||||
?.dropLastWhile(String::isEmpty)
|
|
||||||
?.map(::File)
|
|
||||||
|
|
||||||
fun classpathFromClass(classLoader: ClassLoader, klass: KClass<out Any>): List<File>? = classpathFromFQN(classLoader, klass.qualifiedName!!)
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
|
fun classpathFromClass(classLoader: ClassLoader, klass: KClass<out Any>): List<File>? =
|
||||||
|
kotlin.script.experimental.jvm.util.classpathFromClass(classLoader, klass)
|
||||||
|
|
||||||
fun classpathFromFQN(classLoader: ClassLoader, fqn: String): List<File>? {
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
val clp = "${fqn.replace('.', '/')}.class"
|
fun classpathFromFQN(classLoader: ClassLoader, fqn: String): List<File>? =
|
||||||
val url = classLoader.getResource(clp)
|
kotlin.script.experimental.jvm.util.classpathFromFQN(classLoader, fqn)
|
||||||
return url?.toURI()?.path?.removeSuffix(clp)?.let {
|
|
||||||
listOf(File(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun File.matchMaybeVersionedFile(baseName: String) =
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
name == baseName ||
|
fun File.matchMaybeVersionedFile(baseName: String) = newMatchMaybeVersionedFile(baseName)
|
||||||
name == baseName.removeSuffix(".jar") || // for classes dirs
|
|
||||||
Regex(Regex.escape(baseName.removeSuffix(".jar")) + "(-\\d.*)?\\.jar").matches(name)
|
|
||||||
|
|
||||||
fun File.hasParentNamed(baseName: String): Boolean =
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
nameWithoutExtension == baseName || parentFile?.hasParentNamed(baseName) ?: false
|
fun File.hasParentNamed(baseName: String): Boolean = newHasParentName(baseName)
|
||||||
|
|
||||||
private const val KOTLIN_COMPILER_EMBEDDABLE_JAR = "$KOTLIN_COMPILER_NAME-embeddable.jar"
|
|
||||||
|
|
||||||
internal fun List<File>.takeIfContainsAll(vararg keyNames: String): List<File>? =
|
|
||||||
takeIf { classpath ->
|
|
||||||
keyNames.all { key -> classpath.any { it.matchMaybeVersionedFile(key) } }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun List<File>.filterIfContainsAll(vararg keyNames: String): List<File>? {
|
|
||||||
val res = hashMapOf<String, File>()
|
|
||||||
for (cpentry in this) {
|
|
||||||
for (prefix in keyNames) {
|
|
||||||
if (cpentry.matchMaybeVersionedFile(prefix) ||
|
|
||||||
(cpentry.isDirectory && cpentry.hasParentNamed(prefix))
|
|
||||||
) {
|
|
||||||
res[prefix] = cpentry
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return if (keyNames.all { res.containsKey(it) }) res.values.toList()
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun List<File>.takeIfContainsAny(vararg keyNames: String): List<File>? =
|
|
||||||
takeIf { classpath ->
|
|
||||||
keyNames.any { key -> classpath.any { it.matchMaybeVersionedFile(key) } }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
fun scriptCompilationClasspathFromContextOrNull(
|
fun scriptCompilationClasspathFromContextOrNull(
|
||||||
vararg keyNames: String,
|
vararg keyNames: String,
|
||||||
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
||||||
wholeClasspath: Boolean = false
|
wholeClasspath: Boolean = false
|
||||||
): List<File>? {
|
): List<File>? =
|
||||||
fun List<File>.takeAndFilter() = when {
|
kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrNull(
|
||||||
isEmpty() -> null
|
*keyNames, classLoader = classLoader, wholeClasspath = wholeClasspath
|
||||||
wholeClasspath -> takeIfContainsAll(*keyNames)
|
)
|
||||||
else -> filterIfContainsAll(*keyNames)
|
|
||||||
}
|
|
||||||
return System.getProperty(KOTLIN_SCRIPT_CLASSPATH_PROPERTY)?.split(File.pathSeparator)?.map(::File)
|
|
||||||
?: classpathFromClassloader(classLoader)?.takeAndFilter()
|
|
||||||
?: classpathFromClasspathProperty()?.takeAndFilter()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
fun scriptCompilationClasspathFromContextOrStlib(
|
fun scriptCompilationClasspathFromContextOrStlib(
|
||||||
vararg keyNames: String,
|
vararg keyNames: String,
|
||||||
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
||||||
wholeClasspath: Boolean = false
|
wholeClasspath: Boolean = false
|
||||||
): List<File> =
|
): List<File> =
|
||||||
scriptCompilationClasspathFromContextOrNull(*keyNames, classLoader = classLoader, wholeClasspath = wholeClasspath)
|
kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrStlib(
|
||||||
?: KotlinJars.kotlinScriptStandardJars
|
*keyNames, classLoader = classLoader, wholeClasspath = wholeClasspath
|
||||||
|
)
|
||||||
|
|
||||||
|
@Deprecated("Use the function from kotlin.script.experimental.jvm.util")
|
||||||
fun scriptCompilationClasspathFromContext(
|
fun scriptCompilationClasspathFromContext(
|
||||||
vararg keyNames: String,
|
vararg keyNames: String,
|
||||||
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
|
||||||
wholeClasspath: Boolean = false
|
wholeClasspath: Boolean = false
|
||||||
): List<File> =
|
): List<File> =
|
||||||
scriptCompilationClasspathFromContextOrNull(*keyNames, classLoader = classLoader, wholeClasspath = wholeClasspath)
|
kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext(
|
||||||
?: throw Exception("Unable to get script compilation classpath from context, please specify explicit classpath via \"$KOTLIN_SCRIPT_CLASSPATH_PROPERTY\" property")
|
*keyNames, classLoader = classLoader, wholeClasspath = wholeClasspath
|
||||||
|
)
|
||||||
|
|
||||||
object KotlinJars {
|
@Deprecated("Use the object from kotlin.script.experimental.jvm.util")
|
||||||
|
val KotlinJars = kotlin.script.experimental.jvm.util.KotlinJars
|
||||||
private val explicitCompilerClasspath: List<File>? by lazy {
|
|
||||||
System.getProperty(KOTLIN_COMPILER_CLASSPATH_PROPERTY)?.split(File.pathSeparator)?.map(::File)
|
|
||||||
?: System.getProperty(KOTLIN_COMPILER_JAR_PROPERTY)?.let(::File)?.takeIf(File::exists)?.let { listOf(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val compilerClasspath: List<File> by lazy {
|
|
||||||
val kotlinCompilerJars = listOf(KOTLIN_COMPILER_JAR, KOTLIN_COMPILER_EMBEDDABLE_JAR)
|
|
||||||
val kotlinLibsJars = listOf(KOTLIN_JAVA_STDLIB_JAR, KOTLIN_JAVA_REFLECT_JAR, KOTLIN_JAVA_SCRIPT_RUNTIME_JAR)
|
|
||||||
val kotlinBaseJars = kotlinCompilerJars + kotlinLibsJars
|
|
||||||
|
|
||||||
val classpath = explicitCompilerClasspath
|
|
||||||
// search classpath from context classloader and `java.class.path` property
|
|
||||||
?: (classpathFromFQN(Thread.currentThread().contextClassLoader, "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
|
|
||||||
?: classpathFromClassloader(Thread.currentThread().contextClassLoader)?.takeIf { it.isNotEmpty() }
|
|
||||||
?: classpathFromClasspathProperty()
|
|
||||||
)?.filter { f -> kotlinBaseJars.any { f.matchMaybeVersionedFile(it) } }?.takeIf { it.isNotEmpty() }
|
|
||||||
// if autodetected, additionaly check for presense of the compiler jars
|
|
||||||
if (classpath == null || (explicitCompilerClasspath == null && classpath.none { f -> kotlinCompilerJars.any { f.matchMaybeVersionedFile(it) } })) {
|
|
||||||
throw FileNotFoundException("Cannot find kotlin compiler jar, set kotlin.compiler.classpath property to proper location")
|
|
||||||
}
|
|
||||||
classpath!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLib(propertyName: String, jarName: String, markerClass: KClass<*>): File? =
|
|
||||||
System.getProperty(propertyName)?.let(::File)?.takeIf(File::exists)
|
|
||||||
?: explicitCompilerClasspath?.firstOrNull { it.matchMaybeVersionedFile(jarName) }?.takeIf(File::exists)
|
|
||||||
?: getResourcePathForClass(markerClass.java).takeIf(File::exists)
|
|
||||||
|
|
||||||
val stdlibOrNull: File? by lazy {
|
|
||||||
System.getProperty(KOTLIN_STDLIB_JAR_PROPERTY)?.let(::File)?.takeIf(File::exists)
|
|
||||||
?: getLib(KOTLIN_RUNTIME_JAR_PROPERTY, KOTLIN_JAVA_STDLIB_JAR, JvmStatic::class)
|
|
||||||
}
|
|
||||||
|
|
||||||
val stdlib: File by lazy {
|
|
||||||
stdlibOrNull
|
|
||||||
?: throw Exception("Unable to find kotlin stdlib, please specify it explicitly via \"$KOTLIN_STDLIB_JAR_PROPERTY\" property")
|
|
||||||
}
|
|
||||||
|
|
||||||
val scriptRuntimeOrNull: File? by lazy {
|
|
||||||
getLib(KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY, KOTLIN_JAVA_SCRIPT_RUNTIME_JAR, ScriptTemplateWithArgs::class)
|
|
||||||
}
|
|
||||||
|
|
||||||
val scriptRuntime: File by lazy {
|
|
||||||
scriptRuntimeOrNull
|
|
||||||
?: throw Exception("Unable to find kotlin script runtime, please specify it explicitly via \"$KOTLIN_SCRIPT_RUNTIME_JAR_PROPERTY\" property")
|
|
||||||
}
|
|
||||||
|
|
||||||
val kotlinScriptStandardJars get() = listOf(stdlibOrNull, scriptRuntimeOrNull).filterNotNull()
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user