From 76b56679e6137f5c9d99b7080d6f8d6ab887f4c5 Mon Sep 17 00:00:00 2001 From: Adel El-Beik <adel.el-beik@r3.com> Date: Sun, 13 Oct 2024 19:26:01 +0100 Subject: [PATCH 1/5] ENT-11975: Updating config parsing with 4.12 version, which correctly parses the 4.12 rotated keys config item. --- .../internal/config/ConfigUtilities.kt | 109 +++++------------- 1 file changed, 28 insertions(+), 81 deletions(-) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt index 56f12e0dde..95d195bab8 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt @@ -3,7 +3,13 @@ package net.corda.nodeapi.internal.config -import com.typesafe.config.* +import com.typesafe.config.Config +import com.typesafe.config.ConfigException +import com.typesafe.config.ConfigFactory +import com.typesafe.config.ConfigUtil +import com.typesafe.config.ConfigValue +import com.typesafe.config.ConfigValueFactory +import com.typesafe.config.ConfigValueType import net.corda.core.identity.CordaX500Name import net.corda.core.internal.isStatic import net.corda.core.internal.noneOrSingle @@ -11,9 +17,7 @@ import net.corda.core.internal.uncheckedCast import net.corda.core.utilities.NetworkHostAndPort import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.lang.reflect.Field import java.lang.reflect.InvocationTargetException -import java.lang.reflect.ParameterizedType import java.net.Proxy import java.net.URL import java.nio.file.Path @@ -22,7 +26,9 @@ import java.time.Duration import java.time.Instant import java.time.LocalDate import java.time.temporal.Temporal -import java.util.* +import java.time.temporal.TemporalAmount +import java.util.Properties +import java.util.UUID import javax.security.auth.x500.X500Principal import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -181,7 +187,7 @@ private fun Config.getSingleValue( X500Principal::class -> X500Principal(getString(path)) CordaX500Name::class -> { when (getValue(path).valueType()) { - ConfigValueType.OBJECT -> getConfig(path).parseAs(onUnknownKeys) + ConfigValueType.OBJECT -> getConfig(path).parseAs(onUnknownKeys) as CordaX500Name else -> CordaX500Name.parse(getString(path)) } } @@ -291,98 +297,39 @@ private fun <T : Enum<T>> enumBridge(clazz: Class<T>, name: String): T { */ fun Any.toConfig(): Config = ConfigValueFactory.fromMap(toConfigMap()).toConfig() -fun Any?.toConfigValue(): ConfigValue = if (this is ConfigValue) { - this -} else if (this != null) { - ConfigValueFactory.fromAnyRef(convertValue(this)) -} else { - ConfigValueFactory.fromAnyRef(null) -} +fun Any?.toConfigValue(): ConfigValue = ConfigValueFactory.fromAnyRef(sanitiseForFromAnyRef(this)) -@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") // Reflect over the fields of the receiver and generate a value Map that can use to create Config object. -private fun Any.toConfigMap(): Map<String, Any> { - val values = HashMap<String, Any>() +private fun Any.toConfigMap(): Map<String, Any?> { + val values = LinkedHashMap<String, Any?>() for (field in javaClass.declaredFields) { if (field.isStatic || field.isSynthetic) continue field.isAccessible = true val value = field.get(this) ?: continue - val configValue = if (value is String || value is Boolean || value is Number) { - // These types are supported by Config as use as is - value - } else if (value is Temporal || value is NetworkHostAndPort || value is CordaX500Name || - value is Path || value is URL || value is UUID || value is X500Principal) { - // These types make sense to be represented as Strings and the exact inverse parsing function for use in parseAs - value.toString() - } else if (value is Enum<*>) { - // Expicitly use the Enum's name in case the toString is overridden, which would make parsing problematic. - value.name - } else if (value is Properties) { - // For Properties we treat keys with . as nested configs - ConfigFactory.parseMap(uncheckedCast(value)).root() - } else if (value is Iterable<*>) { - value.toConfigIterable(field) - } else { - // Else this is a custom object recursed over - value.toConfigMap() - } - values[field.name] = configValue + values[field.name] = sanitiseForFromAnyRef(value) } return values } -private fun convertValue(value: Any): Any { - - return if (value is String || value is Boolean || value is Number) { +/** + * @see ConfigValueFactory.fromAnyRef + */ +private fun sanitiseForFromAnyRef(value: Any?): Any? { + return when (value) { // These types are supported by Config as use as is - value - } else if (value is Temporal || value is NetworkHostAndPort || value is CordaX500Name || - value is Path || value is URL || value is UUID || value is X500Principal) { - // These types make sense to be represented as Strings and the exact inverse parsing function for use in parseAs - value.toString() - } else if (value is Enum<*>) { - // Expicitly use the Enum's name in case the toString is overridden, which would make parsing problematic. - value.name - } else if (value is Properties) { + is String, is Boolean, is Number, is ConfigValue, is Duration, null -> value + is Enum<*> -> value.name + // These types make sense to be represented as Strings + is Temporal, is TemporalAmount, is NetworkHostAndPort, is CordaX500Name, is Path, is URL, is UUID, is X500Principal -> value.toString() // For Properties we treat keys with . as nested configs - ConfigFactory.parseMap(uncheckedCast(value)).root() - } else if (value is Iterable<*>) { - value.toConfigIterable() - } else { + is Properties -> ConfigFactory.parseMap(uncheckedCast(value)).root() + is Map<*, *> -> ConfigFactory.parseMap(value.map { it.key.toString() to sanitiseForFromAnyRef(it.value) }.toMap()).root() + is Iterable<*> -> value.map(::sanitiseForFromAnyRef) // Else this is a custom object recursed over - value.toConfigMap() + else -> value.toConfigMap() } } -// For Iterables figure out the type parameter and apply the same logic as above on the individual elements. -private fun Iterable<*>.toConfigIterable(field: Field): Iterable<Any?> { - val elementType = (field.genericType as ParameterizedType).actualTypeArguments[0] as Class<*> - return when (elementType) { - // For the types already supported by Config we can use the Iterable as is - String::class.java -> this - Integer::class.java -> this - java.lang.Long::class.java -> this - java.lang.Double::class.java -> this - java.lang.Boolean::class.java -> this - LocalDate::class.java -> map(Any?::toString) - Instant::class.java -> map(Any?::toString) - NetworkHostAndPort::class.java -> map(Any?::toString) - Path::class.java -> map(Any?::toString) - URL::class.java -> map(Any?::toString) - X500Principal::class.java -> map(Any?::toString) - UUID::class.java -> map(Any?::toString) - CordaX500Name::class.java -> map(Any?::toString) - Properties::class.java -> map { ConfigFactory.parseMap(uncheckedCast(it)).root() } - else -> if (elementType.isEnum) { - map { (it as Enum<*>).name } - } else { - map { it?.toConfigMap() } - } - } -} - -private fun Iterable<*>.toConfigIterable(): Iterable<Any?> = map { element -> element?.let(::convertValue) } - // The typesafe .getBoolean function is case sensitive, this is a case insensitive version fun Config.getBooleanCaseInsensitive(path: String): Boolean { try { From 94bd9dceac640461842ca4bb228e51f3cf61be60 Mon Sep 17 00:00:00 2001 From: chriscochrane <chris.cochrane@r3.com> Date: Mon, 14 Oct 2024 13:34:49 +0100 Subject: [PATCH 2/5] Dependency update --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b7e96776d0..9ae8e9bdf9 100644 --- a/build.gradle +++ b/build.gradle @@ -126,7 +126,7 @@ buildscript { ext.jcabi_manifests_version = '1.1' ext.picocli_version = '3.9.6' ext.commons_lang_version = '3.9' - ext.commons_io_version = '2.6' + ext.commons_io_version = '2.17.0' ext.controlsfx_version = '8.40.15' ext.detekt_version = constants.getProperty('detektVersion') ext.docker_java_version = constants.getProperty("dockerJavaVersion") From 31ad1d99c497e43420c22a2c41412cf84f4048d1 Mon Sep 17 00:00:00 2001 From: chriscochrane <chris.cochrane@r3.com> Date: Mon, 14 Oct 2024 14:43:45 +0100 Subject: [PATCH 3/5] New WriterOutputStream API --- .../kotlin/net/corda/blobinspector/BlobInspectorTest.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/blobinspector/src/test/kotlin/net/corda/blobinspector/BlobInspectorTest.kt b/tools/blobinspector/src/test/kotlin/net/corda/blobinspector/BlobInspectorTest.kt index 210a5e9e11..fd00341ea5 100644 --- a/tools/blobinspector/src/test/kotlin/net/corda/blobinspector/BlobInspectorTest.kt +++ b/tools/blobinspector/src/test/kotlin/net/corda/blobinspector/BlobInspectorTest.kt @@ -55,7 +55,12 @@ class BlobInspectorTest { private fun run(resourceName: String): String { blobInspector.source = javaClass.getResource(resourceName) val writer = StringWriter() - blobInspector.run(PrintStream(WriterOutputStream(writer, UTF_8))) + val oStream = WriterOutputStream.builder() + .setCharset(UTF_8) + .setWriter(writer) + .get() + blobInspector.run(PrintStream(oStream)) + val output = writer.toString() println(output) return output From 78e7f62df3a104637f53b53cf2fb01db57868832 Mon Sep 17 00:00:00 2001 From: chriscochrane <chris.cochrane@r3.com> Date: Tue, 15 Oct 2024 10:11:58 +0100 Subject: [PATCH 4/5] Updated commons-io version --- constants.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.properties b/constants.properties index 2874bcc1df..d29b038341 100644 --- a/constants.properties +++ b/constants.properties @@ -99,7 +99,7 @@ snappyVersion=0.5 jcabiManifestsVersion=1.1 picocliVersion=3.9.6 commonsLangVersion=3.9 -commonsIoVersion=2.6 +commonsIoVersion=2.17.0 controlsfxVersion=8.40.15 # FontAwesomeFX for Java8 fontawesomefxCommonsJava8Version=8.15 From c59040fbc2a8fcee5619f7d4eb3e57ad11be49fa Mon Sep 17 00:00:00 2001 From: Adel El-Beik <adel.el-beik@r3.com> Date: Mon, 21 Oct 2024 09:01:25 +0100 Subject: [PATCH 5/5] ENT-11975:Merge typo, removed commons_lang_version added. --- constants.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/constants.properties b/constants.properties index b99bff5255..b570aaec15 100644 --- a/constants.properties +++ b/constants.properties @@ -93,7 +93,6 @@ protonjVersion=0.33.0 snappyVersion=0.5 jcabiManifestsVersion=1.1 picocliVersion=3.9.6 -commonsLangVersion=3.9 commonsIoVersion=2.17.0 controlsfxVersion=8.40.15 fontawesomefxCommonsVersion=11.0