com.isyscore.cse.sdk.ISCCrossScriptEngine.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of csesdk Show documentation
Show all versions of csesdk Show documentation
iSysCore Cross Script JVM SDK
package com.isyscore.cse.sdk
import com.isyscore.kotlin.common.*
import org.slf4j.LoggerFactory
import java.io.File
import java.util.logging.Logger
import kotlin.math.log
data class ExecParam(
val paramName: String,
val paramType: String,
val paramValue: String = "")
private data class InternalCompileParam(val code: String, val outputPath: String, val params: List)
private data class InternalExecuteParam(val data: List)
private data class ParamDTO(
val binaryPath: String,
val timeout: Long = 0L,
val isTest: Boolean = false,
val params: List
)
data class CompileResult(val code: Int, val message: String, val codeId: String)
data class ExecOutput(val output: String, val error: String)
data class ExecuteResult(val code: Int, val message: String, val data: ExecOutput)
/**
* 指令集 Cross Script 引擎总控
*
* 需要在目标机器上安装 Cross Script 必备文件:
*
* **linux**:
*
* libcrossscript.so,置于 /usr/lib/ 内
*
* iscx,置于 /usr/bin/ 内
*
* **MacOS**
*
* libcrossscript.dylib,置于 /usr/local/lib/ 内
*
* iscx,置于 /usr/local/bin/ 内
*
* **Windows (仅x86_64)**
*
* crossscript.dll,置于 C:\Window\system32\ 内
*
* iscx.exe,置于 C:\Window\system32\ 内
*
* 特别说明,已支持 Apple M1 芯片
*/
object ISCCrossScriptEngine {
@JvmStatic val VERSION = 100
val logger = LoggerFactory.getLogger(ISCCrossScriptEngine::class.java)
private val SPL = if (isWindows) "\\" else "/"
private val EXEC = when {
isWindows -> "C:\\Window\\System32\\iscx.exe"
isMac -> "/usr/local/bin/iscx"
else -> "/usr/bin/iscx"
}
private val COMP_EXEC = when {
isWindows -> "C:\\Window\\System32\\isccx.exe"
isMac -> "/usr/local/bin/isccx"
else -> "/usr/bin/isccx"
}
/**
* 定义参数类型:int
*/
@JvmStatic val TYPE_INT = "01"
/**
* 定义参数类型: long
*/
@JvmStatic val TYPE_INT64 = "02"
/**
* 定义参数类型: float
*/
@JvmStatic val TYPE_FLOAT = "03"
/**
* 定义参数类型: double
*/
@JvmStatic val TYPE_DOUBLE = "04"
/**
* 定义参数类型: boolean
*/
@JvmStatic val TYPE_BOOL = "05"
/**
* 定义参数类型: string
*/
@JvmStatic val TYPE_STRING = "06"
init {
try {
System.loadLibrary("crossscript")
println("load crossscript finished")
} catch (th: Throwable) {
println("load crossscript error: $th")
}
}
private external fun execute(timeout: Long, codeId: String, params: String): String
private external fun version(): String
/**
* 环境检查,建议在脚本执行前,进行环境检查,以便了解部署是否有不完善之处
*
* 更为合理的操作是,在程序启动时,执行一次检查,后续即可不必再进行检查
*
* 当检查出有问题的项目时,将以日志形式输出到 Terminal
*/
@JvmStatic
fun environmentCheck(): Boolean {
var ret = true
if (!File(EXEC).exists()) {
logger.error("$EXEC 未正确安装")
ret = false
} else {
val vE = runCommand {
commands.add(EXEC)
commands.add("version")
}.output.trim().toIntOrNull()
if (vE == null) {
logger.error("$EXEC 太旧,不支持版本检查")
ret = false
} else {
if (vE != VERSION) {
logger.error("$EXEC 版本号为 $vE,与当前环境要求不符")
ret = false
}
}
}
if (!File(COMP_EXEC).exists()) {
logger.error("$COMP_EXEC 未正确安装")
ret = false
} else {
val vE = runCommand {
commands.add(COMP_EXEC)
commands.add("version")
}.output.trim().toIntOrNull()
if (vE == null) {
logger.error("$COMP_EXEC 太旧,不支持版本检查")
ret = false
} else {
if (vE != VERSION) {
logger.error("$COMP_EXEC 版本号为 $vE,与当前环境要求不符")
ret = false
}
}
}
val vLib = try {
version().toIntOrNull()
} catch (th: Throwable) {
null
}
if (vLib == null) {
logger.error("共享库太旧,不支持版本检查")
ret = false
} else {
if (vLib != VERSION) {
logger.error("共享库版本号为 $vLib,与当前环境要求不符")
ret = false
}
}
return ret
}
/**
* 编译 Cross Script 脚本代码
*
* @param code 要编译的脚本代码(推荐使用强类型语言,指令集内部项目建议 typejs)
* @param params 参数列表,仅需要填入参数名称和类型
* @return 编译结果
*
* @see TYPE_INT
* @see TYPE_INT64
* @see TYPE_FLOAT
* @see TYPE_DOUBLE
* @see TYPE_BOOL
* @see TYPE_STRING
*
* @see CompileResult
*/
@JvmStatic
fun compile(code: String, params: List): CompileResult {
val path = "." + SPL + "scripts" + SPL
val pjson = InternalCompileParam(
code = code,
outputPath = path,
params = params).toJson()
return runCommand {
commands.add(COMP_EXEC)
commands.add(pjson)
}.output.toObj()
}
/**
* 执行 Cross Script 的二进制程序
*
* 需要注意,执行此方法时,若产生了内存异常,将引起 Java 进程崩溃,需要在测试执行后才使用此方法来高速执行脚本
*
* @param timeout 执行超时时间,单位毫秒,设置为 0 时不使用超时限制
* @param codeId 二进制程序 ID
* @param params 参数列表
* @return 执行结果
*
* @see TYPE_INT
* @see TYPE_INT64
* @see TYPE_FLOAT
* @see TYPE_DOUBLE
* @see TYPE_BOOL
* @see TYPE_STRING
*
* @see ExecuteResult
*/
@JvmStatic
fun execute(timeout: Long, codeId: String, params: List): ExecuteResult {
val pjson = InternalExecuteParam(params).toJson()
return try {
execute(timeout, codeId, pjson).toObj()
} catch (e: Throwable) {
ExecuteResult(500, e.message ?: "unknown", ExecOutput("", ""))
}
}
/**
* 尝试执行 Cross Script 的二进制脚本
*
* 注意,这个方法用于对脚本的运行情况进行试验,性能较差,但是产生异常时不会引起 Java 进程崩溃。在正式执行前,应当用此方法进行试验
*
* @param timeout 执行超时时间,单位毫秒,设置为 0 时不使用超时限制
* @param codeId 二进制程序 ID
* @param params 参数列表
* @return 执行结果
*
* @see TYPE_INT
* @see TYPE_INT64
* @see TYPE_FLOAT
* @see TYPE_DOUBLE
* @see TYPE_BOOL
* @see TYPE_STRING
*
* @see ExecuteResult
*/
@JvmStatic
fun testExecute(timeout: Long, codeId: String, params: List): ExecuteResult {
val path = "." + SPL + "scripts" + SPL + codeId
if (!File(path).exists()) {
return ExecuteResult(400, "文件不存在", ExecOutput("", ""))
}
val pJson = ParamDTO(path, timeout, true, params).toJson()
return runCommand {
commands.add(EXEC)
commands.add(pJson)
}.output.toObj()
}
}