mirror of
https://github.com/smyalygames/checklist-tester.git
synced 2025-05-18 14:34:12 +02:00
feat(connector): change VDMJ to use interpreter
This commit is contained in:
parent
b784ab9799
commit
e781c12d22
@ -1,12 +1,14 @@
|
|||||||
package io.anthonyberg.connector.routes
|
package io.anthonyberg.connector.routes
|
||||||
|
|
||||||
import io.anthonyberg.connector.shared.vdmj.vdmjExecute
|
import io.anthonyberg.connector.shared.vdmj.VDMJ
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.server.response.*
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Route.vdmjRouting() {
|
fun Route.vdmjRouting() {
|
||||||
|
val vdmj = VDMJ()
|
||||||
|
|
||||||
route("/vdmj") {
|
route("/vdmj") {
|
||||||
get("{exp?}") {
|
get("{exp?}") {
|
||||||
val exp = call.parameters["exp"] ?: return@get call.respondText(
|
val exp = call.parameters["exp"] ?: return@get call.respondText(
|
||||||
@ -15,7 +17,7 @@ fun Route.vdmjRouting() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TODO output is empty string after first request
|
// TODO output is empty string after first request
|
||||||
val result = vdmjExecute(exp)
|
val result = vdmj.run(exp)
|
||||||
|
|
||||||
call.respond(result)
|
call.respond(result)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package io.anthonyberg.connector.shared.entity
|
package io.anthonyberg.connector.shared.entity
|
||||||
|
|
||||||
import com.fujitsu.vdmj.ExitStatus
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class VDMJExpression(val output: String, val exitStatus: ExitStatus)
|
data class VDMJExpression(val output: String)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.anthonyberg.connector.shared.vdmj
|
package io.anthonyberg.connector.shared.vdmj
|
||||||
|
|
||||||
|
import com.fujitsu.vdmj.ExitStatus
|
||||||
import com.fujitsu.vdmj.Settings
|
import com.fujitsu.vdmj.Settings
|
||||||
import com.fujitsu.vdmj.config.Properties
|
import com.fujitsu.vdmj.config.Properties
|
||||||
import com.fujitsu.vdmj.messages.Console
|
import com.fujitsu.vdmj.messages.Console
|
||||||
@ -8,62 +9,101 @@ import com.fujitsu.vdmj.plugins.EventHub
|
|||||||
import com.fujitsu.vdmj.plugins.Lifecycle
|
import com.fujitsu.vdmj.plugins.Lifecycle
|
||||||
import com.fujitsu.vdmj.plugins.VDMJ
|
import com.fujitsu.vdmj.plugins.VDMJ
|
||||||
import io.anthonyberg.connector.shared.entity.VDMJExpression
|
import io.anthonyberg.connector.shared.entity.VDMJExpression
|
||||||
import java.io.ByteArrayOutputStream
|
import kotlinx.coroutines.*
|
||||||
|
import java.io.*
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.io.path.pathString
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
/**
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
* Handler for the VDM Model
|
class VDMJ {
|
||||||
*/
|
|
||||||
fun vdmjExecute(expression: String): VDMJExpression {
|
|
||||||
Settings.mainClass = VDMJ::class.java
|
|
||||||
Properties.init()
|
|
||||||
|
|
||||||
val lifecycle: Lifecycle = createLifecycle(expression)
|
|
||||||
|
|
||||||
// Create a ByteArrayOutputStream to capture the output
|
// Create a ByteArrayOutputStream to capture the output
|
||||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
private val byteArrayOutputStream = ByteArrayOutputStream()
|
||||||
val printStream = ConsolePrintWriter(byteArrayOutputStream)
|
private val printStream = ConsolePrintWriter(byteArrayOutputStream)
|
||||||
|
|
||||||
|
private val inputStream = PipedInputStream()
|
||||||
|
private val inputOutput = PipedOutputStream(inputStream)
|
||||||
|
private val bufferedReader = BufferedReader(InputStreamReader(inputStream))
|
||||||
|
private val writer = BufferedWriter(OutputStreamWriter(inputOutput))
|
||||||
|
|
||||||
// Save the old PrintStreams
|
// Save the old PrintStreams
|
||||||
val oldOut = Console.out
|
private val oldOut = Console.out
|
||||||
val oldErr = Console.err
|
private val oldErr = Console.err
|
||||||
|
private val oldIn = Console.`in`
|
||||||
|
|
||||||
// Redirect Console's PrintStreams to the new PrintStream
|
private lateinit var exitStatus: ExitStatus
|
||||||
Console.out = printStream
|
|
||||||
Console.err = printStream
|
|
||||||
|
|
||||||
// TODO check if there is actually a memory leak or if it is just Java
|
/**
|
||||||
val exitStatus = lifecycle.run()
|
* Starts VDMJ interpreter
|
||||||
|
*/
|
||||||
|
init {
|
||||||
|
Settings.mainClass = VDMJ::class.java
|
||||||
|
Properties.init()
|
||||||
|
|
||||||
// Reset Console's PrintStreams to the old PrintStreams
|
// Redirect Console's PrintStreams to the new PrintStream
|
||||||
Console.out = oldOut
|
Console.out = printStream
|
||||||
Console.err = oldErr
|
Console.err = printStream
|
||||||
|
Console.`in` = bufferedReader
|
||||||
|
|
||||||
// Convert the captured output to a string
|
val lifecycle: Lifecycle = createLifecycle()
|
||||||
val console = byteArrayOutputStream.toString()
|
|
||||||
|
|
||||||
// Reset the ByteArrayOutputStream
|
// Start a coroutine for VDMJ to run in
|
||||||
byteArrayOutputStream.reset()
|
GlobalScope.launch {
|
||||||
|
exitStatus = lifecycle.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resets VDMJ's EventHub after closing lifecycle
|
|
||||||
EventHub.reset()
|
|
||||||
|
|
||||||
val output = VDMJExpression(output = console, exitStatus = exitStatus)
|
/**
|
||||||
|
* Creates VDMJ Lifecycle with interpreter mode
|
||||||
|
*/
|
||||||
|
private fun createLifecycle(): Lifecycle {
|
||||||
|
val vdmPath = Paths.get("src/main/resources/checklist.vdmsl")
|
||||||
|
|
||||||
return output
|
// Creates the arguments for VDMJ - i.e. where the file is located
|
||||||
|
val vdmArgs = arrayOf(vdmPath.pathString, "-vdmsl", "-i", "-q")
|
||||||
|
|
||||||
// exitProcess(if (lifecycle.run() == ExitStatus.EXIT_OK) 0 else 1)
|
return Lifecycle(vdmArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun cleanup() {
|
||||||
* Creates arguments for VDMJ
|
// Reset Console's PrintStreams to the old PrintStreams
|
||||||
*/
|
Console.out = oldOut
|
||||||
private fun createLifecycle(command: String): Lifecycle {
|
Console.err = oldErr
|
||||||
val vdmPath = Paths.get( "src/main/resources/checklist.vdmsl")
|
Console.`in` = oldIn
|
||||||
|
|
||||||
// Creates the arguments for VDMJ - i.e. where the file is located
|
// Reset the ByteArrayOutputStream
|
||||||
val vdmArgs = arrayOf(vdmPath.pathString, "-vdmsl", "-e", command, "-q", "-w")
|
byteArrayOutputStream.reset()
|
||||||
|
|
||||||
return Lifecycle(vdmArgs)
|
// Resets VDMJ's EventHub after closing lifecycle
|
||||||
|
EventHub.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs VDM command
|
||||||
|
*/
|
||||||
|
suspend fun run(command: String): VDMJExpression {
|
||||||
|
// Clean previous console outputs
|
||||||
|
byteArrayOutputStream.reset()
|
||||||
|
|
||||||
|
// Run commands
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
writer.write(command)
|
||||||
|
writer.write(System.lineSeparator())
|
||||||
|
writer.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
var output = byteArrayOutputStream.toString()
|
||||||
|
|
||||||
|
while(!this::exitStatus.isInitialized and output.isEmpty()) {
|
||||||
|
delay(10)
|
||||||
|
|
||||||
|
// Convert the captured output to a string
|
||||||
|
output = byteArrayOutputStream.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear console output again, just to be kind
|
||||||
|
byteArrayOutputStream.reset()
|
||||||
|
|
||||||
|
return VDMJExpression(output = output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user