mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 08:27:12 -07:00
Make Kobalt reentrant.
This commit is contained in:
parent
fdcca3a1aa
commit
bace815481
7 changed files with 228 additions and 36 deletions
|
@ -26,6 +26,10 @@ class Args {
|
||||||
"actually running them")
|
"actually running them")
|
||||||
var dryRun: Boolean = false
|
var dryRun: Boolean = false
|
||||||
|
|
||||||
|
@Parameter(names = arrayOf("--force"), description = "Force a new server to be launched even if another one" +
|
||||||
|
" is already running")
|
||||||
|
var force: Boolean = false
|
||||||
|
|
||||||
@Parameter(names = arrayOf("--gc"), description = "Delete old files")
|
@Parameter(names = arrayOf("--gc"), description = "Delete old files")
|
||||||
var gc: Boolean = false
|
var gc: Boolean = false
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ import com.beust.kobalt.Plugins
|
||||||
import com.beust.kobalt.ProxyConfig
|
import com.beust.kobalt.ProxyConfig
|
||||||
import com.google.inject.Injector
|
import com.google.inject.Injector
|
||||||
import org.eclipse.aether.repository.Proxy
|
import org.eclipse.aether.repository.Proxy
|
||||||
|
import com.beust.kobalt.internal.PluginInfo
|
||||||
|
import com.google.inject.Guice
|
||||||
|
import com.google.inject.Module
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
@ -15,6 +18,18 @@ class Kobalt {
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var INJECTOR : Injector
|
lateinit var INJECTOR : Injector
|
||||||
|
|
||||||
|
fun init(module: Module) {
|
||||||
|
Kobalt.INJECTOR = Guice.createInjector(module)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add all the plugins read in kobalt-plugin.xml to the Plugins singleton, so that code
|
||||||
|
// in the build file that calls Plugins.findPlugin() can find them (code in the
|
||||||
|
// build file do not have access to the KobaltContext).
|
||||||
|
//
|
||||||
|
val pluginInfo = Kobalt.INJECTOR.getInstance(PluginInfo::class.java)
|
||||||
|
pluginInfo.plugins.forEach { Plugins.addPluginInstance(it) }
|
||||||
|
}
|
||||||
|
|
||||||
var context: KobaltContext? = null
|
var context: KobaltContext? = null
|
||||||
|
|
||||||
val proxyConfig = with(Kobalt.context?.settings?.proxy) {
|
val proxyConfig = with(Kobalt.context?.settings?.proxy) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.beust.kobalt.api.Kobalt
|
||||||
import com.beust.kobalt.api.PluginTask
|
import com.beust.kobalt.api.PluginTask
|
||||||
import com.beust.kobalt.api.Project
|
import com.beust.kobalt.api.Project
|
||||||
import com.beust.kobalt.app.*
|
import com.beust.kobalt.app.*
|
||||||
|
import com.beust.kobalt.app.remote.DependencyData
|
||||||
import com.beust.kobalt.app.remote.KobaltClient
|
import com.beust.kobalt.app.remote.KobaltClient
|
||||||
import com.beust.kobalt.app.remote.KobaltServer
|
import com.beust.kobalt.app.remote.KobaltServer
|
||||||
import com.beust.kobalt.internal.Gc
|
import com.beust.kobalt.internal.Gc
|
||||||
|
@ -18,7 +19,6 @@ import com.beust.kobalt.maven.Http
|
||||||
import com.beust.kobalt.maven.dependency.FileDependency
|
import com.beust.kobalt.maven.dependency.FileDependency
|
||||||
import com.beust.kobalt.misc.*
|
import com.beust.kobalt.misc.*
|
||||||
import com.google.common.collect.HashMultimap
|
import com.google.common.collect.HashMultimap
|
||||||
import com.google.inject.Guice
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
@ -42,7 +42,7 @@ private fun parseArgs(argv: Array<String>): Main.RunInfo {
|
||||||
|
|
||||||
fun mainNoExit(argv: Array<String>): Int {
|
fun mainNoExit(argv: Array<String>): Int {
|
||||||
val (jc, args) = parseArgs(argv)
|
val (jc, args) = parseArgs(argv)
|
||||||
Kobalt.INJECTOR = Guice.createInjector(MainModule(args, KobaltSettings.readSettingsXml()))
|
Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
|
||||||
val result = Kobalt.INJECTOR.getInstance(Main::class.java).run {
|
val result = Kobalt.INJECTOR.getInstance(Main::class.java).run {
|
||||||
val runResult = run(jc, args, argv)
|
val runResult = run(jc, args, argv)
|
||||||
pluginInfo.shutdown()
|
pluginInfo.shutdown()
|
||||||
|
@ -64,8 +64,8 @@ private class Main @Inject constructor(
|
||||||
val github: GithubApi2,
|
val github: GithubApi2,
|
||||||
val updateKobalt: UpdateKobalt,
|
val updateKobalt: UpdateKobalt,
|
||||||
val client: KobaltClient,
|
val client: KobaltClient,
|
||||||
val server: KobaltServer,
|
|
||||||
val pluginInfo: PluginInfo,
|
val pluginInfo: PluginInfo,
|
||||||
|
val dependencyData: DependencyData,
|
||||||
val projectGenerator: ProjectGenerator,
|
val projectGenerator: ProjectGenerator,
|
||||||
val resolveDependency: ResolveDependency) {
|
val resolveDependency: ResolveDependency) {
|
||||||
|
|
||||||
|
@ -91,21 +91,12 @@ private class Main @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun run(jc: JCommander, args: Args, argv: Array<String>): Int {
|
fun run(jc: JCommander, args: Args, argv: Array<String>): Int {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Install plug-ins requested from the command line
|
// Install plug-ins requested from the command line
|
||||||
//
|
//
|
||||||
val pluginClassLoader = installCommandLinePlugins(args)
|
val pluginClassLoader = installCommandLinePlugins(args)
|
||||||
|
|
||||||
//
|
|
||||||
// Add all the plugins read in kobalt-plugin.xml to the Plugins singleton, so that code
|
|
||||||
// in the build file that calls Plugins.findPlugin() can find them (code in the
|
|
||||||
// build file do not have access to the KobaltContext).
|
|
||||||
//
|
|
||||||
pluginInfo.plugins.forEach { Plugins.addPluginInstance(it) }
|
|
||||||
|
|
||||||
// val data = dependencyData.dependenciesDataFor(homeDir("kotlin/klaxon/kobalt/src/Build.kt"), Args())
|
|
||||||
// println("Data: $data")
|
|
||||||
|
|
||||||
// --listTemplates
|
// --listTemplates
|
||||||
if (args.listTemplates) {
|
if (args.listTemplates) {
|
||||||
Templates().list(pluginInfo)
|
Templates().list(pluginInfo)
|
||||||
|
@ -166,7 +157,7 @@ private class Main @Inject constructor(
|
||||||
} else if (args.usage) {
|
} else if (args.usage) {
|
||||||
jc.usage()
|
jc.usage()
|
||||||
} else if (args.serverMode) {
|
} else if (args.serverMode) {
|
||||||
server.run()
|
val port = KobaltServer(args.force, { pluginInfo.shutdown()}).call()
|
||||||
} else {
|
} else {
|
||||||
// Options that don't need Build.kt to be parsed first
|
// Options that don't need Build.kt to be parsed first
|
||||||
if (args.gc) {
|
if (args.gc) {
|
||||||
|
@ -213,6 +204,9 @@ private class Main @Inject constructor(
|
||||||
//
|
//
|
||||||
plugins.applyPlugins(Kobalt.context!!, allProjects)
|
plugins.applyPlugins(Kobalt.context!!, allProjects)
|
||||||
|
|
||||||
|
// DONOTCOMMIT
|
||||||
|
// val data = dependencyData.dependenciesDataFor(homeDir("kotlin/klaxon/kobalt/src/Build.kt"), Args())
|
||||||
|
// println("Data: $data")
|
||||||
|
|
||||||
if (args.projectInfo) {
|
if (args.projectInfo) {
|
||||||
// --projectInfo
|
// --projectInfo
|
||||||
|
|
|
@ -1,18 +1,128 @@
|
||||||
package com.beust.kobalt.app.remote
|
package com.beust.kobalt.app.remote
|
||||||
|
|
||||||
|
import com.beust.kobalt.Args
|
||||||
import com.beust.kobalt.SystemProperties
|
import com.beust.kobalt.SystemProperties
|
||||||
|
import com.beust.kobalt.api.Kobalt
|
||||||
|
import com.beust.kobalt.app.MainModule
|
||||||
|
import com.beust.kobalt.homeDir
|
||||||
|
import com.beust.kobalt.internal.KobaltSettings
|
||||||
|
import com.beust.kobalt.misc.KFiles
|
||||||
import com.beust.kobalt.misc.log
|
import com.beust.kobalt.misc.log
|
||||||
|
import com.beust.kobalt.misc.warn
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import java.io.BufferedReader
|
import com.google.inject.Guice
|
||||||
import java.io.InputStreamReader
|
import java.io.*
|
||||||
import java.io.PrintWriter
|
|
||||||
import java.net.ConnectException
|
import java.net.ConnectException
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Executors
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
fun main(argv: Array<String>) {
|
||||||
|
Kobalt.INJECTOR = Guice.createInjector(MainModule(Args(), KobaltSettings.readSettingsXml()))
|
||||||
|
val port = ServerProcess().launch()
|
||||||
|
println("SERVER RUNNING ON PORT $port")
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServerProcess {
|
||||||
|
val SERVER_FILE = KFiles.joinDir(homeDir(KFiles.KOBALT_DOT_DIR, "kobaltServer.properties"))
|
||||||
|
val KEY_PORT = "port"
|
||||||
|
val executor = Executors.newFixedThreadPool(5)
|
||||||
|
|
||||||
|
fun launch() : Int {
|
||||||
|
var port = launchPrivate()
|
||||||
|
while (port == 0) {
|
||||||
|
executor.submit {
|
||||||
|
KobaltServer(force = true, shutdownCallback = {}).call()
|
||||||
|
}
|
||||||
|
// launchServer(ProcessUtil.findAvailablePort())
|
||||||
|
port = launchPrivate()
|
||||||
|
}
|
||||||
|
return port
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun launchPrivate() : Int {
|
||||||
|
var result = 0
|
||||||
|
File(SERVER_FILE).let { serverFile ->
|
||||||
|
if (serverFile.exists()) {
|
||||||
|
val properties = Properties().apply {
|
||||||
|
load(FileReader(serverFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val socket = Socket("localhost", result)
|
||||||
|
val outgoing = PrintWriter(socket.outputStream, true)
|
||||||
|
val c: String = """{ "name": "ping"}"""
|
||||||
|
outgoing.println(c)
|
||||||
|
val ins = BufferedReader(InputStreamReader(socket.inputStream))
|
||||||
|
var line = ins.readLine()
|
||||||
|
val jo = JsonParser().parse(line) as JsonObject
|
||||||
|
val jsonData = jo["data"]?.asString
|
||||||
|
val dataObject = JsonParser().parse(jsonData) as JsonObject
|
||||||
|
val received = JsonParser().parse(dataObject["received"].asString) as JsonObject
|
||||||
|
if (received["name"].asString == "ping") {
|
||||||
|
result = properties.getProperty(KEY_PORT).toInt()
|
||||||
|
}
|
||||||
|
} catch(ex: IOException) {
|
||||||
|
log(1, "Couldn't connect to current server, launching a new one")
|
||||||
|
Thread.sleep(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun launchServer(port: Int) {
|
||||||
|
val kobaltJar = File(KFiles().kobaltJar[0])
|
||||||
|
log(1, "Kobalt jar: $kobaltJar")
|
||||||
|
if (! kobaltJar.exists()) {
|
||||||
|
warn("Can't find the jar file " + kobaltJar.absolutePath + " can't be found")
|
||||||
|
} else {
|
||||||
|
val args = listOf("java",
|
||||||
|
"-classpath", KFiles().kobaltJar.joinToString(File.pathSeparator),
|
||||||
|
"com.beust.kobalt.MainKt",
|
||||||
|
"--dev", "--server", "--port", port.toString())
|
||||||
|
val pb = ProcessBuilder(args)
|
||||||
|
// pb.directory(File(directory))
|
||||||
|
pb.inheritIO()
|
||||||
|
// pb.environment().put("JAVA_HOME", ProjectJdkTable.getInstance().allJdks[0].homePath)
|
||||||
|
val tempFile = createTempFile("kobalt")
|
||||||
|
pb.redirectOutput(tempFile)
|
||||||
|
warn("Launching " + args.joinToString(" "))
|
||||||
|
warn("Server output in: $tempFile")
|
||||||
|
val process = pb.start()
|
||||||
|
val errorCode = process.waitFor()
|
||||||
|
if (errorCode == 0) {
|
||||||
|
log(1, "Server exiting")
|
||||||
|
} else {
|
||||||
|
log(1, "Server exiting with error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createServerFile(port: Int, force: Boolean) : Boolean {
|
||||||
|
if (File(SERVER_FILE).exists() && ! force) {
|
||||||
|
log(1, "Server file $SERVER_FILE already exists, is another server running?")
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
Properties().apply {
|
||||||
|
put(KEY_PORT, port.toString())
|
||||||
|
}.store(FileWriter(SERVER_FILE), "")
|
||||||
|
log(2, "KobaltServer created $SERVER_FILE")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteServerFile() {
|
||||||
|
log(1, "KobaltServer deleting $SERVER_FILE")
|
||||||
|
File(SERVER_FILE).delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class KobaltClient @Inject constructor() : Runnable {
|
class KobaltClient @Inject constructor() : Runnable {
|
||||||
var outgoing: PrintWriter? = null
|
var outgoing: PrintWriter? = null
|
||||||
|
|
||||||
|
|
39
src/main/kotlin/com/beust/kobalt/app/remote/KobaltHub.kt
Normal file
39
src/main/kotlin/com/beust/kobalt/app/remote/KobaltHub.kt
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package com.beust.kobalt.app.remote
|
||||||
|
|
||||||
|
import com.beust.kobalt.Args
|
||||||
|
import com.beust.kobalt.api.Kobalt
|
||||||
|
import com.beust.kobalt.app.MainModule
|
||||||
|
import com.beust.kobalt.internal.KobaltSettings
|
||||||
|
import com.beust.kobalt.internal.remote.ICommand
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
|
enum class Command(val n: Int, val command: ICommand) {
|
||||||
|
GET_DEPENDENCIES(1, Kobalt.INJECTOR.getInstance(GetDependenciesCommand::class.java));
|
||||||
|
companion object {
|
||||||
|
val commandMap = hashMapOf<Int, ICommand>()
|
||||||
|
fun commandFor(n: Int) = values().filter { it.n == n }[0].command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KobaltHub(val dependencyData: DependencyData) {
|
||||||
|
val args = Args()
|
||||||
|
|
||||||
|
fun runCommand(n: Int) : String {
|
||||||
|
val data =
|
||||||
|
when(n) {
|
||||||
|
1 -> Gson().toJson(
|
||||||
|
dependencyData.dependenciesDataFor("/Users/beust/kotlin/klaxon/kobalt/src/Build.kt", args))
|
||||||
|
else -> throw RuntimeException("Unknown command")
|
||||||
|
}
|
||||||
|
println("Data: $data")
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(argv: Array<String>) {
|
||||||
|
Kobalt.init(MainModule(Args(), KobaltSettings.readSettingsXml()))
|
||||||
|
val dependencyData = Kobalt.INJECTOR.getInstance(DependencyData::class.java)
|
||||||
|
val json = KobaltHub(dependencyData).runCommand(1)
|
||||||
|
val dd = Gson().fromJson(json, DependencyData.GetDependenciesData::class.java)
|
||||||
|
println("Data2: $dd")
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
package com.beust.kobalt.app.remote
|
package com.beust.kobalt.app.remote
|
||||||
|
|
||||||
import com.beust.kobalt.Args
|
|
||||||
import com.beust.kobalt.api.Kobalt
|
import com.beust.kobalt.api.Kobalt
|
||||||
import com.beust.kobalt.homeDir
|
import com.beust.kobalt.homeDir
|
||||||
import com.beust.kobalt.internal.PluginInfo
|
|
||||||
import com.beust.kobalt.internal.remote.CommandData
|
import com.beust.kobalt.internal.remote.CommandData
|
||||||
import com.beust.kobalt.internal.remote.ICommandSender
|
import com.beust.kobalt.internal.remote.ICommandSender
|
||||||
import com.beust.kobalt.internal.remote.PingCommand
|
import com.beust.kobalt.internal.remote.PingCommand
|
||||||
|
@ -12,15 +10,14 @@ import com.beust.kobalt.misc.log
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import com.google.inject.Singleton
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
@Singleton
|
class KobaltServer(val force: Boolean, val shutdownCallback: () -> Unit) : Callable<Int>, ICommandSender {
|
||||||
class KobaltServer @Inject constructor(val args: Args, val pluginInfo: PluginInfo) : Runnable, ICommandSender {
|
|
||||||
// var outgoing: PrintWriter? = null
|
// var outgoing: PrintWriter? = null
|
||||||
val pending = arrayListOf<CommandData>()
|
val pending = arrayListOf<CommandData>()
|
||||||
|
|
||||||
|
@ -29,28 +26,34 @@ class KobaltServer @Inject constructor(val args: Args, val pluginInfo: PluginInf
|
||||||
Kobalt.INJECTOR.getInstance(it).let { Pair(it.name, it) }
|
Kobalt.INJECTOR.getInstance(it).let { Pair(it.name, it) }
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
|
||||||
override fun run() {
|
override fun call() : Int {
|
||||||
|
val port = ProcessUtil.findAvailablePort()
|
||||||
try {
|
try {
|
||||||
if (createServerFile(args.port)) {
|
if (createServerFile(port, force)) {
|
||||||
privateRun()
|
privateRun(port)
|
||||||
}
|
}
|
||||||
} catch(ex: Exception) {
|
} catch(ex: Exception) {
|
||||||
ex.printStackTrace()
|
ex.printStackTrace()
|
||||||
} finally {
|
} finally {
|
||||||
deleteServerFile()
|
deleteServerFile()
|
||||||
}
|
}
|
||||||
|
return port
|
||||||
}
|
}
|
||||||
|
|
||||||
val SERVER_FILE = KFiles.joinDir(homeDir(KFiles.KOBALT_DOT_DIR, "kobaltServer.properties"))
|
val SERVER_FILE = KFiles.joinDir(homeDir(KFiles.KOBALT_DOT_DIR, "kobaltServer.properties"))
|
||||||
val KEY_PORT = "port"
|
val KEY_PORT = "port"
|
||||||
|
val KEY_PID = "pid"
|
||||||
|
|
||||||
private fun createServerFile(port: Int) : Boolean {
|
private fun createServerFile(port: Int, force: Boolean) : Boolean {
|
||||||
if (File(SERVER_FILE).exists()) {
|
if (File(SERVER_FILE).exists() && ! force) {
|
||||||
log(1, "Server file $SERVER_FILE already exists, is another server running?")
|
log(1, "Server file $SERVER_FILE already exists, is another server running?")
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
|
val processName = ManagementFactory.getRuntimeMXBean().name
|
||||||
|
val pid = processName.split("@")[0]
|
||||||
Properties().apply {
|
Properties().apply {
|
||||||
put(KEY_PORT, port.toString())
|
put(KEY_PORT, port.toString())
|
||||||
|
put(KEY_PID, pid)
|
||||||
}.store(FileWriter(SERVER_FILE), "")
|
}.store(FileWriter(SERVER_FILE), "")
|
||||||
log(2, "KobaltServer created $SERVER_FILE")
|
log(2, "KobaltServer created $SERVER_FILE")
|
||||||
return true
|
return true
|
||||||
|
@ -84,12 +87,10 @@ class KobaltServer @Inject constructor(val args: Args, val pluginInfo: PluginInf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun privateRun() {
|
private fun privateRun(port: Int) {
|
||||||
val portNumber = args.port
|
log(1, "Listening to port $port")
|
||||||
|
|
||||||
log(1, "Listening to port $portNumber")
|
|
||||||
var quit = false
|
var quit = false
|
||||||
serverInfo = ServerInfo(portNumber)
|
serverInfo = ServerInfo(port)
|
||||||
while (!quit) {
|
while (!quit) {
|
||||||
if (pending.size > 0) {
|
if (pending.size > 0) {
|
||||||
log(1, "Emptying the queue, size $pending.size()")
|
log(1, "Emptying the queue, size $pending.size()")
|
||||||
|
@ -114,10 +115,13 @@ class KobaltServer @Inject constructor(val args: Args, val pluginInfo: PluginInf
|
||||||
// Done, send a quit to the client
|
// Done, send a quit to the client
|
||||||
sendData(CommandData("quit", ""))
|
sendData(CommandData("quit", ""))
|
||||||
|
|
||||||
|
// Clean up all the plug-in actors
|
||||||
|
shutdownCallback()
|
||||||
line = serverInfo.reader.readLine()
|
line = serverInfo.reader.readLine()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line == null) {
|
if (line == null) {
|
||||||
|
log(1, "Received null line, resetting the server")
|
||||||
serverInfo.reset()
|
serverInfo.reset()
|
||||||
}
|
}
|
||||||
} catch(ex: SocketException) {
|
} catch(ex: SocketException) {
|
||||||
|
@ -130,8 +134,6 @@ class KobaltServer @Inject constructor(val args: Args, val pluginInfo: PluginInf
|
||||||
}
|
}
|
||||||
log(1, "Command failed: ${ex.message}")
|
log(1, "Command failed: ${ex.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginInfo.shutdown()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,4 +157,5 @@ class KobaltServer @Inject constructor(val args: Args, val pluginInfo: PluginInf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
src/main/kotlin/com/beust/kobalt/app/remote/ProcessUtil.kt
Normal file
27
src/main/kotlin/com/beust/kobalt/app/remote/ProcessUtil.kt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package com.beust.kobalt.app.remote
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.Socket
|
||||||
|
|
||||||
|
class ProcessUtil {
|
||||||
|
companion object {
|
||||||
|
fun findAvailablePort(): Int {
|
||||||
|
for (i in 1234..65000) {
|
||||||
|
if (isPortAvailable(i)) return i
|
||||||
|
}
|
||||||
|
throw IllegalArgumentException("Couldn't find any port available, something is very wrong")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPortAvailable(port: Int): Boolean {
|
||||||
|
var s: Socket? = null
|
||||||
|
try {
|
||||||
|
s = Socket("localhost", port)
|
||||||
|
return false
|
||||||
|
} catch(ex: IOException) {
|
||||||
|
return true
|
||||||
|
} finally {
|
||||||
|
s?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue