Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.rmi
import java.io.File
import java.io.Serializable
import java.lang.management.ManagementFactory
import java.security.DigestInputStream
import java.security.MessageDigest
import kotlin.reflect.KMutableProperty1
public val COMPILER_JAR_NAME: String = "kotlin-compiler.jar"
public val COMPILER_SERVICE_RMI_NAME: String = "KotlinJvmCompilerService"
public val COMPILER_DAEMON_CLASS_FQN: String = "org.jetbrains.kotlin.rmi.service.CompileDaemon"
public val COMPILE_DAEMON_FIND_PORT_ATTEMPTS: Int = 10
public val COMPILE_DAEMON_PORTS_RANGE_START: Int = 17001
public val COMPILE_DAEMON_PORTS_RANGE_END: Int = 18000
public val COMPILE_DAEMON_STARTUP_LOCK_TIMEOUT_MS: Long = 10000L
public val COMPILE_DAEMON_STARTUP_LOCK_TIMEOUT_CHECK_MS: Long = 100L
public val COMPILE_DAEMON_ENABLED_PROPERTY: String = "kotlin.daemon.enabled"
public val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String = "kotlin.daemon.jvm.options"
public val COMPILE_DAEMON_OPTIONS_PROPERTY: String = "kotlin.daemon.options"
public val COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY: String = "kotlin.daemon.client.alive.path"
public val COMPILE_DAEMON_LOG_PATH_PROPERTY: String = "kotlin.daemon.log.path"
public val COMPILE_DAEMON_REPORT_PERF_PROPERTY: String = "kotlin.daemon.perf"
public val COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY: String = "kotlin.daemon.verbose"
public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String = "--daemon-"
public val COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY: String = "kotlin.daemon.startup.timeout"
public val COMPILE_DAEMON_DEFAULT_FILES_PREFIX: String = "kotlin-daemon"
public val COMPILE_DAEMON_DATA_DIRECTORY_NAME: String = "." + COMPILE_DAEMON_DEFAULT_FILES_PREFIX
public val COMPILE_DAEMON_TIMEOUT_INFINITE_S: Int = 0
public val COMPILE_DAEMON_DEFAULT_IDLE_TIMEOUT_S: Int = 7200 // 2 hours
public val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L
public val COMPILE_DAEMON_FORCE_SHUTDOWN_DEFAULT_TIMEOUT_MS: Long = 10000L // 10 secs
public val COMPILE_DAEMON_FORCE_SHUTDOWN_TIMEOUT_INFINITE: Long = 0L
public val COMPILE_DAEMON_DEFAULT_RUN_DIR_PATH: String get() =
// TODO consider special case for windows - local appdata
File(System.getProperty("user.home"), COMPILE_DAEMON_DATA_DIRECTORY_NAME).absolutePath
val COMPILER_ID_DIGEST = "MD5"
public fun makeRunFilenameString(timestamp: String, digest: String, port: String, escapeSequence: String = ""): String = "$COMPILE_DAEMON_DEFAULT_FILES_PREFIX$escapeSequence.$timestamp$escapeSequence.$digest$escapeSequence.$port$escapeSequence.run"
open class PropMapper>(val dest: C,
val prop: P,
val names: List = listOf(prop.name),
val fromString: (String) -> V,
val toString: ((V) -> String?) = { it.toString() },
val skipIf: ((V) -> Boolean) = { false },
val mergeDelimiter: String? = null) {
open fun toArgs(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List =
when {
skipIf(prop.get(dest)) -> listOf()
mergeDelimiter != null -> listOf(listOf(prefix + names.first(), toString(prop.get(dest))).filterNotNull().joinToString(mergeDelimiter))
else -> listOf(prefix + names.first(), toString(prop.get(dest))).filterNotNull()
}
open fun apply(s: String) = prop.set(dest, fromString(s))
}
class NullablePropMapper>(dest: C,
prop: P,
names: List = listOf(),
fromString: ((String) -> V),
toString: ((V) -> String?) = { it.toString() },
skipIf: ((V) -> Boolean) = { it == null },
mergeDelimiter: String? = null)
: PropMapper(dest = dest, prop = prop, names = if (names.any()) names else listOf(prop.name),
fromString = fromString, toString = toString, skipIf = skipIf, mergeDelimiter = mergeDelimiter)
class StringPropMapper>(dest: C,
prop: P,
names: List = listOf(),
fromString: ((String) -> String) = { it },
toString: ((String) -> String?) = { it.toString() },
skipIf: ((String) -> Boolean) = { it.isEmpty() },
mergeDelimiter: String? = null)
: PropMapper(dest = dest, prop = prop, names = if (names.any()) names else listOf(prop.name),
fromString = fromString, toString = toString, skipIf = skipIf, mergeDelimiter = mergeDelimiter)
class BoolPropMapper>(dest: C, prop: P, names: List = listOf())
: PropMapper(dest = dest, prop = prop, names = if (names.any()) names else listOf(prop.name),
fromString = { true }, toString = { null }, skipIf = { !prop.get(dest) })
class RestPropMapper>>(dest: C, prop: P)
: PropMapper, P>(dest = dest, prop = prop, toString = { null }, fromString = { arrayListOf() }) {
override fun toArgs(prefix: String): List = prop.get(dest).map { prefix + it }
override fun apply(s: String) = add(s)
fun add(s: String) {
prop.get(dest).add(s)
}
}
// helper function combining find with map, useful for the cases then there is a calculation performed in find, which is nice to return along with
// found value; mappingPredicate should return the pair of boolean compare predicate result and transformation value, we want to get along with found value
inline fun Iterable.findWithTransform(mappingPredicate: (T) -> Pair): R? {
for (element in this) {
val (found, mapped) = mappingPredicate(element)
if (found) return mapped
}
return null
}
// filter-like function, takes list of propmappers, bound to properties of concrete objects, iterates over receiver, extract matching values via appropriate
// mappers into bound properties; if restParser is given, adds all non-matching elements to it, otherwise return them as an iterable
// note bound properties mutation!
fun Iterable.filterExtractProps(propMappers: List>, prefix: String, restParser: RestPropMapper<*, *>? = null): Iterable {
val iter = iterator()
val rest = arrayListOf()
while (iter.hasNext()) {
val param = iter.next()
val (propMapper, matchingOption) = propMappers.findWithTransform { mapper ->
mapper.names
.firstOrNull { param.startsWith(prefix + it) }
.let { Pair(it != null, Pair(mapper, it)) }
} ?: Pair(null, null)
when {
propMapper != null -> {
val optionLength = prefix.length() + matchingOption!!.length()
when {
propMapper is BoolPropMapper<*, *> -> {
if (param.length() > optionLength)
throw IllegalArgumentException("Invalid switch option '$param', expecting $prefix$matchingOption without arguments")
propMapper.apply("")
}
param.length() > optionLength ->
if (param[optionLength] != '=') {
if (propMapper.mergeDelimiter == null)
throw IllegalArgumentException("Invalid option syntax '$param', expecting $prefix$matchingOption[= ]")
propMapper.apply(param.substring(optionLength))
}
else {
propMapper.apply(param.substring(optionLength + 1))
}
else -> {
if (!iter.hasNext()) throw IllegalArgumentException("Expecting argument for the option $prefix$matchingOption")
propMapper.apply(iter.next())
}
}
}
restParser != null && param.startsWith(prefix) ->
restParser.add(param.removePrefix(prefix))
else -> rest.add(param)
}
}
return rest
}
public fun String.trimQuotes() = trim('"','\'')
public interface OptionsGroup : Serializable {
public val mappers: List>
}
public fun Iterable.filterExtractProps(vararg groups: OptionsGroup, prefix: String): Iterable =
filterExtractProps(groups.flatMap { it.mappers }, prefix)
public data class DaemonJVMOptions(
public var maxMemory: String = "",
public var maxPermSize: String = "",
public var reservedCodeCacheSize: String = "",
public var jvmParams: MutableCollection = arrayListOf()
) : OptionsGroup {
override val mappers: List>
get() = listOf(StringPropMapper(this, DaemonJVMOptions::maxMemory, listOf("Xmx"), mergeDelimiter = ""),
StringPropMapper(this, DaemonJVMOptions::maxPermSize, listOf("XX:MaxPermSize"), mergeDelimiter = "="),
StringPropMapper(this, DaemonJVMOptions::reservedCodeCacheSize, listOf("XX:ReservedCodeCacheSize"), mergeDelimiter = "="),
restMapper)
val restMapper: RestPropMapper<*, *>
get() = RestPropMapper(this, DaemonJVMOptions::jvmParams)
}
public data class DaemonOptions(
public var runFilesPath: String = COMPILE_DAEMON_DEFAULT_RUN_DIR_PATH,
public var autoshutdownMemoryThreshold: Long = COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE,
public var autoshutdownIdleSeconds: Int = COMPILE_DAEMON_DEFAULT_IDLE_TIMEOUT_S,
public var forceShutdownTimeoutMilliseconds: Long = COMPILE_DAEMON_FORCE_SHUTDOWN_DEFAULT_TIMEOUT_MS,
public var clientAliveFlagPath: String? = null,
public var verbose: Boolean = false,
public var reportPerf: Boolean = false
) : OptionsGroup {
override val mappers: List>
get() = listOf(PropMapper(this, DaemonOptions::runFilesPath, fromString = { it.trimQuotes() }),
PropMapper(this, DaemonOptions::autoshutdownMemoryThreshold, fromString = { it.toLong() }, skipIf = { it == 0L }, mergeDelimiter = "="),
PropMapper(this, DaemonOptions::autoshutdownIdleSeconds, fromString = { it.toInt() }, skipIf = { it == 0 }, mergeDelimiter = "="),
PropMapper(this, DaemonOptions::forceShutdownTimeoutMilliseconds, fromString = { it.toLong() }, skipIf = { it == COMPILE_DAEMON_FORCE_SHUTDOWN_DEFAULT_TIMEOUT_MS }, mergeDelimiter = "="),
NullablePropMapper(this, DaemonOptions::clientAliveFlagPath, fromString = { it }, toString = { "${it?.trimQuotes()}" }, mergeDelimiter = "="),
BoolPropMapper(this, DaemonOptions::verbose),
BoolPropMapper(this, DaemonOptions::reportPerf))
}
fun updateSingleFileDigest(file: File, md: MessageDigest) {
DigestInputStream(file.inputStream(), md).use {
val buf = ByteArray(1024)
while (it.read(buf) != -1) {}
it.close()
}
}
fun updateForAllClasses(dir: File, md: MessageDigest) {
dir.walk().forEach { updateEntryDigest(it, md) }
}
fun updateEntryDigest(entry: File, md: MessageDigest) {
when {
entry.isDirectory
-> updateForAllClasses(entry, md)
entry.isFile &&
(entry.extension.equals("class", ignoreCase = true) ||
entry.extension.equals("jar", ignoreCase = true))
-> updateSingleFileDigest(entry, md)
// else skip
}
}
@JvmName("getFilesClasspathDigest_Files")
fun Iterable.getFilesClasspathDigest(): String {
val md = MessageDigest.getInstance(COMPILER_ID_DIGEST)
this.forEach { updateEntryDigest(it, md) }
return md.digest().joinToString("", transform = { "%02x".format(it) })
}
@JvmName("getFilesClasspathDigest_Strings")
fun Iterable.getFilesClasspathDigest(): String = map { File(it) }.getFilesClasspathDigest()
fun Iterable.distinctStringsDigest(): String =
MessageDigest.getInstance(COMPILER_ID_DIGEST)
.digest(this.distinct().sorted().joinToString("").toByteArray())
.joinToString("", transform = { "%02x".format(it) })
public data class CompilerId(
public var compilerClasspath: List = listOf(),
public var compilerDigest: String = "",
public var compilerVersion: String = ""
) : OptionsGroup {
override val mappers: List>
get() = listOf(PropMapper(this, CompilerId::compilerClasspath, toString = { it.joinToString(File.pathSeparator) }, fromString = { it.trimQuotes().split(File.pathSeparator) }),
StringPropMapper(this, CompilerId::compilerDigest),
StringPropMapper(this, CompilerId::compilerVersion))
public fun updateDigest() {
compilerDigest = compilerClasspath.getFilesClasspathDigest()
}
companion object {
@JvmStatic
public fun makeCompilerId(vararg paths: File): CompilerId = makeCompilerId(paths.asIterable())
@JvmStatic
public fun makeCompilerId(paths: Iterable): CompilerId =
CompilerId(compilerClasspath = paths.map { it.absolutePath }, compilerDigest = paths.getFilesClasspathDigest())
}
}
public fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null
public fun configureDaemonJVMOptions(opts: DaemonJVMOptions, inheritMemoryLimits: Boolean, vararg additionalParams: String): DaemonJVMOptions {
// note: sequence matters, explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
if (inheritMemoryLimits) {
ManagementFactory.getRuntimeMXBean().inputArguments.filterExtractProps(opts.mappers, "-")
}
System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let {
opts.jvmParams.addAll(
it.trimQuotes()
.split("(?