diff --git a/drivers/jvm/core/build.gradle b/drivers/jvm/core/build.gradle index 28b2d172..bcb167d3 100644 --- a/drivers/jvm/core/build.gradle +++ b/drivers/jvm/core/build.gradle @@ -13,8 +13,8 @@ ext { dependencies { compileOnly 'org.apache.tomcat:annotations-api:6.0.53' - implementation 'au.com.dius.pact.core:model:4.5.9' - implementation 'au.com.dius.pact.core:support:4.5.9' + implementation 'au.com.dius.pact.core:model:4.5.12' + implementation 'au.com.dius.pact.core:support:4.5.12' implementation 'com.google.guava:guava:33.2.0-jre' implementation 'com.vdurmont:semver4j:3.1.0' implementation 'commons-codec:commons-codec:1.17.0' @@ -25,7 +25,6 @@ dependencies { implementation 'io.grpc:grpc-protobuf:1.66.0' implementation 'io.grpc:grpc-stub:1.66.0' implementation 'io.hotmoka:toml4j:0.7.3' - implementation 'jakarta.json:jakarta.json-api:2.1.3' implementation 'org.apache.commons:commons-lang3:3.14.0' implementation 'org.apache.httpcomponents.client5:httpclient5-fluent:5.3.1' implementation 'org.apache.tika:tika-core:2.9.2' diff --git a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/ChildProcess.kt b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/ChildProcess.kt index 53476640..9eb6c775 100644 --- a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/ChildProcess.kt +++ b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/ChildProcess.kt @@ -1,12 +1,12 @@ package io.pact.plugins.jvm.core +import au.com.dius.pact.core.support.json.JsonException +import au.com.dius.pact.core.support.json.JsonParser +import au.com.dius.pact.core.support.json.JsonValue import io.github.oshai.kotlinlogging.KotlinLogging import java.io.StringReader import java.lang.Thread.sleep import java.util.concurrent.LinkedBlockingDeque -import jakarta.json.Json -import jakarta.json.JsonObject -import jakarta.json.stream.JsonParsingException private val logger = KotlinLogging.logger {} @@ -26,7 +26,7 @@ open class ChildProcess( private lateinit var errorThread: Thread private lateinit var ioThread: Thread private lateinit var process: Process - val channel: LinkedBlockingDeque = LinkedBlockingDeque() + val channel: LinkedBlockingDeque = LinkedBlockingDeque() /** * Starts the child process and attach threads to read the standard output and error. Will scan the standard output @@ -47,9 +47,9 @@ open class ChildProcess( if (line.trim().startsWith("{")) { logger.debug { "Got JSON message from plugin process" } try { - val jsonReader = Json.createReader(StringReader(line.trim())); - channel.offer(jsonReader.readObject()) - } catch (ex: JsonParsingException) { + val json = JsonParser.parseReader(StringReader(line.trim())) + channel.offer(json) + } catch (ex: JsonException) { logger.debug(ex) { "Failed to parse JSON message, ignoring it" } } } diff --git a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/Json.kt b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/Json.kt index cb8c9e78..55208b1c 100644 --- a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/Json.kt +++ b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/Json.kt @@ -1,13 +1,5 @@ package io.pact.plugins.jvm.core -import jakarta.json.JsonNumber -import jakarta.json.JsonString -import jakarta.json.JsonValue +import au.com.dius.pact.core.support.json.JsonValue -fun toInteger(value: JsonValue?) = - if (value is JsonNumber) value.intValue() - else null - -fun toString(value: JsonValue?) = - if (value is JsonString) value.string - else value?.toString() +fun toInteger(value: JsonValue?) = value?.asNumber()?.toInt() diff --git a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginDownloader.kt b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginDownloader.kt index 4bd4d350..d8934ed2 100644 --- a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginDownloader.kt +++ b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginDownloader.kt @@ -2,11 +2,9 @@ package io.pact.plugins.jvm.core import au.com.dius.pact.core.support.Result import au.com.dius.pact.core.support.isNotEmpty +import au.com.dius.pact.core.support.json.JsonParser +import au.com.dius.pact.core.support.json.JsonValue import io.github.oshai.kotlinlogging.KotlinLogging -import jakarta.json.Json -import jakarta.json.JsonObject -import jakarta.json.JsonString -import jakarta.json.JsonValue import org.apache.commons.codec.digest.DigestUtils import org.apache.commons.io.FilenameUtils import org.apache.commons.io.IOUtils @@ -39,26 +37,25 @@ object DefaultPluginDownloader: PluginDownloader { is Result.Ok -> response.value is Result.Err -> return response } - return if (response is JsonObject) { - val tagName = response["tag_name"] + return if (response.isObject) { + val tagName = response["tag_name"].asString() if (tagName != null) { - val tag = asString(tagName) - logger.debug { "Found tag $tag" } + logger.debug { "Found tag $tagName" } val url = if (sourceUrl.endsWith("/latest")) { sourceUrl.removeSuffix("/latest") } else { - sourceUrl.removeSuffix("/tag/$tag") + sourceUrl.removeSuffix("/tag/$tagName") } - when (val manifestJsonResult = downloadJsonFromGithub(url, tag, "pact-plugin.json")) { + when (val manifestJsonResult = downloadJsonFromGithub(url, tagName, "pact-plugin.json")) { is Result.Ok -> { val manifestJson = manifestJsonResult.value - if (manifestJson is JsonObject) { + if (manifestJson.isObject) { val pluginDirs = File(DefaultPluginManager.pluginInstallDirectory()) if (!pluginDirs.exists()) { pluginDirs.mkdirs() } - val pluginName = asString(manifestJson["name"]) - val pluginVersion = asString(manifestJson["version"]) + val pluginName = manifestJson["name"].asString() + val pluginVersion = manifestJson["version"].asString() val pluginDir = File(pluginDirs, "${pluginName}-${pluginVersion}") pluginDir.mkdir() val manifest = DefaultPactPluginManifest.fromJson(pluginDir, manifestJson) @@ -67,7 +64,7 @@ object DefaultPluginDownloader: PluginDownloader { manifestFile.writeText(manifestJson.toString()) logger.debug { "Installing plugin ${manifest.name} version ${manifest.version}" } - when (val result = downloadPluginExecutable(manifest, pluginDir, url, tag)) { + when (val result = downloadPluginExecutable(manifest, pluginDir, url, tagName)) { is Result.Ok -> Result.Ok(manifest) is Result.Err -> result } @@ -331,14 +328,6 @@ object DefaultPluginDownloader: PluginDownloader { return os to osArch } - private fun asString(value: JsonValue?): String { - return when (value?.valueType) { - JsonValue.ValueType.STRING -> (value as JsonString).string - null -> "null" - else -> value.toString() - } - } - private fun downloadJsonFromGithub(url: String, tag: String, fileName: String) = fetchJsonFromUrl("$url/download/$tag/$fileName") @@ -352,7 +341,7 @@ object DefaultPluginDownloader: PluginDownloader { .returnContent() .asString() logger.debug { "Got response $json" } - Result.Ok(Json.createReader(StringReader(json)).readValue()) + Result.Ok(JsonParser.parseString(json)) } catch (ex: RuntimeException) { logger.error(ex) { "Failed to fetch JSON from URL" } Result.Err("Failed to fetch JSON from URL: ${ex.message}") diff --git a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginManager.kt b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginManager.kt index b4338fe4..696fd936 100644 --- a/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginManager.kt +++ b/drivers/jvm/core/src/main/kotlin/io/pact/plugins/jvm/core/PluginManager.kt @@ -22,6 +22,7 @@ import au.com.dius.pact.core.support.Json.toJson import au.com.dius.pact.core.support.Result import au.com.dius.pact.core.support.Utils.lookupEnvironmentValue import au.com.dius.pact.core.support.isNotEmpty +import au.com.dius.pact.core.support.json.JsonParser import au.com.dius.pact.core.support.json.JsonValue import au.com.dius.pact.core.support.mapError import com.google.protobuf.ByteString @@ -52,9 +53,6 @@ import java.lang.Runtime.getRuntime import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executor import java.util.concurrent.TimeUnit -import jakarta.json.Json -import jakarta.json.JsonArray -import jakarta.json.JsonObject private val logger = KotlinLogging.logger {} @@ -179,10 +177,10 @@ data class DefaultPactPluginManifest( companion object { @JvmStatic - fun fromJson(pluginDir: File, pluginJson: JsonObject): PactPluginManifest { - val entryPoints = if (pluginJson.containsKey("entryPoints")) { + fun fromJson(pluginDir: File, pluginJson: JsonValue): PactPluginManifest { + val entryPoints = if (pluginJson.has("entryPoints")) { when (val ep = pluginJson["entryPoints"]) { - is JsonObject -> ep.entries.associate { it.key to toString(it.value) } + is JsonValue.Object -> ep.entries.entries.associate { it.key to it.value.toString() } else -> { logger.warn { "entryPoints field in plugin manifest is invalid" } emptyMap() @@ -192,9 +190,9 @@ data class DefaultPactPluginManifest( emptyMap() } - val args = if (pluginJson.containsKey("args")) { + val args = if (pluginJson.has("args")) { when (val aj = pluginJson["args"]) { - is JsonArray -> aj.map { toString(it)!! } + is JsonValue.Array -> aj.values.map { it.toString() } else -> { logger.warn { "args field in plugin manifest is invalid" } emptyList() @@ -207,11 +205,11 @@ data class DefaultPactPluginManifest( return DefaultPactPluginManifest( pluginDir, toInteger(pluginJson["pluginInterfaceVersion"]) ?: 1, - toString(pluginJson["name"])!!, - toString(pluginJson["version"])!!, - toString(pluginJson["executableType"])!!, - toString(pluginJson["minimumRequiredVersion"]), - toString(pluginJson["entryPoint"])!!, + pluginJson["name"].asString().orEmpty(), + pluginJson["version"].asString().orEmpty(), + pluginJson["executableType"].asString().orEmpty(), + pluginJson["minimumRequiredVersion"].asString(), + pluginJson["entryPoint"].asString().orEmpty(), entryPoints, args, listOf() @@ -974,8 +972,8 @@ object DefaultPluginManager: PluginManager { logger.debug { "Plugin ${manifest.name} started with PID ${cp.pid}" } val timeout = System.getProperty("pact.plugin.loadTimeoutInMs")?.toLongOrNull() ?: 10000 val startupInfo = cp.channel.poll(timeout, TimeUnit.MILLISECONDS) - if (startupInfo is JsonObject) { - Result.Ok(DefaultPactPlugin(cp, manifest, toInteger(startupInfo["port"]), toString(startupInfo["serverKey"])!!)) + if (startupInfo is JsonValue.Object) { + Result.Ok(DefaultPactPlugin(cp, manifest, toInteger(startupInfo["port"]), startupInfo["serverKey"].toString())) } else { cp.destroy() Result.Err("Plugin process did not output the correct startup message in $timeout ms - got $startupInfo") @@ -1009,7 +1007,7 @@ object DefaultPluginManager: PluginManager { for (file in File(pluginDir).walk()) { if (file.isFile && file.name == "pact-plugin.json") { logger.debug { "Found plugin manifest: $file" } - val pluginJson = file.bufferedReader().use { Json.createReader(it).readObject() } + val pluginJson = file.bufferedReader().use { JsonParser.parseReader(it).asObject() } if (pluginJson != null) { val plugin = DefaultPactPluginManifest.fromJson(file.parentFile, pluginJson) if (plugin.name == name && versionsCompatible(plugin.version, version)) { diff --git a/drivers/jvm/core/src/test/groovy/io/pact/plugins/jvm/core/DefaultPactPluginManifestSpec.groovy b/drivers/jvm/core/src/test/groovy/io/pact/plugins/jvm/core/DefaultPactPluginManifestSpec.groovy index 73dbe4d3..ffef9bdc 100644 --- a/drivers/jvm/core/src/test/groovy/io/pact/plugins/jvm/core/DefaultPactPluginManifestSpec.groovy +++ b/drivers/jvm/core/src/test/groovy/io/pact/plugins/jvm/core/DefaultPactPluginManifestSpec.groovy @@ -1,9 +1,8 @@ package io.pact.plugins.jvm.core +import au.com.dius.pact.core.support.json.JsonParser import spock.lang.Specification -import jakarta.json.Json - class DefaultPactPluginManifestSpec extends Specification { File pluginFile @@ -130,7 +129,7 @@ class DefaultPactPluginManifestSpec extends Specification { def 'loading manifest from JSON'() { given: InputStream pluginFile = DefaultPactPluginManifestSpec.getResourceAsStream('/pact-plugin.json') - def pluginJson = Json.createReader(pluginFile).readObject() + def pluginJson = JsonParser.parseStream(pluginFile) when: def pluginManifest = DefaultPactPluginManifest.fromJson('pact-plugin.json' as File, pluginJson)