diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 518069b359..d62eaf2220 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -14,6 +14,8 @@
+
+
@@ -189,4 +191,4 @@
-
\ No newline at end of file
+
diff --git a/build.gradle b/build.gradle
index d1aaa2a74a..1d81060ce1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -93,6 +93,7 @@ buildscript {
ext.eaagentloader_version = '1.0.3'
ext.curator_version = '4.0.0'
ext.jsch_version = '0.1.54'
+ ext.commons_cli_version = '1.4'
// Update 121 is required for ObjectInputFilter and at time of writing 131 was latest:
ext.java8_minUpdateVersion = '131'
diff --git a/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt b/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt
index b958602c3f..15bf4a7ea2 100644
--- a/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt
+++ b/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt
@@ -12,6 +12,7 @@ package net.corda.core.contracts
import net.corda.core.crypto.SecureHash
import net.corda.core.transactions.LedgerTransaction
+import net.corda.nodeapi.internal.serialization.AMQP_RPC_CLIENT_CONTEXT
import net.corda.nodeapi.internal.serialization.AllWhitelist
import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import net.corda.nodeapi.internal.serialization.amqp.SerializationOutput
@@ -29,13 +30,17 @@ class TransactionVerificationExceptionSerialisationTests {
ClassLoader.getSystemClassLoader()
)
+ private val context get() = AMQP_RPC_CLIENT_CONTEXT
+
private val txid = SecureHash.allOnesHash
private val factory = defaultFactory()
@Test
fun contractConstraintRejectionTest() {
val excp = TransactionVerificationException.ContractConstraintRejection(txid, "This is only a test")
- val excp2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(excp))
+ val excp2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(excp, context),
+ context)
assertEquals(excp.message, excp2.message)
assertEquals(excp.cause, excp2.cause)
@@ -52,7 +57,9 @@ class TransactionVerificationExceptionSerialisationTests {
val cause = Throwable("wibble")
val exception = TransactionVerificationException.ContractRejection(txid, contract, cause)
- val exception2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(exception))
+ val exception2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(exception, context),
+ context)
assertEquals(exception.message, exception2.message)
assertEquals(exception.cause?.message, exception2.cause?.message)
@@ -62,7 +69,9 @@ class TransactionVerificationExceptionSerialisationTests {
@Test
fun missingAttachmentRejectionTest() {
val exception = TransactionVerificationException.MissingAttachmentRejection(txid, "Some contract class")
- val exception2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(exception))
+ val exception2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(exception, context),
+ context)
assertEquals(exception.message, exception2.message)
assertEquals(exception.cause?.message, exception2.cause?.message)
@@ -72,7 +81,9 @@ class TransactionVerificationExceptionSerialisationTests {
@Test
fun conflictingAttachmentsRejectionTest() {
val exception = TransactionVerificationException.ContractConstraintRejection(txid, "Some contract class")
- val exception2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(exception))
+ val exception2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(exception, context),
+ context)
assertEquals(exception.message, exception2.message)
assertEquals(exception.cause?.message, exception2.cause?.message)
@@ -83,7 +94,9 @@ class TransactionVerificationExceptionSerialisationTests {
fun contractCreationErrorTest() {
val cause = Throwable("wibble")
val exception = TransactionVerificationException.ContractCreationError(txid, "Some contract class", cause)
- val exception2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(exception))
+ val exception2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(exception, context),
+ context)
assertEquals(exception.message, exception2.message)
assertEquals(exception.cause?.message, exception2.cause?.message)
@@ -94,7 +107,9 @@ class TransactionVerificationExceptionSerialisationTests {
fun transactionMissingEncumbranceTest() {
val exception = TransactionVerificationException.TransactionMissingEncumbranceException(
txid, 12, TransactionVerificationException.Direction.INPUT)
- val exception2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(exception))
+ val exception2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(exception, context),
+ context)
assertEquals(exception.message, exception2.message)
assertEquals(exception.cause?.message, exception2.cause?.message)
@@ -109,7 +124,9 @@ class TransactionVerificationExceptionSerialisationTests {
val factory = defaultFactory()
factory.register(PublicKeySerializer)
val exception = TransactionVerificationException.NotaryChangeInWrongTransactionType(txid, dummyBankA, dummyNotary)
- val exception2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(exception))
+ val exception2 = DeserializationInput(factory).deserialize(
+ SerializationOutput(factory).serialize(exception, context),
+ context)
assertEquals(exception.message, exception2.message)
assertEquals(exception.cause?.message, exception2.cause?.message)
diff --git a/docs/source/api-testing.rst b/docs/source/api-testing.rst
index b2662c1acf..5169f7b3b5 100644
--- a/docs/source/api-testing.rst
+++ b/docs/source/api-testing.rst
@@ -165,6 +165,40 @@ Nodes are created on the ``MockNetwork`` using:
}
}
+Nodes added using ``createPartyNode`` are provided a default set of node parameters. However, it is also possible to
+provide different parameters to each node using the following methods on ``MockNetwork``:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ /**
+ * Create a started node with the given parameters.
+ *
+ * @param legalName The node's legal name.
+ * @param forcedID A unique identifier for the node.
+ * @param entropyRoot The initial entropy value to use when generating keys. Defaults to an (insecure) random value,
+ * but can be overridden to cause nodes to have stable or colliding identity/service keys.
+ * @param configOverrides Add/override behaviour of the [NodeConfiguration] mock object.
+ * @param extraCordappPackages Extra CorDapp packages to add for this node.
+ */
+ @JvmOverloads
+ fun createNode(legalName: CordaX500Name? = null,
+ forcedID: Int? = null,
+ entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
+ configOverrides: (NodeConfiguration) -> Any? = {},
+ extraCordappPackages: List = emptyList()
+ ): StartedMockNode
+
+ /** Create a started node with the given parameters. **/
+ fun createNode(parameters: MockNodeParameters = MockNodeParameters()): StartedMockNode
+
+As you can see above, parameters can be added individually or encapsulated within a ``MockNodeParameters`` object. Of
+particular interest are ``configOverrides`` which allow you to override any default config option specified within the
+``NodeConfiguration`` object. Also, the ``extraCordappPackages`` parameter allows you to add extra CorDapps to a
+specific node. This is useful when you wish for all nodes to load a common CorDapp but for a subset of nodes to load
+CorDapps specific to their role in the network.
+
Running the network
^^^^^^^^^^^^^^^^^^^
diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst
index e1ef09876c..ef153d78ab 100644
--- a/docs/source/changelog.rst
+++ b/docs/source/changelog.rst
@@ -7,6 +7,9 @@ release, see :doc:`upgrade-notes`.
Unreleased
==========
+* Refactor AMQP Serializer to pass context object down the serialization call hierarchy. Will allow per thread
+ extensions to be set and used by the RPC work (Observable Context Key)
+
* Refactor RPC Server Kryo observable serializer into it's own sub module
* Refactor RPC Client Kryo observable serializer into it's own sub module
diff --git a/experimental/blobinspector/build.gradle b/experimental/blobinspector/build.gradle
new file mode 100644
index 0000000000..2862ff6fae
--- /dev/null
+++ b/experimental/blobinspector/build.gradle
@@ -0,0 +1,52 @@
+apply plugin: 'java'
+apply plugin: 'kotlin'
+apply plugin: 'application'
+
+mainClassName = 'net.corda.blobinspector.MainKt'
+
+dependencies {
+ compile project(':core')
+ compile project(':node-api')
+
+ compile "commons-cli:commons-cli:$commons_cli_version"
+
+ testCompile project(':test-utils')
+
+ testCompile "junit:junit:$junit_version"
+}
+
+/**
+ * To run from within gradle use
+ *
+ * ./gradlew -PrunArgs=" " :experimental:blobinspector:run
+ *
+ * For example, to parse a file from the command line and print out the deserialized properties
+ *
+ * ./gradlew -PrunArgs="-f -d" :experimental:blobinspector:run
+ *
+ * at the command line.
+ */
+run {
+ if (project.hasProperty('runArgs')) {
+ args = [ project.findProperty('runArgs').toString().split(" ") ].flatten()
+ }
+
+ if (System.properties.getProperty('consoleLogLevel') != null) {
+ logging.captureStandardOutput(LogLevel.valueOf(System.properties.getProperty('consoleLogLevel')))
+ logging.captureStandardError(LogLevel.valueOf(System.properties.getProperty('consoleLogLevel')))
+ systemProperty "consoleLogLevel", System.properties.getProperty('consoleLogLevel')
+ }
+}
+
+/**
+ * Build a executable jar
+ */
+jar {
+ baseName 'blobinspector'
+ manifest {
+ attributes(
+ 'Automatic-Module-Name': 'net.corda.experimental.blobinspector',
+ 'Main-Class': 'net.corda.blobinspector.MainKt'
+ )
+ }
+}
diff --git a/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/BlobInspector.kt b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/BlobInspector.kt
new file mode 100644
index 0000000000..8a30c2319f
--- /dev/null
+++ b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/BlobInspector.kt
@@ -0,0 +1,399 @@
+package net.corda.blobinspector
+
+import net.corda.core.crypto.SecureHash
+import net.corda.core.serialization.EncodingWhitelist
+import net.corda.core.serialization.SerializationEncoding
+import net.corda.core.utilities.ByteSequence
+import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
+import net.corda.nodeapi.internal.serialization.amqp.*
+import org.apache.qpid.proton.amqp.Binary
+import org.apache.qpid.proton.amqp.DescribedType
+import org.apache.qpid.proton.amqp.Symbol
+
+/**
+ * Print a string to the console only if the verbose config option is set.
+ */
+fun String.debug(config: Config) {
+ if (config.verbose) {
+ println(this)
+ }
+}
+
+/**
+ *
+ */
+interface Stringify {
+ fun stringify(sb: IndentingStringBuilder)
+}
+
+/**
+ * Makes classnames easier to read by stripping off the package names from the class and separating nested
+ * classes
+ *
+ * For example:
+ *
+ * net.corda.blobinspector.Class1
+ * Class1
+ *
+ * net.corda.blobinspector.Class1
+ * Class1
+ *
+ * net.corda.blobinspector.Class1>
+ * Class1 >
+ *
+ * net.corda.blobinspector.Class1>
+ * Class1 :: C >
+ */
+fun String.simplifyClass(): String {
+
+ return if (this.endsWith('>')) {
+ val templateStart = this.indexOf('<')
+ val clazz = (this.substring(0, templateStart))
+ val params = this.substring(templateStart+1, this.length-1).split(',').map { it.simplifyClass() }.joinToString()
+
+ "${clazz.simplifyClass()} <$params>"
+ }
+ else {
+ substring(this.lastIndexOf('.') + 1).replace("$", " :: ")
+ }
+}
+
+/**
+ * Represents the deserialized form of the property of an Object
+ *
+ * @param name
+ * @param type
+ */
+abstract class Property(
+ val name: String,
+ val type: String) : Stringify
+
+/**
+ * Derived class of [Property], represents properties of an object that are non compelex, such
+ * as any POD type or String
+ */
+class PrimProperty(
+ name: String,
+ type: String,
+ private val value: String) : Property(name, type) {
+ override fun toString(): String = "$name : $type : $value"
+
+ override fun stringify(sb: IndentingStringBuilder) {
+ sb.appendln("$name : $type : $value")
+ }
+}
+
+/**
+ * Derived class of [Property] that represents a binary blob. Specifically useful because printing
+ * a stream of bytes onto the screen isn't very use friendly
+ */
+class BinaryProperty(
+ name: String,
+ type: String,
+ val value: ByteArray) : Property(name, type) {
+ override fun toString(): String = "$name : $type : <<>>"
+
+ override fun stringify(sb: IndentingStringBuilder) {
+ sb.appendln("$name : $type : <<>>")
+ }
+}
+
+/**
+ * Derived class of [Property] that represent a list property. List could be either PoD types or
+ * composite types.
+ */
+class ListProperty(
+ name: String,
+ type: String,
+ private val values: MutableList = mutableListOf()) : Property(name, type) {
+ override fun stringify(sb: IndentingStringBuilder) {
+ sb.apply {
+ if (values.isEmpty()) {
+ appendln("$name : $type : [ << EMPTY LIST >> ]")
+ } else if (values.first() is Stringify) {
+ appendln("$name : $type : [")
+ values.forEach {
+ (it as Stringify).stringify(this)
+ }
+ appendln("]")
+ } else {
+ appendln("$name : $type : [")
+ values.forEach {
+ appendln(it.toString())
+ }
+ appendln("]")
+ }
+ }
+ }
+}
+
+class MapProperty(
+ name: String,
+ type: String,
+ private val map: MutableMap<*, *>
+) : Property(name, type) {
+ override fun stringify(sb: IndentingStringBuilder) {
+ if (map.isEmpty()) {
+ sb.appendln("$name : $type : { << EMPTY MAP >> }")
+ return
+ }
+
+ // TODO this will not produce pretty output
+ sb.apply {
+ appendln("$name : $type : {")
+ map.forEach {
+ try {
+ (it.key as Stringify).stringify(this)
+ } catch (e: ClassCastException) {
+ append (it.key.toString() + " : ")
+ }
+ try {
+ (it.value as Stringify).stringify(this)
+ } catch (e: ClassCastException) {
+ appendln("\"${it.value.toString()}\"")
+ }
+ }
+ appendln("}")
+ }
+ }
+}
+
+/**
+ * Derived class of [Property] that represents class properties that are themselves instances of
+ * some complex type.
+ */
+class InstanceProperty(
+ name: String,
+ type: String,
+ val value: Instance) : Property(name, type) {
+ override fun stringify(sb: IndentingStringBuilder) {
+ sb.append("$name : ")
+ value.stringify(sb)
+ }
+}
+
+/**
+ * Represents an instance of a composite type.
+ */
+class Instance(
+ val name: String,
+ val type: String,
+ val fields: MutableList = mutableListOf()) : Stringify {
+ override fun stringify(sb: IndentingStringBuilder) {
+ sb.apply {
+ appendln("${name.simplifyClass()} : {")
+ fields.forEach {
+ it.stringify(this)
+ }
+ appendln("}")
+ }
+ }
+}
+
+/**
+ *
+ */
+fun inspectComposite(
+ config: Config,
+ typeMap: Map,
+ obj: DescribedType): Instance {
+ if (obj.described !is List<*>) throw MalformedBlob("")
+
+ val name = (typeMap[obj.descriptor] as CompositeType).name
+ "composite: $name".debug(config)
+
+ val inst = Instance(
+ typeMap[obj.descriptor]?.name ?: "",
+ typeMap[obj.descriptor]?.label ?: "")
+
+ (typeMap[obj.descriptor] as CompositeType).fields.zip(obj.described as List<*>).forEach {
+ " field: ${it.first.name}".debug(config)
+ inst.fields.add(
+ if (it.second is DescribedType) {
+ " - is described".debug(config)
+ val d = inspectDescribed(config, typeMap, it.second as DescribedType)
+
+ when (d) {
+ is Instance ->
+ InstanceProperty(
+ it.first.name,
+ it.first.type,
+ d)
+ is List<*> -> {
+ " - List".debug(config)
+ ListProperty(
+ it.first.name,
+ it.first.type,
+ d as MutableList)
+ }
+ is Map<*, *> -> {
+ MapProperty(
+ it.first.name,
+ it.first.type,
+ d as MutableMap<*, *>)
+ }
+ else -> {
+ " skip it".debug(config)
+ return@forEach
+ }
+ }
+
+ } else {
+ " - is prim".debug(config)
+ when (it.first.type) {
+ // Note, as in the case of SHA256 we can treat particular binary types
+ // as different properties with a little coercion
+ "binary" -> {
+ if (name == "net.corda.core.crypto.SecureHash\$SHA256") {
+ PrimProperty(
+ it.first.name,
+ it.first.type,
+ SecureHash.SHA256((it.second as Binary).array).toString())
+ } else {
+ BinaryProperty(it.first.name, it.first.type, (it.second as Binary).array)
+ }
+ }
+ else -> PrimProperty(it.first.name, it.first.type, it.second.toString())
+ }
+ })
+ }
+
+ return inst
+}
+
+fun inspectRestricted(
+ config: Config,
+ typeMap: Map,
+ obj: DescribedType): Any {
+ return when ((typeMap[obj.descriptor] as RestrictedType).source) {
+ "list" -> inspectRestrictedList(config, typeMap, obj)
+ "map" -> inspectRestrictedMap(config, typeMap, obj)
+ else -> throw NotImplementedError()
+ }
+}
+
+
+fun inspectRestrictedList(
+ config: Config,
+ typeMap: Map,
+ obj: DescribedType
+) : List {
+ if (obj.described !is List<*>) throw MalformedBlob("")
+
+ return mutableListOf().apply {
+ (obj.described as List<*>).forEach {
+ when (it) {
+ is DescribedType -> add(inspectDescribed(config, typeMap, it))
+ is RestrictedType -> add(inspectRestricted(config, typeMap, it))
+ else -> add (it.toString())
+ }
+ }
+ }
+}
+
+fun inspectRestrictedMap(
+ config: Config,
+ typeMap: Map,
+ obj: DescribedType
+) : Map {
+ if (obj.described !is Map<*,*>) throw MalformedBlob("")
+
+ return mutableMapOf().apply {
+ (obj.described as Map<*, *>).forEach {
+ val key = when (it.key) {
+ is DescribedType -> inspectDescribed(config, typeMap, it.key as DescribedType)
+ is RestrictedType -> inspectRestricted(config, typeMap, it.key as RestrictedType)
+ else -> it.key.toString()
+ }
+
+ val value = when (it.value) {
+ is DescribedType -> inspectDescribed(config, typeMap, it.value as DescribedType)
+ is RestrictedType -> inspectRestricted(config, typeMap, it.value as RestrictedType)
+ else -> it.value.toString()
+ }
+
+ this[key] = value
+ }
+ }
+}
+
+
+/**
+ * Every element of the blob stream will be a ProtonJ [DescribedType]. When inspecting the blob stream
+ * the two custom Corda types we're interested in are [CompositeType]'s, representing the instance of
+ * some object (class), and [RestrictedType]'s, representing containers and enumerations.
+ *
+ * @param config The configuration object that controls the behaviour of the BlobInspector
+ * @param typeMap
+ * @param obj
+ */
+fun inspectDescribed(
+ config: Config,
+ typeMap: Map,
+ obj: DescribedType): Any {
+ "${obj.descriptor} in typeMap? = ${obj.descriptor in typeMap}".debug(config)
+
+ return when (typeMap[obj.descriptor]) {
+ is CompositeType -> {
+ "* It's composite".debug(config)
+ inspectComposite(config, typeMap, obj)
+ }
+ is RestrictedType -> {
+ "* It's restricted".debug(config)
+ inspectRestricted(config, typeMap, obj)
+ }
+ else -> {
+ "${typeMap[obj.descriptor]?.name} is neither Composite or Restricted".debug(config)
+ }
+ }
+
+}
+
+internal object NullEncodingWhitelist : EncodingWhitelist {
+ override fun acceptEncoding(encoding: SerializationEncoding) = false
+}
+
+// TODO : Refactor to generically poerate on arbitrary blobs, not a single workflow
+fun inspectBlob(config: Config, blob: ByteArray) {
+ val bytes = ByteSequence.of(blob)
+
+ val headerSize = SerializationFactoryImpl.magicSize
+
+ // TODO written to only understand one version, when we support multiple this will need to change
+ val headers = listOf(ByteSequence.of(amqpMagic.bytes))
+
+ val blobHeader = bytes.take(headerSize)
+
+ if (blobHeader !in headers) {
+ throw MalformedBlob("Blob is not a Corda AMQP serialised object graph")
+ }
+
+
+ val e = DeserializationInput.getEnvelope(bytes, NullEncodingWhitelist)
+
+ if (config.schema) {
+ println(e.schema)
+ }
+
+ if (config.transforms) {
+ println(e.transformsSchema)
+ }
+
+ val typeMap = e.schema.types.associateBy({ it.descriptor.name }, { it })
+
+ if (config.data) {
+ val inspected = inspectDescribed(config, typeMap, e.obj as DescribedType)
+
+ println("\n${IndentingStringBuilder().apply { (inspected as Instance).stringify(this) }}")
+
+ (inspected as Instance).fields.find {
+ it.type.startsWith("net.corda.core.serialization.SerializedBytes<")
+ }?.let {
+ "Found field of SerializedBytes".debug(config)
+ (it as InstanceProperty).value.fields.find { it.name == "bytes" }?.let { raw ->
+ inspectBlob(config, (raw as BinaryProperty).value)
+ }
+ }
+ }
+}
+
diff --git a/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/BlobLoader.kt b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/BlobLoader.kt
new file mode 100644
index 0000000000..a027249079
--- /dev/null
+++ b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/BlobLoader.kt
@@ -0,0 +1,40 @@
+package net.corda.blobinspector
+
+import java.io.File
+import java.net.URL
+
+/**
+ *
+ */
+class FileBlobHandler(config_: Config) : BlobHandler(config_) {
+ private val path = File(URL((config_ as FileConfig).file).toURI())
+
+ override fun getBytes(): ByteArray {
+ return path.readBytes()
+ }
+}
+
+/**
+ *
+ */
+class InMemoryBlobHandler(config_: Config) : BlobHandler(config_) {
+ private val localBytes = (config_ as InMemoryConfig).blob?.bytes ?: kotlin.ByteArray(0)
+ override fun getBytes(): ByteArray = localBytes
+}
+
+/**
+ *
+ */
+abstract class BlobHandler (val config: Config) {
+ companion object {
+ fun make(config: Config) : BlobHandler {
+ return when (config.mode) {
+ Mode.file -> FileBlobHandler(config)
+ Mode.inMem -> InMemoryBlobHandler(config)
+ }
+ }
+ }
+
+ abstract fun getBytes() : ByteArray
+}
+
diff --git a/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Config.kt b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Config.kt
new file mode 100644
index 0000000000..376331ec2b
--- /dev/null
+++ b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Config.kt
@@ -0,0 +1,137 @@
+package net.corda.blobinspector
+
+import org.apache.commons.cli.CommandLine
+import net.corda.core.serialization.SerializedBytes
+import org.apache.commons.cli.Option
+import org.apache.commons.cli.Options
+
+/**
+ * Enumeration of the modes in which the blob inspector can be run.
+ *
+ * @property make lambda function that takes no parameters and returns a specific instance of the configuration
+ * object for that mode.
+ *
+ * @property options A lambda function that takes no parameters and returns an [Options] instance that define
+ * the command line flags related to this mode. For example ``file`` mode would have an option to pass in
+ * the name of the file to read.
+ *
+ */
+enum class Mode(
+ val make : () -> Config,
+ val options : (Options) -> Unit
+) {
+ file(
+ {
+ FileConfig(Mode.file)
+ },
+ { o ->
+ o.apply{
+ addOption(
+ Option ("f", "file", true, "path to file").apply {
+ isRequired = true
+ }
+ )
+ }
+ }
+ ),
+ inMem(
+ {
+ InMemoryConfig(Mode.inMem)
+ },
+ {
+ // The in memory only mode has no specific option assocaited with it as it's intended for
+ // testing purposes only within the unit test framework and not use on the command line
+ }
+ )
+}
+
+/**
+ * Configuration data class for the Blob Inspector.
+ *
+ * @property mode
+ */
+abstract class Config (val mode: Mode) {
+ var schema: Boolean = false
+ var transforms: Boolean = false
+ var data: Boolean = false
+ var verbose: Boolean = false
+
+ abstract fun populateSpecific(cmdLine: CommandLine)
+ abstract fun withVerbose() : Config
+
+ fun populate(cmdLine: CommandLine) {
+ schema = cmdLine.hasOption('s')
+ transforms = cmdLine.hasOption('t')
+ data = cmdLine.hasOption('d')
+ verbose = cmdLine.hasOption('v')
+
+ populateSpecific(cmdLine)
+ }
+
+ fun options() = Options().apply {
+ // install generic options
+ addOption(Option("s", "schema", false, "print the blob's schema").apply {
+ isRequired = false
+ })
+
+ addOption(Option("t", "transforms", false, "print the blob's transforms schema").apply {
+ isRequired = false
+ })
+
+ addOption(Option("d", "data", false, "Display the serialised data").apply {
+ isRequired = false
+ })
+
+ addOption(Option("v", "verbose", false, "Enable debug output").apply {
+ isRequired = false
+ })
+
+ // install the mode specific options
+ mode.options(this)
+ }
+}
+
+
+/**
+ * Configuration object when running in "File" mode, i.e. the object has been specified at
+ * the command line
+ */
+class FileConfig (
+ mode: Mode
+) : Config(mode) {
+
+ var file: String = "unset"
+
+ override fun populateSpecific(cmdLine : CommandLine) {
+ file = cmdLine.getParsedOptionValue("f") as String
+ }
+
+ override fun withVerbose() : FileConfig {
+ return FileConfig(mode).apply {
+ this.schema = schema
+ this.transforms = transforms
+ this.data = data
+ this.verbose = true
+ }
+ }
+}
+
+
+/**
+ * Placeholder config objet used when running unit tests and the inspected blob is being fed in
+ * via some mechanism directly. Normally this will be the direct serialisation of an object in a unit
+ * test and then dumping that blob into the inspector for visual comparison of the output
+ */
+class InMemoryConfig (
+ mode: Mode
+) : Config(mode) {
+ var blob: SerializedBytes<*>? = null
+
+ override fun populateSpecific(cmdLine: CommandLine) {
+ throw UnsupportedOperationException("In memory config is for testing only and cannot set specific flags")
+ }
+
+ override fun withVerbose(): Config {
+ throw UnsupportedOperationException("In memory config is for testing headlessly, cannot be verbose")
+ }
+}
diff --git a/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Errors.kt b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Errors.kt
new file mode 100644
index 0000000000..888ef1e302
--- /dev/null
+++ b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Errors.kt
@@ -0,0 +1,3 @@
+package net.corda.blobinspector
+
+class MalformedBlob(msg: String) : Exception(msg)
diff --git a/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/IndentingStringBuilder.kt b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/IndentingStringBuilder.kt
new file mode 100644
index 0000000000..48d81a8eb7
--- /dev/null
+++ b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/IndentingStringBuilder.kt
@@ -0,0 +1,45 @@
+package net.corda.blobinspector
+
+/**
+ * Wrapper around a [StringBuilder] that automates the indenting of lines as they're appended to facilitate
+ * pretty printing of deserialized blobs.
+ *
+ * @property sb The wrapped [StringBuilder]
+ * @property indenting Boolean flag that indicates weather we need to pad the start of whatever text
+ * currently being added to the string.
+ * @property indent How deeply the next line should be offset from the first column
+ */
+class IndentingStringBuilder(s : String = "", private val offset : Int = 4) {
+ private val sb = StringBuilder(s)
+ private var indenting = true
+ private var indent = 0
+
+ private fun wrap(ln: String, appender: (String) -> Unit) {
+ if ((ln.endsWith("}") || ln.endsWith("]")) && indent > 0 && ln.length == 1) {
+ indent -= offset
+ }
+
+ appender(ln)
+
+ if (ln.endsWith("{") || ln.endsWith("[")){
+ indent += offset
+ }
+ }
+
+ fun appendln(ln: String) {
+ wrap(ln) { s -> sb.appendln("${"".padStart(if (indenting) indent else 0, ' ')}$s") }
+
+ indenting = true
+ }
+
+
+ fun append(ln: String) {
+ indenting = false
+
+ wrap(ln) { s -> sb.append("${"".padStart(indent, ' ')}$s") }
+ }
+
+ override fun toString(): String {
+ return sb.toString()
+ }
+}
\ No newline at end of file
diff --git a/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Main.kt b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Main.kt
new file mode 100644
index 0000000000..0e13b9e087
--- /dev/null
+++ b/experimental/blobinspector/src/main/kotlin/net/corda/blobinspector/Main.kt
@@ -0,0 +1,81 @@
+package net.corda.blobinspector
+
+import org.apache.commons.cli.*
+import java.lang.IllegalArgumentException
+
+/**
+ * Mode isn't a required property as we default it to [Mode.file]
+ */
+private fun modeOption() = Option("m", "mode", true, "mode, file is the default").apply {
+ isRequired = false
+}
+
+/**
+ *
+ * Parse the command line arguments looking for the main mode into which the application is
+ * being put. Note, this defaults to [Mode.file] if not set meaning we will look for a file path
+ * being passed as a parameter and parse that file.
+ *
+ * @param args reflects the command line arguments
+ *
+ * @return An instantiated but unpopulated [Config] object instance suitable for the mode into
+ * which we've been placed. This Config object should be populated via [loadModeSpecificOptions]
+ */
+fun getMode(args: Array) : Config {
+ // For now we only care what mode we're being put in, we can build the rest of the args and parse them
+ // later
+ val options = Options().apply {
+ addOption(modeOption())
+ }
+
+ val cmd = try {
+ DefaultParser().parse(options, args, true)
+ } catch (e: org.apache.commons.cli.ParseException) {
+ println (e)
+ HelpFormatter().printHelp("blobinspector", options)
+ throw IllegalArgumentException("OH NO!!!")
+ }
+
+ return try {
+ Mode.valueOf(cmd.getParsedOptionValue("m") as? String ?: "file")
+ } catch (e: IllegalArgumentException) {
+ Mode.file
+ }.make()
+}
+
+/**
+ *
+ * @param config an instance of a [Config] specialisation suitable for the mode into which
+ * the application has been put.
+ * @param args The command line arguments
+ */
+fun loadModeSpecificOptions(config: Config, args: Array) {
+ config.apply {
+ // load that modes specific command line switches, needs to include the mode option
+ val modeSpecificOptions = config.options().apply {
+ addOption(modeOption())
+ }
+
+ populate (try {
+ DefaultParser().parse(modeSpecificOptions, args, false)
+ } catch (e: org.apache.commons.cli.ParseException) {
+ println ("Error: ${e.message}")
+ HelpFormatter().printHelp("blobinspector", modeSpecificOptions)
+ System.exit(1)
+ return
+ })
+ }
+}
+
+/**
+ * Executable entry point
+ */
+fun main(args: Array) {
+ println ("<<< WARNING: this tool is experimental and under active development >>>")
+ getMode(args).let { mode ->
+ loadModeSpecificOptions(mode, args)
+ BlobHandler.make(mode)
+ }.apply {
+ inspectBlob(config, getBytes())
+ }
+}
diff --git a/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/FileParseTests.kt b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/FileParseTests.kt
new file mode 100644
index 0000000000..a018baaf49
--- /dev/null
+++ b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/FileParseTests.kt
@@ -0,0 +1,84 @@
+package net.corda.blobinspector
+
+import java.net.URI
+
+import org.junit.Test
+import net.corda.testing.common.internal.ProjectStructure.projectRootDir
+
+
+class FileParseTests {
+ @Suppress("UNUSED")
+ var localPath : URI = projectRootDir.toUri().resolve(
+ "tools/blobinspector/src/test/resources/net/corda/blobinspector")
+
+ fun setupArgsWithFile(path: String) = Array(5) {
+ when (it) {
+ 0 -> "-m"
+ 1 -> "file"
+ 2 -> "-f"
+ 3 -> path
+ 4 -> "-d"
+ else -> "error"
+ }
+ }
+
+ private val filesToTest = listOf (
+ "FileParseTests.1Int",
+ "FileParseTests.2Int",
+ "FileParseTests.3Int",
+ "FileParseTests.1String",
+ "FileParseTests.1Composite",
+ "FileParseTests.2Composite",
+ "FileParseTests.IntList",
+ "FileParseTests.StringList",
+ "FileParseTests.MapIntString",
+ "FileParseTests.MapIntClass"
+ )
+
+ fun testFile(file : String) {
+ val path = FileParseTests::class.java.getResource(file)
+ val args = setupArgsWithFile(path.toString())
+
+ val handler = getMode(args).let { mode ->
+ loadModeSpecificOptions(mode, args)
+ BlobHandler.make(mode)
+ }
+
+ inspectBlob(handler.config, handler.getBytes())
+ }
+
+ @Test
+ fun simpleFiles() {
+ filesToTest.forEach { testFile(it) }
+ }
+
+ @Test
+ fun specificTest() {
+ testFile(filesToTest[4])
+ testFile(filesToTest[5])
+ testFile(filesToTest[6])
+ }
+
+ @Test
+ fun networkParams() {
+ val file = "networkParams"
+ val path = FileParseTests::class.java.getResource(file)
+ val verbose = false
+
+ val args = verbose.let {
+ if (it)
+ Array(4) { when (it) { 0 -> "-f" ; 1 -> path.toString(); 2 -> "-d"; 3 -> "-vs"; else -> "error" } }
+ else
+ Array(3) { when (it) { 0 -> "-f" ; 1 -> path.toString(); 2 -> "-d"; else -> "error" } }
+ }
+
+ val handler = getMode(args).let { mode ->
+ loadModeSpecificOptions(mode, args)
+ BlobHandler.make(mode)
+ }
+
+ inspectBlob(handler.config, handler.getBytes())
+
+ }
+
+}
diff --git a/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt
new file mode 100644
index 0000000000..26313b1d3c
--- /dev/null
+++ b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt
@@ -0,0 +1,91 @@
+package net.corda.blobinspector
+
+import net.corda.core.serialization.SerializedBytes
+import net.corda.nodeapi.internal.serialization.AllWhitelist
+import net.corda.nodeapi.internal.serialization.amqp.SerializationOutput
+import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
+import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT
+import org.junit.Test
+
+
+class InMemoryTests {
+ private val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
+
+ private fun inspect (b: SerializedBytes<*>) {
+ BlobHandler.make(
+ InMemoryConfig(Mode.inMem).apply { blob = b; data = true}
+ ).apply {
+ inspectBlob(config, getBytes())
+ }
+ }
+
+ @Test
+ fun test1() {
+ data class C (val a: Int, val b: Long, val c: String)
+ inspect (SerializationOutput(factory).serialize(C(100, 567L, "this is a test"), AMQP_P2P_CONTEXT))
+ }
+
+ @Test
+ fun test2() {
+ data class C (val i: Int, val c: C?)
+ inspect (SerializationOutput(factory).serialize(C(1, C(2, C(3, C(4, null)))), AMQP_P2P_CONTEXT))
+ }
+
+ @Test
+ fun test3() {
+ data class C (val a: IntArray, val b: Array)
+
+ val a = IntArray(10) { i -> i }
+ val c = C(a, arrayOf("aaa", "bbb", "ccc"))
+
+ inspect (SerializationOutput(factory).serialize(c, AMQP_P2P_CONTEXT))
+ }
+
+ @Test
+ fun test4() {
+ data class Elem(val e1: Long, val e2: String)
+ data class Wrapper (val name: String, val elementes: List)
+
+ inspect (SerializationOutput(factory).serialize(
+ Wrapper("Outer Class",
+ listOf(
+ Elem(1L, "First element"),
+ Elem(2L, "Second element"),
+ Elem(3L, "Third element")
+ )), AMQP_P2P_CONTEXT))
+ }
+
+ @Test
+ fun test4b() {
+ data class Elem(val e1: Long, val e2: String)
+ data class Wrapper (val name: String, val elementes: List>)
+
+ inspect (SerializationOutput(factory).serialize(
+ Wrapper("Outer Class",
+ listOf (
+ listOf(
+ Elem(1L, "First element"),
+ Elem(2L, "Second element"),
+ Elem(3L, "Third element")
+ ),
+ listOf(
+ Elem(4L, "Fourth element"),
+ Elem(5L, "Fifth element"),
+ Elem(6L, "Sixth element")
+ )
+ )), AMQP_P2P_CONTEXT))
+ }
+
+ @Test
+ fun test5() {
+ data class C (val a: Map)
+
+ inspect (SerializationOutput(factory).serialize(
+ C(mapOf(
+ "a" to "a a a",
+ "b" to "b b b",
+ "c" to "c c c")),
+ AMQP_P2P_CONTEXT
+ ))
+ }
+}
\ No newline at end of file
diff --git a/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/ModeParse.kt b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/ModeParse.kt
new file mode 100644
index 0000000000..9b69363386
--- /dev/null
+++ b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/ModeParse.kt
@@ -0,0 +1,77 @@
+package net.corda.blobinspector
+
+import org.junit.Test
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import kotlin.test.assertFalse
+
+class ModeParse {
+ @Test
+ fun fileIsSetToFile() {
+ val opts1 = Array(2) {
+ when (it) {
+ 0 -> "-m"
+ 1 -> "file"
+ else -> "error"
+ }
+ }
+
+ assertEquals(Mode.file, getMode(opts1).mode)
+ }
+
+ @Test
+ fun nothingIsSetToFile() {
+ val opts1 = Array(0) { "" }
+
+ assertEquals(Mode.file, getMode(opts1).mode)
+ }
+
+ @Test
+ fun filePathIsSet() {
+ val opts1 = Array(4) {
+ when (it) {
+ 0 -> "-m"
+ 1 -> "file"
+ 2 -> "-f"
+ 3 -> "path/to/file"
+ else -> "error"
+ }
+ }
+
+ val config = getMode(opts1)
+ assertTrue (config is FileConfig)
+ assertEquals(Mode.file, config.mode)
+ assertEquals("unset", (config as FileConfig).file)
+
+ loadModeSpecificOptions(config, opts1)
+
+ assertEquals("path/to/file", config.file)
+ }
+
+ @Test
+ fun schemaIsSet() {
+ Array(2) { when (it) { 0 -> "-f"; 1 -> "path/to/file"; else -> "error" } }.let { options ->
+ getMode(options).apply {
+ loadModeSpecificOptions(this, options)
+ assertFalse (schema)
+ }
+ }
+
+ Array(3) { when (it) { 0 -> "--schema"; 1 -> "-f"; 2 -> "path/to/file"; else -> "error" } }.let {
+ getMode(it).apply {
+ loadModeSpecificOptions(this, it)
+ assertTrue (schema)
+ }
+ }
+
+ Array(3) { when (it) { 0 -> "-f"; 1 -> "path/to/file"; 2 -> "-s"; else -> "error" } }.let {
+ getMode(it).apply {
+ loadModeSpecificOptions(this, it)
+ assertTrue (schema)
+ }
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/SimplifyClassTests.kt b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/SimplifyClassTests.kt
new file mode 100644
index 0000000000..10d470685b
--- /dev/null
+++ b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/SimplifyClassTests.kt
@@ -0,0 +1,28 @@
+package net.corda.blobinspector
+
+import org.junit.Test
+
+class SimplifyClassTests {
+
+ @Test
+ fun test1() {
+ data class A(val a: Int)
+
+ println (A::class.java.name)
+ println (A::class.java.name.simplifyClass())
+ }
+
+ @Test
+ fun test2() {
+ val p = this.javaClass.`package`.name
+
+ println("$p.Class1<$p.Class2>")
+ println("$p.Class1<$p.Class2>".simplifyClass())
+ println("$p.Class1<$p.Class2, $p.Class3>")
+ println("$p.Class1<$p.Class2, $p.Class3>".simplifyClass())
+ println("$p.Class1<$p.Class2<$p.Class3>>")
+ println("$p.Class1<$p.Class2<$p.Class3>>".simplifyClass())
+ println("$p.Class1<$p.Class2<$p.Class3>>")
+ println("$p.Class1\$C<$p.Class2<$p.Class3>>".simplifyClass())
+ }
+}
\ No newline at end of file
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1Composite b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1Composite
new file mode 100644
index 0000000000..450e6970da
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1Composite differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1Int b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1Int
new file mode 100644
index 0000000000..25dcb48d65
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1Int differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1String b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1String
new file mode 100644
index 0000000000..9676f0375f
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.1String differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.2Composite b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.2Composite
new file mode 100644
index 0000000000..0bf3a5c475
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.2Composite differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.2Int b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.2Int
new file mode 100644
index 0000000000..118a23f37b
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.2Int differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.3Int b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.3Int
new file mode 100644
index 0000000000..9f00d59068
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.3Int differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.IntList b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.IntList
new file mode 100644
index 0000000000..d762a9e821
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.IntList differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.MapIntClass b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.MapIntClass
new file mode 100644
index 0000000000..175949d9aa
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.MapIntClass differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.MapIntString b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.MapIntString
new file mode 100644
index 0000000000..67ba352ec4
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.MapIntString differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.StringList b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.StringList
new file mode 100644
index 0000000000..5758d9fa62
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/FileParseTests.StringList differ
diff --git a/experimental/blobinspector/src/test/resources/net/corda/blobinspector/networkParams b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/networkParams
new file mode 100644
index 0000000000..dcdbaa7b5f
Binary files /dev/null and b/experimental/blobinspector/src/test/resources/net/corda/blobinspector/networkParams differ
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/engine/ConnectionStateMachine.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/engine/ConnectionStateMachine.kt
index e16446d2d8..dbf93ec26e 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/engine/ConnectionStateMachine.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/engine/ConnectionStateMachine.kt
@@ -361,7 +361,7 @@ internal class ConnectionStateMachine(serverMode: Boolean,
val connection = event.connection
val channel = connection?.context as? Channel
if (channel != null) {
- val appProperties = HashMap(amqpMessage.applicationProperties.value)
+ val appProperties = HashMap(amqpMessage.applicationProperties.value as Map)
appProperties["_AMQ_VALIDATED_USER"] = remoteLegalName
val localAddress = channel.localAddress() as InetSocketAddress
val remoteAddress = channel.remoteAddress() as InetSocketAddress
@@ -438,7 +438,6 @@ internal class ConnectionStateMachine(serverMode: Boolean,
}
fun transportWriteMessage(msg: SendableMessageImpl) {
- log.debug { "Queue application message write uuid: ${msg.applicationProperties["_AMQ_DUPL_ID"]} ${javax.xml.bind.DatatypeConverter.printHexBinary(msg.payload)}" }
msg.buf = encodePayloadBytes(msg)
val messageQueue = messageQueues.getOrPut(msg.topic, { LinkedList() })
messageQueue.offer(msg)
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPChannelHandler.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPChannelHandler.kt
index 4c9bd812ab..ad5a22bae9 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPChannelHandler.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPChannelHandler.kt
@@ -130,7 +130,6 @@ internal class AMQPChannelHandler(private val serverMode: Boolean,
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
try {
- log.debug { "Received $msg" }
if (msg is ByteBuf) {
eventProcessor!!.transportProcessInput(msg)
}
@@ -143,7 +142,6 @@ internal class AMQPChannelHandler(private val serverMode: Boolean,
override fun write(ctx: ChannelHandlerContext, msg: Any, promise: ChannelPromise) {
try {
try {
- log.debug { "Sent $msg" }
when (msg) {
// Transfers application packet into the AMQP engine.
is SendableMessageImpl -> {
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/CordaClassResolver.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/CordaClassResolver.kt
index b531fce895..6c72829fca 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/CordaClassResolver.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/CordaClassResolver.kt
@@ -90,10 +90,10 @@ class CordaClassResolver(serializationContext: SerializationContext) : DefaultCl
val objectInstance = try {
targetType.declaredFields.singleOrNull {
it.name == "INSTANCE" &&
- it.type == type &&
- Modifier.isStatic(it.modifiers) &&
- Modifier.isFinal(it.modifiers) &&
- Modifier.isPublic(it.modifiers)
+ it.type == type &&
+ Modifier.isStatic(it.modifiers) &&
+ Modifier.isFinal(it.modifiers) &&
+ Modifier.isPublic(it.modifiers)
}?.let {
it.isAccessible = true
type.cast(it.get(null)!!)
@@ -172,7 +172,7 @@ object AllWhitelist : ClassWhitelist {
override fun hasListed(type: Class<*>): Boolean = true
}
-sealed class AbstractMutableClassWhitelist(private val whitelist: MutableSet, private val delegate: ClassWhitelist) : MutableClassWhitelist {
+sealed class AbstractMutableClassWhitelist(private val whitelist: MutableSet, private val delegate: ClassWhitelist) : MutableClassWhitelist {
override fun hasListed(type: Class<*>): Boolean {
/**
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt
index e1550d296f..bda44ea16f 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt
@@ -76,5 +76,5 @@ object DefaultWhitelist : SerializationWhitelist {
// Implementation of X509Certificate.
X509CertImpl::class.java,
CRLReason::class.java
- )
+ )
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationFormat.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationFormat.kt
index 60004f0d44..d469cb688d 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationFormat.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationFormat.kt
@@ -17,8 +17,8 @@ import net.corda.core.utilities.OpaqueBytes
import net.corda.nodeapi.internal.serialization.OrdinalBits.OrdinalWriter
import org.iq80.snappy.SnappyFramedInputStream
import org.iq80.snappy.SnappyFramedOutputStream
-import java.io.OutputStream
import java.io.InputStream
+import java.io.OutputStream
import java.nio.ByteBuffer
import java.util.zip.DeflaterOutputStream
import java.util.zip.InflaterInputStream
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationScheme.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationScheme.kt
index 1b5d3ed93d..47bb652013 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationScheme.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializationScheme.kt
@@ -49,13 +49,15 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
*/
override fun withAttachmentsClassLoader(attachmentHashes: List): SerializationContext {
properties[attachmentsClassLoaderEnabledPropertyName] as? Boolean == true || return this
- val serializationContext = properties[serializationContextKey] as? SerializeAsTokenContextImpl ?: return this // Some tests don't set one.
+ val serializationContext = properties[serializationContextKey] as? SerializeAsTokenContextImpl
+ ?: return this // Some tests don't set one.
try {
return withClassLoader(cache.get(attachmentHashes) {
val missing = ArrayList()
val attachments = ArrayList()
attachmentHashes.forEach { id ->
- serializationContext.serviceHub.attachments.openAttachment(id)?.let { attachments += it } ?: run { missing += id }
+ serializationContext.serviceHub.attachments.openAttachment(id)?.let { attachments += it }
+ ?: run { missing += id }
}
missing.isNotEmpty() && throw MissingAttachmentsException(missing)
AttachmentsClassLoader(attachments, parent = deserializationClassLoader)
@@ -90,7 +92,7 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
open class SerializationFactoryImpl : SerializationFactory() {
companion object {
- private val magicSize = sequenceOf(kryoMagic, amqpMagic).map { it.size }.distinct().single()
+ val magicSize = sequenceOf(kryoMagic, amqpMagic).map { it.size }.distinct().single()
}
private val creator: List = Exception().stackTrace.asList()
@@ -153,8 +155,6 @@ open class SerializationFactoryImpl : SerializationFactory() {
}
-
-
interface SerializationScheme {
fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean
@Throws(NotSerializableException::class)
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializeAsTokenContextImpl.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializeAsTokenContextImpl.kt
index 8cfd815c22..2ac9849a6e 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializeAsTokenContextImpl.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/SerializeAsTokenContextImpl.kt
@@ -62,5 +62,6 @@ class SerializeAsTokenContextImpl(override val serviceHub: ServiceHub, init: Ser
}
}
- override fun getSingleton(className: String) = classNameToSingleton[className] ?: throw IllegalStateException("Unable to find tokenized instance of $className in context $this")
+ override fun getSingleton(className: String) = classNameToSingleton[className]
+ ?: throw IllegalStateException("Unable to find tokenized instance of $className in context $this")
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/UseCaseAwareness.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/UseCaseAwareness.kt
index 605f098662..c2307bddbe 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/UseCaseAwareness.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/UseCaseAwareness.kt
@@ -15,7 +15,8 @@ import net.corda.core.serialization.SerializationFactory
import java.util.*
internal fun checkUseCase(allowedUseCases: EnumSet) {
- val currentContext: SerializationContext = SerializationFactory.currentFactory?.currentContext ?: throw IllegalStateException("Current context is not set")
+ val currentContext: SerializationContext = SerializationFactory.currentFactory?.currentContext
+ ?: throw IllegalStateException("Current context is not set")
if (!allowedUseCases.contains(currentContext.useCase)) {
throw IllegalStateException("UseCase '${currentContext.useCase}' is not within '$allowedUseCases'")
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPDescriptorRegistry.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPDescriptorRegistry.kt
index 762d5bcb21..c3e8aaea5a 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPDescriptorRegistry.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPDescriptorRegistry.kt
@@ -20,7 +20,7 @@ import org.apache.qpid.proton.amqp.UnsignedLong
* Repeated here for brevity:
* 50530 - R3 - Mike Hearn - mike&r3.com
*/
-const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl(32 + 16)
+const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl (32 + 16)
/**
* AMQP descriptor ID's for our custom types.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPPrimitiveSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPPrimitiveSerializer.kt
index 081dfb8222..ce74965c01 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPPrimitiveSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPPrimitiveSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Binary
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
@@ -28,7 +29,14 @@ class AMQPPrimitiveSerializer(clazz: Class<*>) : AMQPSerializer {
override fun writeClassInfo(output: SerializationOutput) {
}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(
+ obj: Any,
+ data: Data,
+ type: Type,
+ output: SerializationOutput,
+ context: SerializationContext,
+ debugIndent: Int
+ ) {
if (obj is ByteArray) {
data.putObject(Binary(obj))
} else {
@@ -39,5 +47,6 @@ class AMQPPrimitiveSerializer(clazz: Class<*>) : AMQPSerializer {
override fun readObject(
obj: Any,
schemas: SerializationSchemas,
- input: DeserializationInput): Any = (obj as? Binary)?.array ?: obj
+ input: DeserializationInput,
+ context: SerializationContext): Any = (obj as? Binary)?.array ?: obj
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializationScheme.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializationScheme.kt
index d2240540f2..88c9f1bbf5 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializationScheme.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializationScheme.kt
@@ -16,8 +16,8 @@ import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
import net.corda.core.cordapp.Cordapp
import net.corda.core.internal.objectOrNewInstance
import net.corda.core.serialization.*
-import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
import net.corda.core.utilities.ByteSequence
+import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
import net.corda.nodeapi.internal.serialization.MutableClassWhitelist
import net.corda.nodeapi.internal.serialization.SerializationScheme
@@ -41,12 +41,12 @@ fun SerializerFactory.addToWhitelist(vararg types: Class<*>) {
open class SerializerFactoryFactory {
open fun make(context: SerializationContext) =
- SerializerFactory(context.whitelist, context.deserializationClassLoader)
+ SerializerFactory(context.whitelist, context.deserializationClassLoader)
}
abstract class AbstractAMQPSerializationScheme(
val cordappLoader: List,
- val sff : SerializerFactoryFactory = SerializerFactoryFactory()
+ val sff: SerializerFactoryFactory = SerializerFactoryFactory()
) : SerializationScheme {
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
@@ -62,7 +62,7 @@ abstract class AbstractAMQPSerializationScheme(
val scanSpec: String? = System.getProperty(SCAN_SPEC_PROP_NAME)
- if(scanSpec == null) {
+ if (scanSpec == null) {
emptyList()
} else {
FastClasspathScanner(scanSpec).addClassLoader(this::class.java.classLoader).scan()
@@ -74,7 +74,7 @@ abstract class AbstractAMQPSerializationScheme(
}
}
- private fun registerCustomSerializers(factory: SerializerFactory) {
+ private fun registerCustomSerializers(context: SerializationContext, factory: SerializerFactory) {
with(factory) {
register(publicKeySerializer)
register(net.corda.nodeapi.internal.serialization.amqp.custom.PrivateKeySerializer)
@@ -131,8 +131,7 @@ abstract class AbstractAMQPSerializationScheme(
protected abstract fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory
protected abstract fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory
- open protected val publicKeySerializer: CustomSerializer.Implements
- = net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer
+ protected open val publicKeySerializer: CustomSerializer.Implements = net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer
private fun getSerializerFactory(context: SerializationContext): SerializerFactory {
return serializerFactoriesForContexts.computeIfAbsent(Pair(context.whitelist, context.deserializationClassLoader)) {
@@ -145,19 +144,20 @@ abstract class AbstractAMQPSerializationScheme(
rpcServerSerializerFactory(context)
else -> sff.make(context)
}.also {
- registerCustomSerializers(it)
+ registerCustomSerializers(context, it)
}
}
}
override fun deserialize(byteSequence: ByteSequence, clazz: Class, context: SerializationContext): T {
val serializerFactory = getSerializerFactory(context)
- return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz)
+ return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz, context)
}
override fun serialize(obj: T, context: SerializationContext): SerializedBytes {
val serializerFactory = getSerializerFactory(context)
- return SerializationOutput(serializerFactory).serialize(obj)
+
+ return SerializationOutput(serializerFactory).serialize(obj, context)
}
protected fun canDeserializeVersion(magic: CordaSerializationMagic) = magic == amqpMagic
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt
index 820c7f8951..458e4e47f6 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type
@@ -40,10 +41,11 @@ interface AMQPSerializer {
/**
* Write the given object, with declared type, to the output.
*/
- fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int = 0)
+ fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int = 0)
/**
* Read the given object from the input. The envelope is provided in case the schema is required.
*/
- fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T
+ fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): T
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ArraySerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ArraySerializer.kt
index b65ab9e6f4..d7bd52cca5 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ArraySerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ArraySerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException
@@ -42,7 +43,8 @@ open class ArraySerializer(override val type: Type, factory: SerializerFactory)
}
override val typeDescriptor by lazy {
- Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}") }
+ Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
+ }
internal val elementType: Type by lazy { type.componentType() }
internal open val typeName by lazy { calcTypeName(type) }
@@ -56,20 +58,24 @@ open class ArraySerializer(override val type: Type, factory: SerializerFactory)
}
}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
// Write described
data.withDescribed(typeNotation.descriptor) {
withList {
for (entry in obj as Array<*>) {
- output.writeObjectOrNull(entry, this, elementType, debugIndent)
+ output.writeObjectOrNull(entry, this, elementType, context, debugIndent)
}
}
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): Any {
if (obj is List<*>) {
- return obj.map { input.readObjectOrNull(it, schemas, elementType) }.toArrayOfType(elementType)
+ return obj.map { input.readObjectOrNull(it, schemas, elementType, context) }.toArrayOfType(elementType)
} else throw NotSerializableException("Expected a List but found $obj")
}
@@ -118,20 +124,24 @@ abstract class PrimArraySerializer(type: Type, factory: SerializerFactory) : Arr
}
}
-class PrimIntArraySerializer(factory: SerializerFactory) :
- PrimArraySerializer(IntArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+class PrimIntArraySerializer(factory: SerializerFactory) : PrimArraySerializer(IntArray::class.java, factory) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
localWriteObject(data) {
- (obj as IntArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+ (obj as IntArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
}
}
}
-class PrimCharArraySerializer(factory: SerializerFactory) :
- PrimArraySerializer(CharArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
- localWriteObject(data) { (obj as CharArray).forEach {
- output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+class PrimCharArraySerializer(factory: SerializerFactory) : PrimArraySerializer(CharArray::class.java, factory) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
+ localWriteObject(data) {
+ (obj as CharArray).forEach {
+ output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1)
+ }
}
}
@@ -145,47 +155,55 @@ class PrimCharArraySerializer(factory: SerializerFactory) :
}
}
-class PrimBooleanArraySerializer(factory: SerializerFactory) :
- PrimArraySerializer(BooleanArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+class PrimBooleanArraySerializer(factory: SerializerFactory) : PrimArraySerializer(BooleanArray::class.java, factory) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
localWriteObject(data) {
- (obj as BooleanArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+ (obj as BooleanArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
}
}
}
class PrimDoubleArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(DoubleArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
localWriteObject(data) {
- (obj as DoubleArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+ (obj as DoubleArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
}
}
}
class PrimFloatArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(FloatArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int) {
localWriteObject(data) {
- (obj as FloatArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+ (obj as FloatArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
}
}
}
class PrimShortArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(ShortArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
localWriteObject(data) {
- (obj as ShortArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+ (obj as ShortArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
}
}
}
class PrimLongArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(LongArray::class.java, factory) {
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
localWriteObject(data) {
- (obj as LongArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
+ (obj as LongArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
}
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CollectionSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CollectionSerializer.kt
index 63ebf26045..d5f027e211 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CollectionSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CollectionSerializer.kt
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
+import net.corda.core.serialization.SerializationContext
import net.corda.core.utilities.NonEmptySet
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
@@ -18,15 +19,14 @@ import java.io.NotSerializableException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.*
-import kotlin.collections.Collection
import kotlin.collections.LinkedHashSet
-import kotlin.collections.Set
/**
* Serialization / deserialization of predefined set of supported [Collection] types covering mostly [List]s and [Set]s.
*/
class CollectionSerializer(val declaredType: ParameterizedType, factory: SerializerFactory) : AMQPSerializer {
- override val type: Type = declaredType as? DeserializedParameterizedType ?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType))
+ override val type: Type = declaredType as? DeserializedParameterizedType
+ ?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType))
override val typeDescriptor by lazy {
Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
}
@@ -60,7 +60,8 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
}
private fun deriveParametrizedType(declaredType: Type, collectionClass: Class>): ParameterizedType =
- (declaredType as? ParameterizedType) ?: DeserializedParameterizedType(collectionClass, arrayOf(SerializerFactory.AnyType))
+ (declaredType as? ParameterizedType)
+ ?: DeserializedParameterizedType(collectionClass, arrayOf(SerializerFactory.AnyType))
private fun findMostSuitableCollectionType(actualClass: Class<*>): Class> =
@@ -83,12 +84,13 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
data: Data,
type: Type,
output: SerializationOutput,
+ context: SerializationContext,
debugIndent: Int) = ifThrowsAppend({ declaredType.typeName }) {
// Write described
data.withDescribed(typeNotation.descriptor) {
withList {
for (entry in obj as Collection<*>) {
- output.writeObjectOrNull(entry, this, declaredType.actualTypeArguments[0], debugIndent)
+ output.writeObjectOrNull(entry, this, declaredType.actualTypeArguments[0], context, debugIndent)
}
}
}
@@ -97,8 +99,11 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
override fun readObject(
obj: Any,
schemas: SerializationSchemas,
- input: DeserializationInput): Any = ifThrowsAppend({ declaredType.typeName }) {
+ input: DeserializationInput,
+ context: SerializationContext): Any = ifThrowsAppend({ declaredType.typeName }) {
// TODO: Can we verify the entries in the list?
- concreteBuilder((obj as List<*>).map { input.readObjectOrNull(it, schemas, declaredType.actualTypeArguments[0]) })
+ concreteBuilder((obj as List<*>).map {
+ input.readObjectOrNull(it, schemas, declaredType.actualTypeArguments[0], context)
+ })
}
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappCustomSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappCustomSerializer.kt
index 5cf9fea470..e2038fb626 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappCustomSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappCustomSerializer.kt
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
+import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationCustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.amqp.Symbol
@@ -74,22 +75,25 @@ class CorDappCustomSerializer(
override fun writeClassInfo(output: SerializationOutput) {}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
val proxy = uncheckedCast,
SerializationCustomSerializer>(serializer).toProxy(obj)
data.withDescribed(descriptor) {
data.withList {
- proxySerializer.propertySerializers.serializationOrder.forEach {
- it.getter.writeProperty(proxy, this, output)
+ proxySerializer.propertySerializers.serializationOrder.forEach {
+ it.getter.writeProperty(proxy, this, output, context)
}
}
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput) =
- uncheckedCast, SerializationCustomSerializer>(
- serializer).fromProxy(uncheckedCast(proxySerializer.readObject(obj, schemas, input)))!!
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ) = uncheckedCast, SerializationCustomSerializer>(
+ serializer).fromProxy(uncheckedCast(proxySerializer.readObject(obj, schemas, input, context)))!!
override fun isSerializerFor(clazz: Class<*>) = clazz == type
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CustomSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CustomSerializer.kt
index c8eaef09eb..b6ace5113a 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CustomSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/CustomSerializer.kt
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
@@ -50,13 +51,16 @@ abstract class CustomSerializer : AMQPSerializer, SerializerFor {
*/
override val revealSubclassesInSchema: Boolean get() = false
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
data.withDescribed(descriptor) {
- writeDescribedObject(uncheckedCast(obj), data, type, output)
+ writeDescribedObject(uncheckedCast(obj), data, type, output, context)
}
}
- abstract fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput)
+ abstract fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext)
/**
* This custom serializer represents a sort of symbolic link from a subclass to a super class, where the super
@@ -87,12 +91,16 @@ abstract class CustomSerializer : AMQPSerializer, SerializerFor {
override val descriptor: Descriptor = Descriptor(typeDescriptor)
- override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
- superClassSerializer.writeDescribedObject(obj, data, type, output)
+ override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
+ superClassSerializer.writeDescribedObject(obj, data, type, output, context)
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T {
- return superClassSerializer.readObject(obj, schemas, input)
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): T {
+ return superClassSerializer.readObject(obj, schemas, input, context)
}
}
@@ -134,7 +142,12 @@ abstract class CustomSerializer : AMQPSerializer, SerializerFor {
private val proxySerializer: ObjectSerializer by lazy { ObjectSerializer(proxyClass, factory) }
override val schemaForDocumentation: Schema by lazy {
- val typeNotations = mutableSetOf(CompositeType(nameForType(type), null, emptyList(), descriptor, (proxySerializer.typeNotation as CompositeType).fields))
+ val typeNotations = mutableSetOf(
+ CompositeType(
+ nameForType(type),
+ null,
+ emptyList(),
+ descriptor, (proxySerializer.typeNotation as CompositeType).fields))
for (additional in additionalSerializers) {
typeNotations.addAll(additional.schemaForDocumentation.types)
}
@@ -148,17 +161,21 @@ abstract class CustomSerializer : AMQPSerializer, SerializerFor {
protected abstract fun fromProxy(proxy: P): T
- override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
+ override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
val proxy = toProxy(obj)
data.withList {
proxySerializer.propertySerializers.serializationOrder.forEach {
- it.getter.writeProperty(proxy, this, output)
+ it.getter.writeProperty(proxy, this, output, context)
}
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T {
- val proxy: P = uncheckedCast(proxySerializer.readObject(obj, schemas, input))
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): T {
+ val proxy: P = uncheckedCast(proxySerializer.readObject(obj, schemas, input, context))
return fromProxy(proxy)
}
}
@@ -186,11 +203,15 @@ abstract class CustomSerializer : AMQPSerializer, SerializerFor {
SerializerFactory.primitiveTypeName(String::class.java)!!,
descriptor, emptyList())))
- override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
+ override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
data.putString(unmaker(obj))
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): T {
val proxy = obj as String
return maker(proxy)
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializationInput.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializationInput.kt
index 78d4402516..1c2cb29c44 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializationInput.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializationInput.kt
@@ -14,6 +14,7 @@ import com.esotericsoftware.kryo.io.ByteBufferInputStream
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.getStackTraceAsString
import net.corda.core.serialization.EncodingWhitelist
+import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializedBytes
import net.corda.core.utilities.ByteSequence
import net.corda.nodeapi.internal.serialization.CordaSerializationEncoding
@@ -45,7 +46,7 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
private val encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist) {
private val objectHistory: MutableList = mutableListOf()
- internal companion object {
+ companion object {
private val BYTES_NEEDED_TO_PEEK: Int = 23
fun peekSize(bytes: ByteArray): Int {
@@ -70,9 +71,10 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
@VisibleForTesting
@Throws(NotSerializableException::class)
- internal fun withDataBytes(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist, task: (ByteBuffer) -> T): T {
+ fun withDataBytes(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist, task: (ByteBuffer) -> T): T {
// Check that the lead bytes match expected header
- val amqpSequence = amqpMagic.consume(byteSequence) ?: throw NotSerializableException("Serialization header does not match.")
+ val amqpSequence = amqpMagic.consume(byteSequence)
+ ?: throw NotSerializableException("Serialization header does not match.")
var stream: InputStream = ByteBufferInputStream(amqpSequence)
try {
while (true) {
@@ -89,25 +91,27 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
stream.close()
}
}
- }
- @Throws(NotSerializableException::class)
- inline fun deserialize(bytes: SerializedBytes): T = deserialize(bytes, T::class.java)
-
- @Throws(NotSerializableException::class)
- inline internal fun deserializeAndReturnEnvelope(bytes: SerializedBytes): ObjectAndEnvelope =
- deserializeAndReturnEnvelope(bytes, T::class.java)
-
- @Throws(NotSerializableException::class)
- internal fun getEnvelope(byteSequence: ByteSequence): Envelope {
- return withDataBytes(byteSequence, encodingWhitelist) { dataBytes ->
- val data = Data.Factory.create()
- val expectedSize = dataBytes.remaining()
- if (data.decode(dataBytes) != expectedSize.toLong()) throw NotSerializableException("Unexpected size of data")
- Envelope.get(data)
+ @Throws(NotSerializableException::class)
+ fun getEnvelope(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist): Envelope {
+ return withDataBytes(byteSequence, encodingWhitelist) { dataBytes ->
+ val data = Data.Factory.create()
+ val expectedSize = dataBytes.remaining()
+ if (data.decode(dataBytes) != expectedSize.toLong()) throw NotSerializableException("Unexpected size of data")
+ Envelope.get(data)
+ }
}
}
+
+ @Throws(NotSerializableException::class)
+ fun getEnvelope(byteSequence: ByteSequence) = Companion.getEnvelope(byteSequence, encodingWhitelist)
+
+ @Throws(NotSerializableException::class)
+ inline fun deserialize(bytes: SerializedBytes, context: SerializationContext): T =
+ deserialize(bytes, T::class.java, context)
+
+
@Throws(NotSerializableException::class)
private fun des(generator: () -> R): R {
try {
@@ -127,23 +131,37 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
* be deserialized and a schema describing the types of the objects.
*/
@Throws(NotSerializableException::class)
- fun deserialize(bytes: ByteSequence, clazz: Class): T = des {
- val envelope = getEnvelope(bytes)
- clazz.cast(readObjectOrNull(envelope.obj, SerializationSchemas(envelope.schema, envelope.transformsSchema), clazz))
- }
+ fun deserialize(bytes: ByteSequence, clazz: Class, context: SerializationContext): T =
+ des {
+ val envelope = getEnvelope(bytes, encodingWhitelist)
+ clazz.cast(readObjectOrNull(envelope.obj, SerializationSchemas(envelope.schema, envelope.transformsSchema),
+ clazz, context))
+ }
@Throws(NotSerializableException::class)
- fun deserializeAndReturnEnvelope(bytes: SerializedBytes, clazz: Class): ObjectAndEnvelope = des {
- val envelope = getEnvelope(bytes)
+ fun deserializeAndReturnEnvelope(
+ bytes: SerializedBytes,
+ clazz: Class,
+ context: SerializationContext
+ ): ObjectAndEnvelope = des {
+ val envelope = getEnvelope(bytes, encodingWhitelist)
// Now pick out the obj and schema from the envelope.
- ObjectAndEnvelope(clazz.cast(readObjectOrNull(envelope.obj, SerializationSchemas(envelope.schema, envelope.transformsSchema), clazz)), envelope)
+ ObjectAndEnvelope(
+ clazz.cast(readObjectOrNull(
+ envelope.obj,
+ SerializationSchemas(envelope.schema, envelope.transformsSchema),
+ clazz,
+ context)),
+ envelope)
}
- internal fun readObjectOrNull(obj: Any?, schema: SerializationSchemas, type: Type, offset: Int = 0): Any? {
- return if (obj == null) null else readObject(obj, schema, type, offset)
+ internal fun readObjectOrNull(obj: Any?, schema: SerializationSchemas, type: Type, context: SerializationContext,
+ offset: Int = 0
+ ): Any? {
+ return if (obj == null) null else readObject(obj, schema, type, context, offset)
}
- internal fun readObject(obj: Any, schemas: SerializationSchemas, type: Type, debugIndent: Int = 0): Any =
+ internal fun readObject(obj: Any, schemas: SerializationSchemas, type: Type, context: SerializationContext, debugIndent: Int = 0): Any =
if (obj is DescribedType && ReferencedObject.DESCRIPTOR == obj.descriptor) {
// It must be a reference to an instance that has already been read, cheaply and quickly returning it by reference.
val objectIndex = (obj.described as UnsignedInteger).toInt()
@@ -164,19 +182,20 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
// Look up serializer in factory by descriptor
val serializer = serializerFactory.get(obj.descriptor, schemas)
if (SerializerFactory.AnyType != type && serializer.type != type && with(serializer.type) {
- !isSubClassOf(type) && !materiallyEquivalentTo(type)
- }) {
+ !isSubClassOf(type) && !materiallyEquivalentTo(type)
+ }) {
throw NotSerializableException("Described type with descriptor ${obj.descriptor} was " +
"expected to be of type $type but was ${serializer.type}")
}
- serializer.readObject(obj.described, schemas, this)
+ serializer.readObject(obj.described, schemas, this, context)
}
is Binary -> obj.array
else -> obj // this will be the case for primitive types like [boolean] et al.
}
// Store the reference in case we need it later on.
- // Skip for primitive types as they are too small and overhead of referencing them will be much higher than their content
+ // Skip for primitive types as they are too small and overhead of referencing them will be much higher
+ // than their content
if (suitableForObjectReference(objectRead.javaClass)) {
objectHistory.add(objectRead)
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt
index d3d60ea93e..d45febb609 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException
@@ -75,7 +76,8 @@ class EnumEvolutionSerializer(
new: AMQPSerializer,
factory: SerializerFactory,
schemas: SerializationSchemas): AMQPSerializer {
- val wireTransforms = schemas.transforms.types[old.name] ?: EnumMap>(TransformTypes::class.java)
+ val wireTransforms = schemas.transforms.types[old.name]
+ ?: EnumMap>(TransformTypes::class.java)
val localTransforms = TransformsSchema.get(old.name, factory)
// remember, the longer the list the newer we're assuming the transform set it as we assume
@@ -127,7 +129,9 @@ class EnumEvolutionSerializer(
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): Any {
val enumName = (obj as List<*>)[0] as String
if (enumName !in conversions) {
@@ -141,7 +145,9 @@ class EnumEvolutionSerializer(
throw UnsupportedOperationException("It should be impossible to write an evolution serializer")
}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
throw UnsupportedOperationException("It should be impossible to write an evolution serializer")
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumSerializer.kt
index e481950924..15b6fbfdb3 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException
@@ -38,7 +39,9 @@ class EnumSerializer(declaredType: Type, declaredClass: Class<*>, factory: Seria
output.writeTypeNotations(typeNotation)
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): Any {
val enumName = (obj as List<*>)[0] as String
val enumOrd = obj[1] as Int
val fromOrd = type.asClass()!!.enumConstants[enumOrd] as Enum<*>?
@@ -50,7 +53,9 @@ class EnumSerializer(declaredType: Type, declaredClass: Class<*>, factory: Seria
return fromOrd
}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
if (obj !is Enum<*>) throw NotSerializableException("Serializing $obj as enum when it isn't")
data.withDescribed(typeNotation.descriptor) {
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/Envelope.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/Envelope.kt
index 9b27e264c1..b8941c7143 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/Envelope.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/Envelope.kt
@@ -39,7 +39,7 @@ data class Envelope(val obj: Any?, val schema: Schema, val transformsSchema: Tra
fun get(data: Data): Envelope {
val describedType = data.`object` as DescribedType
if (describedType.descriptor != DESCRIPTOR) {
- throw NotSerializableException("Unexpected descriptor ${describedType.descriptor}.")
+ throw NotSerializableException("Unexpected descriptor ${describedType.descriptor}, should be $DESCRIPTOR.")
}
val list = describedType.described as List<*>
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt
index 6f6ddac708..f08f9dce2c 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt
@@ -11,10 +11,11 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.serialization.carpenter.getTypeAsClass
import org.apache.qpid.proton.codec.Data
-import java.lang.reflect.Type
import java.io.NotSerializableException
+import java.lang.reflect.Type
import kotlin.reflect.KFunction
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.javaType
@@ -49,12 +50,13 @@ abstract class EvolutionSerializer(
* @param property object to read the actual property value
*/
data class OldParam(var resultsIndex: Int, val property: PropertySerializer) {
- fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput, new: Array) =
- property.readProperty(obj, schemas, input).apply {
- if(resultsIndex >= 0) {
- new[resultsIndex] = this
- }
- }
+ fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput,
+ new: Array, context: SerializationContext
+ ) = property.readProperty(obj, schemas, input, context).apply {
+ if (resultsIndex >= 0) {
+ new[resultsIndex] = this
+ }
+ }
}
companion object {
@@ -106,7 +108,7 @@ abstract class EvolutionSerializer(
"New parameter ${it.value.name} is mandatory, should be nullable for evolution to worK")
}
}
- return EvolutionSerializerViaConstructor (new.type, factory, readersAsSerialized, constructor, constructorArgs)
+ return EvolutionSerializerViaConstructor(new.type, factory, readersAsSerialized, constructor, constructorArgs)
}
private fun makeWithSetters(
@@ -118,7 +120,7 @@ abstract class EvolutionSerializer(
val setters = propertiesForSerializationFromSetters(classProperties,
new.type,
factory).associateBy({ it.getter.name }, { it })
- return EvolutionSerializerViaSetters (new.type, factory, readersAsSerialized, constructor, setters)
+ return EvolutionSerializerViaSetters(new.type, factory, readersAsSerialized, constructor, setters)
}
/**
@@ -153,14 +155,15 @@ abstract class EvolutionSerializer(
return if (classProperties.isNotEmpty() && constructor.parameters.isEmpty()) {
makeWithSetters(new, factory, constructor, readersAsSerialized, classProperties)
- }
- else {
+ } else {
makeWithConstructor(new, factory, constructor, readersAsSerialized)
}
}
}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
throw UnsupportedOperationException("It should be impossible to write an evolution serializer")
}
}
@@ -170,7 +173,7 @@ class EvolutionSerializerViaConstructor(
factory: SerializerFactory,
oldReaders: Map,
kotlinConstructor: KFunction?,
- private val constructorArgs: Array) : EvolutionSerializer (clazz, factory, oldReaders, kotlinConstructor) {
+ private val constructorArgs: Array) : EvolutionSerializer(clazz, factory, oldReaders, kotlinConstructor) {
/**
* Unlike a normal [readObject] call where we simply apply the parameter deserialisers
* to the object list of values we need to map that list, which is ordered per the
@@ -180,15 +183,16 @@ class EvolutionSerializerViaConstructor(
*
* TODO: Object references
*/
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): Any {
if (obj !is List<*>) throw NotSerializableException("Body of described type is unexpected $obj")
// *must* read all the parameters in the order they were serialized
- oldReaders.values.zip(obj).map { it.first.readProperty(it.second, schemas, input, constructorArgs) }
+ oldReaders.values.zip(obj).map { it.first.readProperty(it.second, schemas, input, constructorArgs, context) }
- return javaConstructor?.newInstance(*(constructorArgs)) ?:
- throw NotSerializableException(
- "Attempt to deserialize an interface: $clazz. Serialized form is invalid.")
+ return javaConstructor?.newInstance(*(constructorArgs)) ?: throw NotSerializableException(
+ "Attempt to deserialize an interface: $clazz. Serialized form is invalid.")
}
}
@@ -201,18 +205,20 @@ class EvolutionSerializerViaSetters(
factory: SerializerFactory,
oldReaders: Map,
kotlinConstructor: KFunction?,
- private val setters: Map) : EvolutionSerializer (clazz, factory, oldReaders, kotlinConstructor) {
+ private val setters: Map) : EvolutionSerializer(clazz, factory, oldReaders, kotlinConstructor) {
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): Any {
if (obj !is List<*>) throw NotSerializableException("Body of described type is unexpected $obj")
- val instance : Any = javaConstructor?.newInstance() ?: throw NotSerializableException (
+ val instance: Any = javaConstructor?.newInstance() ?: throw NotSerializableException(
"Failed to instantiate instance of object $clazz")
// *must* read all the parameters in the order they were serialized
oldReaders.values.zip(obj).forEach {
// if that property still exists on the new object then set it
- it.first.property.readProperty(it.second, schemas, input).apply {
+ it.first.property.readProperty(it.second, schemas, input, context).apply {
setters[it.first.property.name]?.set(instance, this)
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/MapSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/MapSerializer.kt
index 8eb5c4332b..d12125d90b 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/MapSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/MapSerializer.kt
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException
@@ -18,9 +19,6 @@ import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.*
import kotlin.collections.LinkedHashMap
-import kotlin.collections.Map
-import kotlin.collections.iterator
-import kotlin.collections.map
private typealias MapCreationFunction = (Map<*, *>) -> Map<*, *>
@@ -28,8 +26,8 @@ private typealias MapCreationFunction = (Map<*, *>) -> Map<*, *>
* Serialization / deserialization of certain supported [Map] types.
*/
class MapSerializer(private val declaredType: ParameterizedType, factory: SerializerFactory) : AMQPSerializer {
- override val type: Type = (declaredType as? DeserializedParameterizedType) ?:
- DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType), factory.classloader)
+ override val type: Type = (declaredType as? DeserializedParameterizedType)
+ ?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType), factory.classloader)
override val typeDescriptor: Symbol = Symbol.valueOf(
"$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
@@ -67,7 +65,8 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
}
private fun deriveParametrizedType(declaredType: Type, collectionClass: Class>): ParameterizedType =
- (declaredType as? ParameterizedType) ?: DeserializedParameterizedType(collectionClass, arrayOf(SerializerFactory.AnyType, SerializerFactory.AnyType))
+ (declaredType as? ParameterizedType)
+ ?: DeserializedParameterizedType(collectionClass, arrayOf(SerializerFactory.AnyType, SerializerFactory.AnyType))
private fun findMostSuitableMapType(actualClass: Class<*>): Class> =
@@ -90,6 +89,7 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
data: Data,
type: Type,
output: SerializationOutput,
+ context: SerializationContext,
debugIndent: Int) = ifThrowsAppend({ declaredType.typeName }) {
obj.javaClass.checkSupportedMapType()
// Write described
@@ -98,22 +98,25 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
data.putMap()
data.enter()
for ((key, value) in obj as Map<*, *>) {
- output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0], debugIndent)
- output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1], debugIndent)
+ output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0], context, debugIndent)
+ output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1], context, debugIndent)
}
data.exit() // exit map
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any = ifThrowsAppend({ declaredType.typeName }) {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): Any = ifThrowsAppend({ declaredType.typeName }) {
// TODO: General generics question. Do we need to validate that entries in Maps and Collections match the generic type? Is it a security hole?
- val entries: Iterable> = (obj as Map<*, *>).map { readEntry(schemas, input, it) }
+ val entries: Iterable> = (obj as Map<*, *>).map { readEntry(schemas, input, it, context) }
concreteBuilder(entries.toMap())
}
- private fun readEntry(schemas: SerializationSchemas, input: DeserializationInput, entry: Map.Entry) =
- input.readObjectOrNull(entry.key, schemas, declaredType.actualTypeArguments[0]) to
- input.readObjectOrNull(entry.value, schemas, declaredType.actualTypeArguments[1])
+ private fun readEntry(schemas: SerializationSchemas, input: DeserializationInput, entry: Map.Entry,
+ context: SerializationContext
+ ) = input.readObjectOrNull(entry.key, schemas, declaredType.actualTypeArguments[0], context) to
+ input.readObjectOrNull(entry.value, schemas, declaredType.actualTypeArguments[1], context)
// Cannot use * as a bound for EnumMap and EnumSet since * is not an enum. So, we use a sample enum instead.
// We don't actually care about the type, we just need to make the compiler happier.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt
index 447ca44181..c903a13019 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.trace
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
@@ -67,6 +68,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
data: Data,
type: Type,
output: SerializationOutput,
+ context: SerializationContext,
debugIndent: Int) = ifThrowsAppend({ clazz.typeName }
) {
if (propertySerializers.size != javaConstructor?.parameterCount &&
@@ -82,7 +84,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
// Write list
withList {
propertySerializers.serializationOrder.forEach { property ->
- property.getter.writeProperty(obj, this, output, debugIndent + 1)
+ property.getter.writeProperty(obj, this, output, context, debugIndent + 1)
}
}
}
@@ -91,16 +93,17 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
override fun readObject(
obj: Any,
schemas: SerializationSchemas,
- input: DeserializationInput): Any = ifThrowsAppend({ clazz.typeName }) {
+ input: DeserializationInput,
+ context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
if (obj is List<*>) {
if (obj.size > propertySerializers.size) {
throw NotSerializableException("Too many properties in described type $typeName")
}
return if (propertySerializers.byConstructor) {
- readObjectBuildViaConstructor(obj, schemas, input)
+ readObjectBuildViaConstructor(obj, schemas, input, context)
} else {
- readObjectBuildViaSetters(obj, schemas, input)
+ readObjectBuildViaSetters(obj, schemas, input, context)
}
} else {
throw NotSerializableException("Body of described type is unexpected $obj")
@@ -110,12 +113,13 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
private fun readObjectBuildViaConstructor(
obj: List<*>,
schemas: SerializationSchemas,
- input: DeserializationInput): Any = ifThrowsAppend({ clazz.typeName }) {
+ input: DeserializationInput,
+ context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
logger.trace { "Calling construction based construction for ${clazz.typeName}" }
return construct(propertySerializers.serializationOrder
.zip(obj)
- .map { Pair(it.first.initialPosition, it.first.getter.readProperty(it.second, schemas, input)) }
+ .map { Pair(it.first.initialPosition, it.first.getter.readProperty(it.second, schemas, input, context)) }
.sortedWith(compareBy({ it.first }))
.map { it.second })
}
@@ -123,7 +127,8 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
private fun readObjectBuildViaSetters(
obj: List<*>,
schemas: SerializationSchemas,
- input: DeserializationInput): Any = ifThrowsAppend({ clazz.typeName }) {
+ input: DeserializationInput,
+ context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
logger.trace { "Calling setter based construction for ${clazz.typeName}" }
val instance: Any = javaConstructor?.newInstance() ?: throw NotSerializableException(
@@ -133,7 +138,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
// do it in doesn't matter
val propertiesFromBlob = obj
.zip(propertySerializers.serializationOrder)
- .map { it.second.getter.readProperty(it.first, schemas, input) }
+ .map { it.second.getter.readProperty(it.first, schemas, input, context) }
// one by one take a property and invoke the setter on the class
propertySerializers.serializationOrder.zip(propertiesFromBlob).forEach {
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt
index 61dbd7ec3d..9786d24998 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Binary
import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type
@@ -19,8 +20,8 @@ import java.lang.reflect.Type
*/
sealed class PropertySerializer(val name: String, val propertyReader: PropertyReader, val resolvedType: Type) {
abstract fun writeClassInfo(output: SerializationOutput)
- abstract fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int = 0)
- abstract fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any?
+ abstract fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, context: SerializationContext, debugIndent: Int = 0)
+ abstract fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any?
val type: String = generateType()
val requires: List = generateRequires()
@@ -86,12 +87,15 @@ sealed class PropertySerializer(val name: String, val propertyReader: PropertyRe
override fun readProperty(
obj: Any?,
schemas: SerializationSchemas,
- input: DeserializationInput): Any? = ifThrowsAppend({ nameForDebug }) {
- input.readObjectOrNull(obj, schemas, resolvedType)
+ input: DeserializationInput,
+ context: SerializationContext): Any? = ifThrowsAppend({ nameForDebug }) {
+ input.readObjectOrNull(obj, schemas, resolvedType, context)
}
- override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int) = ifThrowsAppend({ nameForDebug }) {
- output.writeObjectOrNull(propertyReader.read(obj), data, resolvedType, debugIndent)
+ override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int) = ifThrowsAppend({ nameForDebug }
+ ) {
+ output.writeObjectOrNull(propertyReader.read(obj), data, resolvedType, context, debugIndent)
}
private val nameForDebug = "$name(${resolvedType.typeName})"
@@ -106,11 +110,15 @@ sealed class PropertySerializer(val name: String, val propertyReader: PropertyRe
resolvedType: Type) : PropertySerializer(name, readMethod, resolvedType) {
override fun writeClassInfo(output: SerializationOutput) {}
- override fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? {
+ override fun readProperty(obj: Any?, schemas: SerializationSchemas,
+ input: DeserializationInput, context: SerializationContext
+ ): Any? {
return if (obj is Binary) obj.array else obj
}
- override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int) {
+ override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
val value = propertyReader.read(obj)
if (value is ByteArray) {
data.putObject(Binary(value))
@@ -122,18 +130,22 @@ sealed class PropertySerializer(val name: String, val propertyReader: PropertyRe
/**
* A property serializer for the AMQP char type, needed as a specialisation as the underlying
- * value of the character is stored in numeric UTF-16 form and on deserialisation requires explicit
+ * value of the character is stored in numeric UTF-16 form and on deserialization requires explicit
* casting back to a char otherwise it's treated as an Integer and a TypeMismatch occurs
*/
class AMQPCharPropertySerializer(name: String, readMethod: PropertyReader) :
PropertySerializer(name, readMethod, Character::class.java) {
override fun writeClassInfo(output: SerializationOutput) {}
- override fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? {
+ override fun readProperty(obj: Any?, schemas: SerializationSchemas,
+ input: DeserializationInput, context: SerializationContext
+ ): Any? {
return if (obj == null) null else (obj as Short).toChar()
}
- override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int) {
+ override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
val input = propertyReader.read(obj)
if (input != null) data.putShort((input as Char).toShort()) else data.putNull()
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializers.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializers.kt
index 5e7e17765c..c7b72c646f 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializers.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializers.kt
@@ -12,12 +12,12 @@ package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.utilities.loggerFor
import java.io.NotSerializableException
+import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Type
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.javaGetter
import kotlin.reflect.jvm.kotlinProperty
-import java.lang.reflect.Field
abstract class PropertyReader {
abstract fun read(obj: Any?): Any?
@@ -151,6 +151,7 @@ class PropertyAccessorGetterSetter(
*/
setter.isAccessible = true
}
+
/**
* Invokes the setter on the underlying object passing in the serialized value.
*/
@@ -172,7 +173,7 @@ class PropertyAccessorConstructor(
* calls to the explicit setter should be an error.
*/
override fun set(instance: Any, obj: Any?) {
- NotSerializableException ("Attempting to access a setter on an object being instantiated " +
+ NotSerializableException("Attempting to access a setter on an object being instantiated " +
"via its constructor.")
}
}
@@ -197,7 +198,7 @@ abstract class PropertySerializers(
is PropertyAccessorGetterSetter -> PropertySerializersSetter(serializationOrder)
null -> PropertySerializersNoProperties()
else -> {
- throw NotSerializableException ("Unknown Property Accessor type, cannot create set")
+ throw NotSerializableException("Unknown Property Accessor type, cannot create set")
}
}
}
@@ -206,7 +207,7 @@ abstract class PropertySerializers(
abstract val byConstructor: Boolean
}
-class PropertySerializersNoProperties : PropertySerializers (emptyList()) {
+class PropertySerializersNoProperties : PropertySerializers(emptyList()) {
override val byConstructor get() = true
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt
index 950099ffcc..e231532633 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt
@@ -105,7 +105,7 @@ data class PropertyDescriptor(var field: Field?, var setter: Method?, var getter
constructor() : this(null, null, null, null)
- fun preferredGetter() : Method? = getter ?: iser
+ fun preferredGetter(): Method? = getter ?: iser
}
object PropertyDescriptorsRegex {
@@ -173,8 +173,7 @@ fun Class.propertyDescriptors(): Map {
// fails the getter doesn't refer to a property directly, but may refer to a constructor
// parameter that shadows a property
val properties =
- classProperties[groups[2]!!.value] ?:
- classProperties[groups[2]!!.value.decapitalize()] ?:
+ classProperties[groups[2]!!.value] ?: classProperties[groups[2]!!.value.decapitalize()] ?:
// take into account those constructor properties that don't directly map to a named
// property which are, by default, already added to the map
classProperties.computeIfAbsent(groups[2]!!.value) { PropertyDescriptor() }
@@ -255,9 +254,9 @@ internal fun propertiesForSerializationFromConstructor(
// We will already have disambiguated getA for property A or a but we still need to cope
// with the case we don't know the case of A when the parameter doesn't match a property
// but has a getter
- val matchingProperty = classProperties[name] ?: classProperties[name.capitalize()] ?:
- throw NotSerializableException(
- "Constructor parameter - \"$name\" - doesn't refer to a property of \"$clazz\"")
+ val matchingProperty = classProperties[name] ?: classProperties[name.capitalize()]
+ ?: throw NotSerializableException(
+ "Constructor parameter - \"$name\" - doesn't refer to a property of \"$clazz\"")
// If the property has a getter we'll use that to retrieve it's value from the instance, if it doesn't
// *for *know* we switch to a reflection based method
@@ -277,8 +276,8 @@ internal fun propertiesForSerializationFromConstructor(
Pair(PublicPropertyReader(getter), returnType)
} else {
- val field = classProperties[name]!!.field ?:
- throw NotSerializableException("No property matching constructor parameter named - \"$name\" - " +
+ val field = classProperties[name]!!.field
+ ?: throw NotSerializableException("No property matching constructor parameter named - \"$name\" - " +
"of \"$clazz\". If using Java, check that you have the -parameters option specified " +
"in the Java compiler. Alternately, provide a proxy serializer " +
"(SerializationCustomSerializer) if recompiling isn't an option")
@@ -325,7 +324,7 @@ fun propertiesForSerializationFromSetters(
}
// Make sure the getter returns the same type (within inheritance bounds) the setter accepts.
- if (!(TypeToken.of (getter.genericReturnType).isSupertypeOf(setterType))) {
+ if (!(TypeToken.of(getter.genericReturnType).isSupertypeOf(setterType))) {
throw NotSerializableException("Defined setter for parameter ${property.value.field?.name} " +
"takes parameter of type $setterType yet the defined getter returns a value of type " +
"${getter.returnType} [${getter.genericReturnType}]")
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutput.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutput.kt
index 2f4c862362..9b29316260 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutput.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutput.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationEncoding
import net.corda.core.serialization.SerializedBytes
import net.corda.nodeapi.internal.serialization.CordaSerializationEncoding
@@ -33,7 +34,10 @@ data class BytesAndSchemas(
* @param serializerFactory This is the factory for [AMQPSerializer] instances and can be shared across multiple
* instances and threads.
*/
-open class SerializationOutput @JvmOverloads constructor(internal val serializerFactory: SerializerFactory, private val encoding: SerializationEncoding? = null) {
+open class SerializationOutput @JvmOverloads constructor(
+ internal val serializerFactory: SerializerFactory,
+ private val encoding: SerializationEncoding? = null
+) {
private val objectHistory: MutableMap = IdentityHashMap()
private val serializerHistory: MutableSet> = LinkedHashSet()
internal val schemaHistory: MutableSet = LinkedHashSet()
@@ -44,19 +48,18 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
* of AMQP serialization constructed the serialized form.
*/
@Throws(NotSerializableException::class)
- fun serialize(obj: T): SerializedBytes {
+ fun serialize(obj: T, context: SerializationContext): SerializedBytes {
try {
- return _serialize(obj)
+ return _serialize(obj, context)
} finally {
andFinally()
}
}
-
@Throws(NotSerializableException::class)
- fun serializeAndReturnSchema(obj: T): BytesAndSchemas {
+ fun serializeAndReturnSchema(obj: T, context: SerializationContext): BytesAndSchemas {
try {
- val blob = _serialize(obj)
+ val blob = _serialize(obj, context)
val schema = Schema(schemaHistory.toList())
return BytesAndSchemas(blob, schema, TransformsSchema.build(schema, serializerFactory))
} finally {
@@ -70,11 +73,11 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
schemaHistory.clear()
}
- internal fun _serialize(obj: T): SerializedBytes {
+ internal fun _serialize(obj: T, context: SerializationContext): SerializedBytes {
val data = Data.Factory.create()
data.withDescribed(Envelope.DESCRIPTOR_OBJECT) {
withList {
- writeObject(obj, this)
+ writeObject(obj, this, context)
val schema = Schema(schemaHistory.toList())
writeSchema(schema, this)
writeTransformSchema(TransformsSchema.build(schema, serializerFactory), this)
@@ -97,8 +100,8 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
})
}
- internal fun writeObject(obj: Any, data: Data) {
- writeObject(obj, data, obj.javaClass)
+ internal fun writeObject(obj: Any, data: Data, context: SerializationContext) {
+ writeObject(obj, data, obj.javaClass, context)
}
open fun writeSchema(schema: Schema, data: Data) {
@@ -109,15 +112,15 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
data.putObject(transformsSchema)
}
- internal fun writeObjectOrNull(obj: Any?, data: Data, type: Type, debugIndent: Int) {
+ internal fun writeObjectOrNull(obj: Any?, data: Data, type: Type, context: SerializationContext, debugIndent: Int) {
if (obj == null) {
data.putNull()
} else {
- writeObject(obj, data, if (type == SerializerFactory.AnyType) obj.javaClass else type, debugIndent)
+ writeObject(obj, data, if (type == SerializerFactory.AnyType) obj.javaClass else type, context, debugIndent)
}
}
- internal fun writeObject(obj: Any, data: Data, type: Type, debugIndent: Int = 0) {
+ internal fun writeObject(obj: Any, data: Data, type: Type, context: SerializationContext, debugIndent: Int = 0) {
val serializer = serializerFactory.get(obj.javaClass, type)
if (serializer !in serializerHistory) {
serializerHistory.add(serializer)
@@ -126,7 +129,7 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
val retrievedRefCount = objectHistory[obj]
if (retrievedRefCount == null) {
- serializer.writeObject(obj, data, type, this, debugIndent)
+ serializer.writeObject(obj, data, type, this, context, debugIndent)
// Important to do it after serialization such that dependent object will have preceding reference numbers
// assigned to them first as they will be first read from the stream on receiving end.
// Skip for primitive types as they are too small and overhead of referencing them will be much higher than their content
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt
index 53ebafe871..6d3c8f10f6 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt
@@ -15,9 +15,11 @@ import com.google.common.reflect.TypeResolver
import net.corda.core.internal.getStackTraceAsString
import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.ClassWhitelist
-import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.loggerFor
-import net.corda.nodeapi.internal.serialization.carpenter.*
+import net.corda.nodeapi.internal.serialization.carpenter.CarpenterMetaSchema
+import net.corda.nodeapi.internal.serialization.carpenter.ClassCarpenter
+import net.corda.nodeapi.internal.serialization.carpenter.MetaCarpenter
+import net.corda.nodeapi.internal.serialization.carpenter.MetaCarpenterException
import org.apache.qpid.proton.amqp.*
import java.io.NotSerializableException
import java.lang.reflect.*
@@ -69,8 +71,7 @@ open class SerializerFactory(
get() = classCarpenter.classloader
private fun getEvolutionSerializer(typeNotation: TypeNotation, newSerializer: AMQPSerializer,
- schemas: SerializationSchemas)
- = evolutionSerializerGetter.getEvolutionSerializer(this, typeNotation, newSerializer, schemas)
+ schemas: SerializationSchemas) = evolutionSerializerGetter.getEvolutionSerializer(this, typeNotation, newSerializer, schemas)
fun getSerializersByDescriptor() = serializersByDescriptor
@@ -109,7 +110,8 @@ open class SerializerFactory(
makeMapSerializer(declaredTypeAmended)
}
}
- Enum::class.java.isAssignableFrom(actualClass ?: declaredClass) -> serializersByType.computeIfAbsent(actualClass ?: declaredClass) {
+ Enum::class.java.isAssignableFrom(actualClass
+ ?: declaredClass) -> serializersByType.computeIfAbsent(actualClass ?: declaredClass) {
whitelist.requireWhitelisted(actualType)
EnumSerializer(actualType, actualClass ?: declaredClass, this)
}
@@ -254,8 +256,8 @@ open class SerializerFactory(
} catch (e: MetaCarpenterException) {
// preserve the actual message locally
loggerFor().apply {
- error ("${e.message} [hint: enable trace debugging for the stack trace]")
- trace (e.getStackTraceAsString())
+ error("${e.message} [hint: enable trace debugging for the stack trace]")
+ trace(e.getStackTraceAsString())
}
// prevent carpenter exceptions escaping into the world, convert things into a nice
@@ -293,12 +295,12 @@ open class SerializerFactory(
} else {
val singleton = clazz.objectInstance()
if (singleton != null) {
- whitelist.requireWhitelisted(clazz)
- SingletonSerializer(clazz, singleton, this)
- } else {
- whitelist.requireWhitelisted(type)
- ObjectSerializer(type, this)
- }
+ whitelist.requireWhitelisted(clazz)
+ SingletonSerializer(clazz, singleton, this)
+ } else {
+ whitelist.requireWhitelisted(type)
+ ObjectSerializer(type, this)
+ }
}
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SingletonSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SingletonSerializer.kt
index 3dbbc5456f..91f068ef43 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SingletonSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SingletonSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp
+import net.corda.core.serialization.SerializationContext
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type
@@ -33,13 +34,16 @@ class SingletonSerializer(override val type: Class<*>, val singleton: Any, facto
output.writeTypeNotations(typeNotation)
}
- override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
+ override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext, debugIndent: Int
+ ) {
data.withDescribed(typeNotation.descriptor) {
data.putBoolean(false)
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext
+ ): Any {
return singleton
}
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt
index 8b71bce9ba..4b2a33886e 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt
@@ -224,8 +224,8 @@ data class TransformsSchema(val types: Map ?:
- throw NotSerializableException("Transform schema must be encoded as a map")
+ val map = describedType.described as? Map<*, *>
+ ?: throw NotSerializableException("Transform schema must be encoded as a map")
map.forEach { type ->
- val fingerprint = type.key as? String ?:
- throw NotSerializableException("Fingerprint must be encoded as a string")
+ val fingerprint = type.key as? String
+ ?: throw NotSerializableException("Fingerprint must be encoded as a string")
rtn[fingerprint] = EnumMap>(TransformTypes::class.java)
@@ -298,8 +298,8 @@ data class TransformsSchema(val types: Map).forEach {
- rtn[fingerprint]!![TransformTypes.newInstance(transformType)]?.add(Transform.newInstance(it)) ?:
- throw NotSerializableException("De-serialization error with transform for class "
+ rtn[fingerprint]!![TransformTypes.newInstance(transformType)]?.add(Transform.newInstance(it))
+ ?: throw NotSerializableException("De-serialization error with transform for class "
+ "${type.key} ${transform.name}")
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ClassSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ClassSerializer.kt
index d844af4d9c..378b3580c9 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ClassSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ClassSerializer.kt
@@ -12,6 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
+import net.corda.nodeapi.internal.serialization.amqp.custom.ClassSerializer.ClassProxy
/**
* A serializer for [Class] that uses [ClassProxy] proxy object to write out
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/InputStreamSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/InputStreamSerializer.kt
index e9d96784c8..7a12a2fac1 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/InputStreamSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/InputStreamSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp.custom
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.serialization.amqp.*
import org.apache.qpid.proton.amqp.Binary
import org.apache.qpid.proton.codec.Data
@@ -25,7 +26,9 @@ object InputStreamSerializer : CustomSerializer.Implements(InputStr
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
- override fun writeDescribedObject(obj: InputStream, data: Data, type: Type, output: SerializationOutput) {
+ override fun writeDescribedObject(obj: InputStream, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
val startingSize = maxOf(4096, obj.available() + 1)
var buffer = ByteArray(startingSize)
var pos = 0
@@ -44,8 +47,10 @@ object InputStreamSerializer : CustomSerializer.Implements(InputStr
}
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): InputStream {
- val bits = input.readObject(obj, schemas, ByteArray::class.java) as ByteArray
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): InputStream {
+ val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
return bits.inputStream()
}
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/MonthDaySerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/MonthDaySerializer.kt
index 24094b54e2..d9fa3ce32c 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/MonthDaySerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/MonthDaySerializer.kt
@@ -12,12 +12,15 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.MonthDay
/**
* A serializer for [MonthDay] that uses a proxy object to write out the integer form.
*/
-class MonthDaySerializer(factory: SerializerFactory) : CustomSerializer.Proxy(MonthDay::class.java, MonthDayProxy::class.java, factory) {
+class MonthDaySerializer(factory: SerializerFactory)
+ : CustomSerializer.Proxy(
+ MonthDay::class.java, MonthDayProxy::class.java, factory
+) {
override fun toProxy(obj: MonthDay): MonthDayProxy = MonthDayProxy(obj.monthValue.toByte(), obj.dayOfMonth.toByte())
override fun fromProxy(proxy: MonthDayProxy): MonthDay = MonthDay.of(proxy.month.toInt(), proxy.day.toInt())
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetDateTimeSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetDateTimeSerializer.kt
index 6b1217c9f0..a8ba4ec5fb 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetDateTimeSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetDateTimeSerializer.kt
@@ -12,7 +12,9 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.LocalDateTime
+import java.time.OffsetDateTime
+import java.time.ZoneOffset
/**
* A serializer for [OffsetDateTime] that uses a proxy object to write out the date and zone offset.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetTimeSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetTimeSerializer.kt
index 7945b3f9e1..7fad041c1e 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetTimeSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/OffsetTimeSerializer.kt
@@ -12,7 +12,9 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.LocalTime
+import java.time.OffsetTime
+import java.time.ZoneOffset
/**
* A serializer for [OffsetTime] that uses a proxy object to write out the time and zone offset.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PeriodSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PeriodSerializer.kt
index 50478ea8e2..d67db18099 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PeriodSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PeriodSerializer.kt
@@ -12,7 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.Period
/**
* A serializer for [Period] that uses a proxy object to write out the integer form.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PrivateKeySerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PrivateKeySerializer.kt
index 50469d9cd0..9cba34b0b8 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PrivateKeySerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PrivateKeySerializer.kt
@@ -11,7 +11,9 @@
package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.crypto.Crypto
-import net.corda.core.serialization.SerializationContext.UseCase.*
+import net.corda.core.serialization.SerializationContext
+import net.corda.core.serialization.SerializationContext.UseCase.Checkpoint
+import net.corda.core.serialization.SerializationContext.UseCase.Storage
import net.corda.nodeapi.internal.serialization.amqp.*
import net.corda.nodeapi.internal.serialization.checkUseCase
import org.apache.qpid.proton.codec.Data
@@ -25,13 +27,17 @@ object PrivateKeySerializer : CustomSerializer.Implements(PrivateKey
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
- override fun writeDescribedObject(obj: PrivateKey, data: Data, type: Type, output: SerializationOutput) {
+ override fun writeDescribedObject(obj: PrivateKey, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
checkUseCase(allowedUseCases)
- output.writeObject(obj.encoded, data, clazz)
+ output.writeObject(obj.encoded, data, clazz, context)
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): PrivateKey {
- val bits = input.readObject(obj, schemas, ByteArray::class.java) as ByteArray
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): PrivateKey {
+ val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
return Crypto.decodePrivateKey(bits)
}
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PublicKeySerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PublicKeySerializer.kt
index 99b91eaf71..3339f2de17 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PublicKeySerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/PublicKeySerializer.kt
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.crypto.Crypto
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.serialization.amqp.*
import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type
@@ -22,13 +23,17 @@ import java.security.PublicKey
object PublicKeySerializer : CustomSerializer.Implements(PublicKey::class.java) {
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
- override fun writeDescribedObject(obj: PublicKey, data: Data, type: Type, output: SerializationOutput) {
+ override fun writeDescribedObject(obj: PublicKey, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
// TODO: Instead of encoding to the default X509 format, we could have a custom per key type (space-efficient) serialiser.
- output.writeObject(obj.encoded, data, clazz)
+ output.writeObject(obj.encoded, data, clazz, context)
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): PublicKey {
- val bits = input.readObject(obj, schemas, ByteArray::class.java) as ByteArray
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): PublicKey {
+ val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
return Crypto.decodePublicKey(bits)
}
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CRLSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CRLSerializer.kt
index 2b7f026d14..1c95dad698 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CRLSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CRLSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp.custom
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.serialization.amqp.*
import org.apache.qpid.proton.codec.Data
@@ -26,12 +27,16 @@ object X509CRLSerializer : CustomSerializer.Implements(X509CRL::class.j
emptyList()
)))
- override fun writeDescribedObject(obj: X509CRL, data: Data, type: Type, output: SerializationOutput) {
- output.writeObject(obj.encoded, data, clazz)
+ override fun writeDescribedObject(obj: X509CRL, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
+ output.writeObject(obj.encoded, data, clazz, context)
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): X509CRL {
- val bytes = input.readObject(obj, schemas, ByteArray::class.java) as ByteArray
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): X509CRL {
+ val bytes = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
return X509CertificateFactory().delegate.generateCRL(bytes.inputStream()) as X509CRL
}
}
\ No newline at end of file
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt
index 1ef4549915..782aa7c19f 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp.custom
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.serialization.amqp.*
import org.apache.qpid.proton.codec.Data
@@ -26,12 +27,16 @@ object X509CertificateSerializer : CustomSerializer.Implements(
emptyList()
)))
- override fun writeDescribedObject(obj: X509Certificate, data: Data, type: Type, output: SerializationOutput) {
- output.writeObject(obj.encoded, data, clazz)
+ override fun writeDescribedObject(obj: X509Certificate, data: Data, type: Type, output: SerializationOutput,
+ context: SerializationContext
+ ) {
+ output.writeObject(obj.encoded, data, clazz, context)
}
- override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): X509Certificate {
- val bits = input.readObject(obj, schemas, ByteArray::class.java) as ByteArray
+ override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
+ context: SerializationContext
+ ): X509Certificate {
+ val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
return X509CertificateFactory().generateCertificate(bits.inputStream())
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearMonthSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearMonthSerializer.kt
index a849819897..c4b9758a5e 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearMonthSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearMonthSerializer.kt
@@ -12,7 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.YearMonth
/**
* A serializer for [YearMonth] that uses a proxy object to write out the integer form.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearSerializer.kt
index f5bff3f10d..631432e65a 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/YearSerializer.kt
@@ -12,7 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.Year
/**
* A serializer for [Year] that uses a proxy object to write out the integer form.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ZonedDateTimeSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ZonedDateTimeSerializer.kt
index fa09cfa381..aaed150908 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ZonedDateTimeSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ZonedDateTimeSerializer.kt
@@ -12,7 +12,10 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
-import java.time.*
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.time.ZoneOffset
+import java.time.ZonedDateTime
/**
* A serializer for [ZonedDateTime] that uses a proxy object to write out the date, time, offset and zone.
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/AMQPSchemaExtensions.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/AMQPSchemaExtensions.kt
index f93ce58ff4..042784b0af 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/AMQPSchemaExtensions.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/AMQPSchemaExtensions.kt
@@ -12,11 +12,11 @@
package net.corda.nodeapi.internal.serialization.carpenter
+import net.corda.core.serialization.SerializationContext
import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.nodeapi.internal.serialization.amqp.RestrictedType
import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField
import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema
-import net.corda.core.serialization.SerializationContext
fun AMQPSchema.carpenterSchema(classloader: ClassLoader): CarpenterMetaSchema {
val rtn = CarpenterMetaSchema.newInstance()
@@ -130,7 +130,7 @@ val typeStrToType: Map, Class> = mapOf(
Pair("byte", false) to Byte::class.javaObjectType
)
-fun String.stripGenerics() : String = if(this.endsWith('>')) {
+fun String.stripGenerics(): String = if (this.endsWith('>')) {
this.substring(0, this.indexOf('<'))
} else this
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenter.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenter.kt
index 45efb11d5c..298cd5e1e4 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenter.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenter.kt
@@ -36,11 +36,11 @@ class CarpenterClassLoader(parentClassLoader: ClassLoader = Thread.currentThread
fun load(name: String, bytes: ByteArray) = defineClass(name, bytes, 0, bytes.size)
}
-class InterfaceMismatchNonGetterException (val clazz: Class<*>, val method: Method) : InterfaceMismatchException(
- "Requested interfaces must consist only of methods that start with 'get': ${clazz.name}.${method.name}")
+class InterfaceMismatchNonGetterException(val clazz: Class<*>, val method: Method) : InterfaceMismatchException(
+ "Requested interfaces must consist only of methods that start with 'get': ${clazz.name}.${method.name}")
-class InterfaceMismatchMissingAMQPFieldException (val clazz: Class<*>, val field: String) : InterfaceMismatchException(
- "Interface ${clazz.name} requires a field named $field but that isn't found in the schema or any superclass schemas")
+class InterfaceMismatchMissingAMQPFieldException(val clazz: Class<*>, val field: String) : InterfaceMismatchException(
+ "Interface ${clazz.name} requires a field named $field but that isn't found in the schema or any superclass schemas")
/**
* Which version of the java runtime are we constructing objects against
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/Exceptions.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/Exceptions.kt
index 460f73197f..d64dc3017f 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/Exceptions.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/carpenter/Exceptions.kt
@@ -19,18 +19,18 @@ import org.objectweb.asm.Type
abstract class ClassCarpenterException(msg: String) : CordaRuntimeException(msg)
/**
- * Thrown by the [ClassCarpenter] when trying to build
+ * Thrown by the [ClassCarpenter] when trying to build
*/
abstract class InterfaceMismatchException(msg: String) : ClassCarpenterException(msg)
-class DuplicateNameException(val name : String) : ClassCarpenterException (
+class DuplicateNameException(val name: String) : ClassCarpenterException(
"An attempt was made to register two classes with the name '$name' within the same ClassCarpenter namespace.")
class NullablePrimitiveException(val name: String, val field: Class) : ClassCarpenterException(
"Field $name is primitive type ${Type.getDescriptor(field)} and thus cannot be nullable")
class UncarpentableException(name: String, field: String, type: String) :
- ClassCarpenterException("Class $name is loadable yet contains field $field of unknown type $type")
+ ClassCarpenterException("Class $name is loadable yet contains field $field of unknown type $type")
/**
* A meta exception used by the [MetaCarpenter] to wrap any exceptions generated during the build
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt
index 37905fcd15..3695c3bdca 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt
@@ -268,7 +268,7 @@ object NotaryChangeWireTransactionSerializer : Serializer): NotaryChangeWireTransaction {
- val components : List = uncheckedCast(kryo.readClassAndObject(input))
+ val components: List = uncheckedCast(kryo.readClassAndObject(input))
return NotaryChangeWireTransaction(components)
}
}
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoSerializationScheme.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoSerializationScheme.kt
index fa9606b8ee..24c612bb1d 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoSerializationScheme.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoSerializationScheme.kt
@@ -10,7 +10,6 @@
package net.corda.nodeapi.internal.serialization.kryo
-import java.util.concurrent.ConcurrentHashMap
import co.paralleluniverse.fibers.Fiber
import co.paralleluniverse.io.serialization.kryo.KryoSerializer
import com.esotericsoftware.kryo.Kryo
@@ -22,14 +21,14 @@ import com.esotericsoftware.kryo.io.Output
import com.esotericsoftware.kryo.pool.KryoPool
import com.esotericsoftware.kryo.serializers.ClosureSerializer
import net.corda.core.internal.uncheckedCast
+import net.corda.core.serialization.ClassWhitelist
+import net.corda.core.serialization.SerializationContext
+import net.corda.core.serialization.SerializedBytes
import net.corda.core.utilities.ByteSequence
-import net.corda.core.serialization.*
-import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
-import net.corda.nodeapi.internal.serialization.CordaClassResolver
-import net.corda.nodeapi.internal.serialization.SectionId
-import net.corda.nodeapi.internal.serialization.SerializationScheme
import net.corda.nodeapi.internal.serialization.*
+import net.corda.nodeapi.internal.serialization.SectionId
import java.security.PublicKey
+import java.util.concurrent.ConcurrentHashMap
val kryoMagic = CordaSerializationMagic("corda".toByteArray() + byteArrayOf(0, 0))
@@ -96,7 +95,8 @@ abstract class AbstractKryoSerializationScheme : SerializationScheme {
}
override fun deserialize(byteSequence: ByteSequence, clazz: Class, context: SerializationContext): T {
- val dataBytes = kryoMagic.consume(byteSequence) ?: throw KryoException("Serialized bytes header does not match expected format.")
+ val dataBytes = kryoMagic.consume(byteSequence)
+ ?: throw KryoException("Serialized bytes header does not match expected format.")
return context.kryo {
kryoInput(ByteBufferInputStream(dataBytes)) {
val result: T
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoStreams.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoStreams.kt
index c638fff0f3..27b96c6b13 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoStreams.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoStreams.kt
@@ -13,7 +13,10 @@ package net.corda.nodeapi.internal.serialization.kryo
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import net.corda.core.internal.LazyPool
-import java.io.*
+import java.io.ByteArrayOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import java.io.SequenceInputStream
import java.nio.ByteBuffer
class ByteBufferOutputStream(size: Int) : ByteArrayOutputStream(size) {
diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/SerializeAsTokenSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/SerializeAsTokenSerializer.kt
index ea4b9f7e5c..23c0c79971 100644
--- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/SerializeAsTokenSerializer.kt
+++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/SerializeAsTokenSerializer.kt
@@ -24,12 +24,16 @@ import net.corda.core.serialization.SerializeAsToken
*/
class SerializeAsTokenSerializer : Serializer() {
override fun write(kryo: Kryo, output: Output, obj: T) {
- kryo.writeClassAndObject(output, obj.toToken(kryo.serializationContext() ?: throw KryoException("Attempt to write a ${SerializeAsToken::class.simpleName} instance of ${obj.javaClass.name} without initialising a context")))
+ kryo.writeClassAndObject(output, obj.toToken(kryo.serializationContext()
+ ?: throw KryoException("Attempt to write a ${SerializeAsToken::class.simpleName} instance of ${obj.javaClass.name} without initialising a context")))
}
override fun read(kryo: Kryo, input: Input, type: Class): T {
- val token = (kryo.readClassAndObject(input) as? SerializationToken) ?: throw KryoException("Non-token read for tokenized type: ${type.name}")
- val fromToken = token.fromToken(kryo.serializationContext() ?: throw KryoException("Attempt to read a token for a ${SerializeAsToken::class.simpleName} instance of ${type.name} without initialising a context"))
- return type.castIfPossible(fromToken) ?: throw KryoException("Token read ($token) did not return expected tokenized type: ${type.name}")
+ val token = (kryo.readClassAndObject(input) as? SerializationToken)
+ ?: throw KryoException("Non-token read for tokenized type: ${type.name}")
+ val fromToken = token.fromToken(kryo.serializationContext()
+ ?: throw KryoException("Attempt to read a token for a ${SerializeAsToken::class.simpleName} instance of ${type.name} without initialising a context"))
+ return type.castIfPossible(fromToken)
+ ?: throw KryoException("Token read ($token) did not return expected tokenized type: ${type.name}")
}
}
\ No newline at end of file
diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ErrorMessageTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ErrorMessageTests.java
index 035b5f8b24..c7932721ee 100644
--- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ErrorMessageTests.java
+++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ErrorMessageTests.java
@@ -11,6 +11,8 @@
package net.corda.nodeapi.internal.serialization.amqp;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContextKt;
import org.assertj.core.api.Assertions;
import org.junit.Ignore;
import org.junit.Test;
@@ -51,7 +53,7 @@ public class ErrorMessageTests {
SerializationOutput ser = new SerializationOutput(factory1);
- Assertions.assertThatThrownBy(() -> ser.serialize(new C(1)))
+ Assertions.assertThatThrownBy(() -> ser.serialize(new C(1), TestSerializationContext.testSerializationContext))
.isInstanceOf(NotSerializableException.class)
.hasMessage(errMsg("a", getClass().getName()));
}
diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaGenericsTest.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaGenericsTest.java
index f957ae3147..1bdaabdd78 100644
--- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaGenericsTest.java
+++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaGenericsTest.java
@@ -12,6 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp;
import net.corda.core.serialization.SerializedBytes;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
import org.junit.Test;
import java.io.NotSerializableException;
@@ -43,10 +44,10 @@ public class JavaGenericsTest {
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory);
- SerializedBytes> bytes = ser.serialize(a1);
+ SerializedBytes> bytes = ser.serialize(a1, TestSerializationContext.testSerializationContext);
DeserializationInput des = new DeserializationInput(factory);
- A a2 = des.deserialize(bytes, A.class);
+ A a2 = des.deserialize(bytes, A.class, TestSerializationContext.testSerializationContext);
assertEquals(1, a2.getT());
}
@@ -58,13 +59,13 @@ public class JavaGenericsTest {
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
- return (new SerializationOutput(factory)).serialize(a);
+ return (new SerializationOutput(factory)).serialize(a, TestSerializationContext.testSerializationContext);
}
private SerializedBytes> forceWildcardSerializeFactory(
A> a,
SerializerFactory factory) throws NotSerializableException {
- return (new SerializationOutput(factory)).serialize(a);
+ return (new SerializationOutput(factory)).serialize(a, TestSerializationContext.testSerializationContext);
}
private A> forceWildcardDeserialize(SerializedBytes> bytes) throws NotSerializableException {
@@ -75,13 +76,14 @@ public class JavaGenericsTest {
new SerializerFingerPrinter());
DeserializationInput des = new DeserializationInput(factory);
- return des.deserialize(bytes, A.class);
+ return des.deserialize(bytes, A.class, TestSerializationContext.testSerializationContext);
}
private A> forceWildcardDeserializeFactory(
SerializedBytes> bytes,
SerializerFactory factory) throws NotSerializableException {
- return (new DeserializationInput(factory)).deserialize(bytes, A.class);
+ return (new DeserializationInput(factory)).deserialize(bytes, A.class,
+ TestSerializationContext.testSerializationContext);
}
@Test
diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedClassesTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedClassesTests.java
index 66cd995220..80621a0a99 100644
--- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedClassesTests.java
+++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedClassesTests.java
@@ -6,6 +6,7 @@ import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
import net.corda.core.serialization.SerializedBytes;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
import org.assertj.core.api.Assertions;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
@@ -39,17 +40,17 @@ class OuterClass1 {
}
public void run() throws NotSerializableException {
- SerializedBytes b = ser.serialize(new DummyState());
- desExisting.deserialize(b, DummyState.class);
- desRegen.deserialize(b, DummyState.class);
+ SerializedBytes b = ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext);
+ desExisting.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
+ desRegen.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
}
}
class Inherator1 extends OuterClass1 {
public void iRun() throws NotSerializableException {
- SerializedBytes b = ser.serialize(new DummyState());
- desExisting.deserialize(b, DummyState.class);
- desRegen.deserialize(b, DummyState.class);
+ SerializedBytes b = ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext);
+ desExisting.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
+ desRegen.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
}
}
@@ -85,17 +86,17 @@ class OuterClass2 {
}
public void run() throws NotSerializableException {
- SerializedBytes b = ser.serialize(new DummyState(12));
- desExisting.deserialize(b, DummyState.class);
- desRegen.deserialize(b, DummyState.class);
+ SerializedBytes b = ser.serialize(new DummyState(12), TestSerializationContext.testSerializationContext);
+ desExisting.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
+ desRegen.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
}
}
class Inherator2 extends OuterClass2 {
public void iRun() throws NotSerializableException {
- SerializedBytes b = ser.serialize(new DummyState(12));
- desExisting.deserialize(b, DummyState.class);
- desRegen.deserialize(b, DummyState.class);
+ SerializedBytes b = ser.serialize(new DummyState(12), TestSerializationContext.testSerializationContext);
+ desExisting.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
+ desRegen.deserialize(b, DummyState.class, TestSerializationContext.testSerializationContext);
}
}
@@ -120,7 +121,7 @@ abstract class AbstractClass2 {
class Inherator4 extends AbstractClass2 {
public void run() throws NotSerializableException {
- ser.serialize(new DummyState());
+ ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext);
}
}
@@ -139,7 +140,7 @@ class Inherator5 extends AbstractClass3 {
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory);
- ser.serialize(new DummyState());
+ ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext);
}
}
@@ -159,7 +160,7 @@ class Inherator6 extends AbstractClass3 {
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory);
- ser.serialize(new Wrapper(new DummyState()));
+ ser.serialize(new Wrapper(new DummyState()), TestSerializationContext.testSerializationContext);
}
}
diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedInheritenceTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedInheritenceTests.java
index 548f3625a3..8097fe9530 100644
--- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedInheritenceTests.java
+++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaNestedInheritenceTests.java
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
import org.assertj.core.api.Assertions;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
@@ -38,7 +39,7 @@ public class JavaNestedInheritenceTests extends JavaNestedInheritenceTestsBase {
SerializationOutput ser = new SerializationOutput(factory);
- Assertions.assertThatThrownBy(() -> ser.serialize(new DummyState())).isInstanceOf(
+ Assertions.assertThatThrownBy(() -> ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class");
}
@@ -50,7 +51,7 @@ public class JavaNestedInheritenceTests extends JavaNestedInheritenceTestsBase {
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory);
- Assertions.assertThatThrownBy(() -> ser.serialize(new Wrapper (new DummyState()))).isInstanceOf(
+ Assertions.assertThatThrownBy(() -> ser.serialize(new Wrapper (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class");
}
@@ -63,7 +64,7 @@ public class JavaNestedInheritenceTests extends JavaNestedInheritenceTestsBase {
SerializationOutput ser = new SerializationOutput(factory1);
- Assertions.assertThatThrownBy(() -> ser.serialize(new TemplateWrapper (new DummyState()))).isInstanceOf(
+ Assertions.assertThatThrownBy(() -> ser.serialize(new TemplateWrapper (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class");
}
diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaPrivatePropertyTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaPrivatePropertyTests.java
index e11227b9ed..fbc86a1f89 100644
--- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaPrivatePropertyTests.java
+++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaPrivatePropertyTests.java
@@ -11,6 +11,7 @@
package net.corda.nodeapi.internal.serialization.amqp;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -93,7 +94,7 @@ public class JavaPrivatePropertyTests {
DeserializationInput des = new DeserializationInput(factory);
B b = new B(true);
- B b2 = des.deserialize(ser.serialize(b), B.class);
+ B b2 = des.deserialize(ser.serialize(b, TestSerializationContext.testSerializationContext), B.class, TestSerializationContext.testSerializationContext);
assertEquals (b.b, b2.b);
}
@@ -108,7 +109,7 @@ public class JavaPrivatePropertyTests {
B2 b = new B2();
b.setB(false);
- B2 b2 = des.deserialize(ser.serialize(b), B2.class);
+ B2 b2 = des.deserialize(ser.serialize(b, TestSerializationContext.testSerializationContext), B2.class, TestSerializationContext.testSerializationContext);
assertEquals (b.b, b2.b);
}
@@ -122,7 +123,7 @@ public class JavaPrivatePropertyTests {
B3 b = new B3();
b.setB(false);
- B3 b2 = des.deserialize(ser.serialize(b), B3.class);
+ B3 b2 = des.deserialize(ser.serialize(b, TestSerializationContext.testSerializationContext), B3.class, TestSerializationContext.testSerializationContext);
// since we can't find a getter for b (isb != isB) then we won't serialize that parameter
assertEquals (null, b2.b);
@@ -138,7 +139,7 @@ public class JavaPrivatePropertyTests {
C3 c = new C3();
c.setA(12345);
- C3 c2 = des.deserialize(ser.serialize(c), C3.class);
+ C3 c2 = des.deserialize(ser.serialize(c, TestSerializationContext.testSerializationContext), C3.class, TestSerializationContext.testSerializationContext);
assertEquals (c.a, c2.a);
}
@@ -153,7 +154,7 @@ public class JavaPrivatePropertyTests {
DeserializationInput des = new DeserializationInput(factory);
C c = new C("dripping taps");
- C c2 = des.deserialize(ser.serialize(c), C.class);
+ C c2 = des.deserialize(ser.serialize(c, TestSerializationContext.testSerializationContext), C.class, TestSerializationContext.testSerializationContext);
assertEquals (c.a, c2.a);
@@ -185,7 +186,7 @@ public class JavaPrivatePropertyTests {
DeserializationInput des = new DeserializationInput(factory);
C2 c = new C2("dripping taps");
- C2 c2 = des.deserialize(ser.serialize(c), C2.class);
+ C2 c2 = des.deserialize(ser.serialize(c, TestSerializationContext.testSerializationContext), C2.class, TestSerializationContext.testSerializationContext);
assertEquals (c.a, c2.a);
diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerialiseEnumTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerialiseEnumTests.java
index bdc59a8eb0..a263406d81 100644
--- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerialiseEnumTests.java
+++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerialiseEnumTests.java
@@ -10,6 +10,7 @@
package net.corda.nodeapi.internal.serialization.amqp;
+import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
import org.junit.Test;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
@@ -43,6 +44,6 @@ public class JavaSerialiseEnumTests {
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory1);
- SerializedBytes