sbt.internal.client.ServerConnection.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of command_2.12 Show documentation
Show all versions of command_2.12 Show documentation
sbt is an interactive build tool
The newest version!
/*
* sbt
* Copyright 2023, Scala center
* Copyright 2011 - 2022, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt
package internal
package client
import java.io.IOException
import java.net.{ Socket, SocketTimeoutException }
import java.util.concurrent.atomic.AtomicBoolean
import sbt.protocol._
import sbt.internal.protocol._
import sbt.internal.util.ReadJsonFromInputStream
abstract class ServerConnection(connection: Socket) {
private val running = new AtomicBoolean(true)
private val closed = new AtomicBoolean(false)
private val retByte: Byte = '\r'.toByte
private val delimiter: Byte = '\n'.toByte
private val out = connection.getOutputStream
val thread = new Thread(s"sbt-serverconnection-${connection.getPort}") {
setDaemon(true)
override def run(): Unit = {
try {
val in = connection.getInputStream
connection.setSoTimeout(5000)
while (running.get) {
try {
val frame = ReadJsonFromInputStream(in, running, None)
if (running.get) {
Serialization
.deserializeJsonMessage(frame)
.fold(
{ errorDesc =>
val s = frame.mkString("") // new String(: Array[Byte], "UTF-8")
println(s"Got invalid chunk from server: $s \n" + errorDesc)
},
_ match {
case msg: JsonRpcRequestMessage => onRequest(msg)
case msg: JsonRpcResponseMessage => onResponse(msg)
case msg: JsonRpcNotificationMessage => onNotification(msg)
}
)
}
} catch {
case _: SocketTimeoutException => // its ok
case e: IOException => running.set(false)
}
}
} finally {
shutdown()
}
}
}
thread.start()
def sendString(message: String): Unit = this.synchronized {
val a = message.getBytes("UTF-8")
writeLine(s"""Content-Length: ${a.length + 2}""".getBytes("UTF-8"))
writeLine(Array())
writeLine(a)
}
def writeLine(a: Array[Byte]): Unit =
try {
def writeEndLine(): Unit = {
out.write(retByte.toInt)
out.write(delimiter.toInt)
out.flush
}
if (a.nonEmpty) {
out.write(a)
}
writeEndLine()
} catch {
case e: IOException =>
shutdown()
throw e
}
def onRequest(msg: JsonRpcRequestMessage): Unit
def onResponse(msg: JsonRpcResponseMessage): Unit
def onNotification(msg: JsonRpcNotificationMessage): Unit
def onShutdown(): Unit
def shutdown(): Unit = if (closed.compareAndSet(false, true)) {
if (!running.compareAndSet(true, false)) {
System.err.println("\nsbt server connection closed.")
}
try {
out.close()
connection.close()
} catch { case e: IOException => e.printStackTrace() }
onShutdown()
}
}