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 721a78ec6f..418226cea0 100644 --- a/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt +++ b/core/src/test/kotlin/net/corda/core/contracts/TransactionVerificationExceptionSerialisationTests.kt @@ -2,6 +2,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 @@ -19,13 +20,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) @@ -42,7 +47,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) @@ -52,7 +59,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) @@ -62,7 +71,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) @@ -73,7 +84,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) @@ -84,7 +97,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) @@ -99,7 +114,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/changelog.rst b/docs/source/changelog.rst index 3f7a0481bb..5d0f410e30 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/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt index d8451df92d..26313b1d3c 100644 --- a/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt +++ b/experimental/blobinspector/src/test/kotlin/net/corda/blobinspector/InMemoryTests.kt @@ -4,6 +4,7 @@ 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 @@ -21,13 +22,13 @@ class InMemoryTests { @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"))) + 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)))))) + inspect (SerializationOutput(factory).serialize(C(1, C(2, C(3, C(4, null)))), AMQP_P2P_CONTEXT)) } @Test @@ -37,7 +38,7 @@ class InMemoryTests { val a = IntArray(10) { i -> i } val c = C(a, arrayOf("aaa", "bbb", "ccc")) - inspect (SerializationOutput(factory).serialize(c)) + inspect (SerializationOutput(factory).serialize(c, AMQP_P2P_CONTEXT)) } @Test @@ -51,7 +52,7 @@ class InMemoryTests { Elem(1L, "First element"), Elem(2L, "Second element"), Elem(3L, "Third element") - )))) + )), AMQP_P2P_CONTEXT)) } @Test @@ -72,7 +73,7 @@ class InMemoryTests { Elem(5L, "Fifth element"), Elem(6L, "Sixth element") ) - )))) + )), AMQP_P2P_CONTEXT)) } @Test @@ -83,7 +84,8 @@ class InMemoryTests { C(mapOf( "a" to "a a a", "b" to "b b b", - "c" to "c c c")) + "c" to "c c c")), + AMQP_P2P_CONTEXT )) } } \ No newline at end of file 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 1ea1040557..2b7f767c5d 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 @@ -351,7 +351,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 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 c6458e53a4..fe94544a35 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 @@ -80,10 +80,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)!!) @@ -162,7 +162,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 101936ba82..e98cded106 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 @@ -66,5 +66,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 fefdfb930f..84d6aef83b 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 @@ -7,8 +7,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 fa67d13c09..d99227f800 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 @@ -39,13 +39,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) @@ -143,8 +145,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 6877239bd5..8451ac62b2 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 @@ -52,5 +52,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 7f1d8c17b4..6a828e8cc0 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 @@ -5,7 +5,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 3907a86fe8..0f6683202b 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 @@ -10,7 +10,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 27db491d33..f3ddd3947f 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 @@ -1,5 +1,6 @@ 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 @@ -18,7 +19,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 { @@ -29,5 +37,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 141f9af528..ed1ab9c4ed 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 @@ -6,8 +6,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 @@ -31,12 +31,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 @@ -52,7 +52,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() @@ -64,7 +64,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) @@ -121,8 +121,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)) { @@ -135,19 +134,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 9dfcd03cb7..e06412e4bb 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 @@ -1,5 +1,6 @@ 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 @@ -30,10 +31,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 872709a119..e16872809e 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 @@ -1,5 +1,6 @@ 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 @@ -32,7 +33,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) } @@ -46,20 +48,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") } @@ -108,20 +114,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) + } } } @@ -135,47 +145,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 5a6ab42f8e..9c41c37fe3 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 @@ -1,6 +1,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 @@ -8,15 +9,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)}") } @@ -50,7 +50,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> = @@ -73,12 +74,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) } } } @@ -87,8 +89,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 161c18d4cc..bb40f19454 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 @@ -1,6 +1,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 @@ -64,22 +65,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 fd02997c49..631cfc1bf6 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 @@ -1,6 +1,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 @@ -40,13 +41,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 @@ -77,12 +81,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) } } @@ -124,7 +132,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) } @@ -138,17 +151,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) } } @@ -176,11 +193,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 fdfaf01d81..71c303439b 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 @@ -4,6 +4,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 @@ -62,7 +63,8 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto @Throws(NotSerializableException::class) 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) { @@ -96,11 +98,9 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto fun getEnvelope(byteSequence: ByteSequence) = Companion.getEnvelope(byteSequence, encodingWhitelist) @Throws(NotSerializableException::class) - inline fun deserialize(bytes: SerializedBytes): T = deserialize(bytes, T::class.java) + inline fun deserialize(bytes: SerializedBytes, context: SerializationContext): T = + deserialize(bytes, T::class.java, context) - @Throws(NotSerializableException::class) - inline internal fun deserializeAndReturnEnvelope(bytes: SerializedBytes): ObjectAndEnvelope = - deserializeAndReturnEnvelope(bytes, T::class.java) @Throws(NotSerializableException::class) private fun des(generator: () -> R): R { @@ -121,23 +121,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, encodingWhitelist) - 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 { + 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() @@ -158,19 +172,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 a6d9ebb055..ee49ae6e69 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 @@ -1,6 +1,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 @@ -65,7 +66,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 @@ -117,7 +119,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) { @@ -131,7 +135,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 c3d9fdd732..8cc39e6079 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 @@ -1,5 +1,6 @@ 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 @@ -28,7 +29,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<*>? @@ -40,7 +43,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/EvolutionSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt index b2dfa16f53..a83e4744cf 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 @@ -1,10 +1,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 @@ -39,12 +40,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 { @@ -96,7 +98,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( @@ -108,7 +110,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) } /** @@ -143,14 +145,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") } } @@ -160,7 +163,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 @@ -170,15 +173,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.") } } @@ -191,18 +195,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 31def96b4f..d71aec7085 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 @@ -1,6 +1,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 @@ -8,9 +9,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<*, *> @@ -18,8 +16,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)}") @@ -57,7 +55,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> = @@ -80,6 +79,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 @@ -88,22 +88,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 2403d825c8..f9158b74c7 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 @@ -1,5 +1,6 @@ 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 @@ -57,6 +58,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 && @@ -72,7 +74,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) } } } @@ -81,16 +83,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") @@ -100,12 +103,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 }) } @@ -113,7 +117,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( @@ -123,7 +128,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 f9fa3d8f83..f97955a8ca 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 @@ -1,5 +1,6 @@ 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 @@ -9,8 +10,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() @@ -76,12 +77,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})" @@ -96,11 +100,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)) @@ -112,18 +120,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 4687c1173b..03f99f35e7 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 @@ -2,12 +2,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? @@ -141,6 +141,7 @@ class PropertyAccessorGetterSetter( */ setter.isAccessible = true } + /** * Invokes the setter on the underlying object passing in the serialized value. */ @@ -162,7 +163,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.") } } @@ -187,7 +188,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") } } } @@ -196,7 +197,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 e589716672..fe4af5d4bf 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 @@ -95,7 +95,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 { @@ -163,8 +163,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() } @@ -245,9 +244,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 @@ -267,8 +266,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") @@ -315,7 +314,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 1dcf750ef5..3290c063ba 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 @@ -1,5 +1,6 @@ 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 @@ -23,7 +24,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() @@ -34,19 +38,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 { @@ -60,11 +63,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) @@ -87,8 +90,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) { @@ -99,15 +102,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) @@ -116,7 +119,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 b0f3d4746b..abf8034115 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 @@ -5,9 +5,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.* @@ -59,8 +61,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 @@ -99,7 +100,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) } @@ -244,8 +246,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 @@ -283,12 +285,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 b54bb94393..e4d5869f06 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 @@ -1,5 +1,6 @@ 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 @@ -23,13 +24,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 50c38be9f5..829aac7b58 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 @@ -214,8 +214,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) @@ -288,8 +288,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 7c399d5a68..99dd1b9ff6 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 @@ -2,6 +2,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 ff2439bab9..faa4f5eebf 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 @@ -1,5 +1,6 @@ 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 @@ -15,7 +16,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 @@ -34,8 +37,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 e658ccf9a6..ba267f468c 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 @@ -2,12 +2,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 6000cb68cc..e0faf66299 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 @@ -2,7 +2,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 ec5d25e9a1..7f155c090b 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 @@ -2,7 +2,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 c850489d0c..3eca9063c6 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 @@ -2,7 +2,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 9609c926fe..e1310745bc 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 @@ -1,7 +1,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 @@ -15,13 +17,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 13faad17a6..3a9ac67fef 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 @@ -1,6 +1,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 @@ -12,13 +13,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 2f98bddb74..c0cf66a631 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 @@ -1,5 +1,6 @@ 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 @@ -16,12 +17,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 dbbd6c6598..353f3acacf 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 @@ -1,5 +1,6 @@ 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 @@ -16,12 +17,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 1b97e1d131..8bb5458e82 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 @@ -2,7 +2,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 f96c5ed7e9..2d2948c172 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 @@ -2,7 +2,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 9e851ac208..a411f8a955 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 @@ -2,7 +2,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 c400f94ff0..4dacba4f48 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 @@ -2,11 +2,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() @@ -120,7 +120,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 070116c2d4..6dc7453a1a 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 @@ -26,11 +26,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 c7c2830c62..20710e12c5 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 @@ -9,18 +9,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 86316cc006..7a5111fd93 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 @@ -254,7 +254,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 7e1b94fffd..874219e1ec 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 @@ -1,6 +1,5 @@ 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 @@ -12,14 +11,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)) @@ -86,7 +85,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 1d26ba2703..d88d943a79 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 @@ -3,7 +3,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 eebe87a099..142e9fe35e 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 @@ -14,12 +14,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 11db9fc643..24d393b336 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 @@ -1,6 +1,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; @@ -41,7 +43,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 9c206ad8cd..b595195f01 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 @@ -2,6 +2,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; @@ -33,10 +34,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()); } @@ -48,13 +49,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 { @@ -65,13 +66,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 2ee89945f6..75e6d44ea7 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 @@ -1,6 +1,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.*; @@ -83,7 +84,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); } @@ -98,7 +99,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); } @@ -112,7 +113,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); @@ -128,7 +129,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); } @@ -143,7 +144,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); @@ -175,7 +176,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 9be95ca396..e55fe7caed 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 @@ -1,5 +1,6 @@ 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; @@ -33,6 +34,6 @@ public class JavaSerialiseEnumTests { new EvolutionSerializerGetter(), new SerializerFingerPrinter()); SerializationOutput ser = new SerializationOutput(factory1); - SerializedBytes bytes = ser.serialize(bra); + SerializedBytes bytes = ser.serialize(bra, TestSerializationContext.testSerializationContext); } } diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java index e62775218b..f32254110c 100644 --- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java +++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaSerializationOutputTests.java @@ -6,6 +6,7 @@ import net.corda.core.identity.AbstractParty; import net.corda.core.serialization.ConstructorForDeserialization; import net.corda.nodeapi.internal.serialization.AllWhitelist; import net.corda.core.serialization.SerializedBytes; +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext; import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.EncoderImpl; import org.jetbrains.annotations.NotNull; @@ -189,7 +190,7 @@ public class JavaSerializationOutputTests { evolutionSerialiserGetter, fingerPrinter); SerializationOutput ser = new SerializationOutput(factory1); - SerializedBytes bytes = ser.serialize(obj); + SerializedBytes bytes = ser.serialize(obj, TestSerializationContext.testSerializationContext); DecoderImpl decoder = new DecoderImpl(); @@ -209,13 +210,15 @@ public class JavaSerializationOutputTests { assertTrue(result != null); DeserializationInput des = new DeserializationInput(factory2); - Object desObj = des.deserialize(bytes, Object.class); + Object desObj = des.deserialize(bytes, Object.class, TestSerializationContext.testSerializationContext); assertTrue(Objects.deepEquals(obj, desObj)); // Now repeat with a re-used factory SerializationOutput ser2 = new SerializationOutput(factory1); DeserializationInput des2 = new DeserializationInput(factory1); - Object desObj2 = des2.deserialize(ser2.serialize(obj), Object.class); + Object desObj2 = des2.deserialize(ser2.serialize(obj, TestSerializationContext.testSerializationContext), + Object.class, TestSerializationContext.testSerializationContext); + assertTrue(Objects.deepEquals(obj, desObj2)); // TODO: check schema is as expected return desObj2; diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ListsSerializationJavaTest.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ListsSerializationJavaTest.java index 153681fa6a..8397f5a9f8 100644 --- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ListsSerializationJavaTest.java +++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/ListsSerializationJavaTest.java @@ -3,6 +3,7 @@ package net.corda.nodeapi.internal.serialization.amqp; import net.corda.core.serialization.CordaSerializable; 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.Assert; import org.junit.Test; @@ -132,9 +133,9 @@ public class ListsSerializationJavaTest { evolutionSerializerGetter, fingerPrinter); SerializationOutput ser = new SerializationOutput(factory1); - SerializedBytes bytes = ser.serialize(container); + SerializedBytes bytes = ser.serialize(container, TestSerializationContext.testSerializationContext); DeserializationInput des = new DeserializationInput(factory1); - T deserialized = des.deserialize(bytes, clazz); + T deserialized = des.deserialize(bytes, clazz, TestSerializationContext.testSerializationContext); Assert.assertEquals(container, deserialized); } } \ No newline at end of file diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/SetterConstructorTests.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/SetterConstructorTests.java index e9ac48b063..e68e4c9b85 100644 --- a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/SetterConstructorTests.java +++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/SetterConstructorTests.java @@ -2,6 +2,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.assertj.core.api.Assertions; import org.junit.Test; import static org.junit.Assert.*; @@ -132,7 +133,7 @@ public class SetterConstructorTests { c1.setA(1); c1.setB(2); c1.setC(3); - Schema schemas = ser.serializeAndReturnSchema(c1).component2(); + Schema schemas = ser.serializeAndReturnSchema(c1, TestSerializationContext.testSerializationContext).component2(); assertEquals(1, schemas.component1().size()); assertEquals(this.getClass().getName() + "$C", schemas.component1().get(0).getName()); @@ -147,7 +148,7 @@ public class SetterConstructorTests { C2 c2 = new C2(); c2.setA(1); c2.setB(2); - schemas = ser.serializeAndReturnSchema(c2).component2(); + schemas = ser.serializeAndReturnSchema(c2, TestSerializationContext.testSerializationContext).component2(); assertEquals(1, schemas.component1().size()); assertEquals(this.getClass().getName() + "$C2", schemas.component1().get(0).getName()); @@ -164,7 +165,7 @@ public class SetterConstructorTests { c3.setA(1); c3.setB(2); c3.setC(3); - schemas = ser.serializeAndReturnSchema(c3).component2(); + schemas = ser.serializeAndReturnSchema(c3, TestSerializationContext.testSerializationContext).component2(); assertEquals(1, schemas.component1().size()); assertEquals(this.getClass().getName() + "$C3", schemas.component1().get(0).getName()); @@ -180,7 +181,7 @@ public class SetterConstructorTests { c4.setA(1); c4.setB(2); c4.setC(3); - schemas = ser.serializeAndReturnSchema(c4).component2(); + schemas = ser.serializeAndReturnSchema(c4, TestSerializationContext.testSerializationContext).component2(); assertEquals(1, schemas.component1().size()); assertEquals(this.getClass().getName() + "$C4", schemas.component1().get(0).getName()); @@ -212,9 +213,9 @@ public class SetterConstructorTests { cPre1.setB(b); cPre1.setC(c); - SerializedBytes bytes = new SerializationOutput(factory1).serialize(cPre1); + SerializedBytes bytes = new SerializationOutput(factory1).serialize(cPre1, TestSerializationContext.testSerializationContext); - C cPost1 = new DeserializationInput(factory1).deserialize(bytes, C.class); + C cPost1 = new DeserializationInput(factory1).deserialize(bytes, C.class, TestSerializationContext.testSerializationContext); assertEquals(a, cPost1.a); assertEquals(b, cPost1.b); @@ -224,8 +225,8 @@ public class SetterConstructorTests { cPre2.setA(1); cPre2.setB(2); - C2 cPost2 = new DeserializationInput(factory1).deserialize(new SerializationOutput(factory1).serialize(cPre2), - C2.class); + C2 cPost2 = new DeserializationInput(factory1).deserialize(new SerializationOutput(factory1).serialize(cPre2, TestSerializationContext.testSerializationContext), + C2.class, TestSerializationContext.testSerializationContext); assertEquals(a, cPost2.a); assertEquals(b, cPost2.b); @@ -239,8 +240,9 @@ public class SetterConstructorTests { cPre3.setB(2); cPre3.setC(3); - C3 cPost3 = new DeserializationInput(factory1).deserialize(new SerializationOutput(factory1).serialize(cPre3), - C3.class); + C3 cPost3 = new DeserializationInput(factory1).deserialize( + new SerializationOutput(factory1).serialize(cPre3, TestSerializationContext.testSerializationContext), + C3.class, TestSerializationContext.testSerializationContext); assertEquals(a, cPost3.a); @@ -253,8 +255,11 @@ public class SetterConstructorTests { cPre4.setB(2); cPre4.setC(3); - C4 cPost4 = new DeserializationInput(factory1).deserialize(new SerializationOutput(factory1).serialize(cPre4), - C4.class); + C4 cPost4 = new DeserializationInput(factory1).deserialize( + new SerializationOutput(factory1).serialize(cPre4, + TestSerializationContext.testSerializationContext), + C4.class, + TestSerializationContext.testSerializationContext); assertEquals(0, cPost4.a); assertEquals(0, cPost4.b); @@ -280,8 +285,10 @@ public class SetterConstructorTests { o.setB("World"); o.setC(i2); - Outer post = new DeserializationInput(factory1).deserialize(new SerializationOutput(factory1).serialize(o), - Outer.class); + Outer post = new DeserializationInput(factory1).deserialize( + new SerializationOutput(factory1).serialize( + o, TestSerializationContext.testSerializationContext), + Outer.class, TestSerializationContext.testSerializationContext); assertEquals("Hello", post.a.a); assertEquals("World", post.b); @@ -290,7 +297,7 @@ public class SetterConstructorTests { } @Test - public void typeMistmatch() throws NotSerializableException { + public void typeMistmatch() { EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); FingerPrinter fingerPrinter = new SerializerFingerPrinter(); SerializerFactory factory1 = new SerializerFactory( @@ -303,12 +310,13 @@ public class SetterConstructorTests { tm.setA(10); assertEquals("10", tm.getA()); - Assertions.assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm)).isInstanceOf ( + Assertions.assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm, + TestSerializationContext.testSerializationContext)).isInstanceOf ( NotSerializableException.class); } @Test - public void typeMistmatch2() throws NotSerializableException { + public void typeMistmatch2() { EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); FingerPrinter fingerPrinter = new SerializerFingerPrinter(); SerializerFactory factory1 = new SerializerFactory( @@ -321,7 +329,8 @@ public class SetterConstructorTests { tm.setA("10"); assertEquals((Integer)10, tm.getA()); - Assertions.assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm)).isInstanceOf( + Assertions.assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm, + TestSerializationContext.testSerializationContext)).isInstanceOf( NotSerializableException.class); } @@ -347,6 +356,10 @@ public class SetterConstructorTests { // if we've got super / sub types on the setter vs the underlying type the wrong way around this will // explode. See CORDA-1229 (https://r3-cev.atlassian.net/browse/CORDA-1229) - new DeserializationInput(factory1).deserialize(new SerializationOutput(factory1).serialize(cil), CIntList.class); + new DeserializationInput(factory1).deserialize( + new SerializationOutput(factory1).serialize( + cil, TestSerializationContext.testSerializationContext), + CIntList.class, + TestSerializationContext.testSerializationContext); } } diff --git a/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/testutils/TestSerializationContext.java b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/testutils/TestSerializationContext.java new file mode 100644 index 0000000000..126ff34f71 --- /dev/null +++ b/node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/testutils/TestSerializationContext.java @@ -0,0 +1,24 @@ +package net.corda.nodeapi.internal.serialization.amqp.testutils; + +import net.corda.core.serialization.SerializationContext; +import net.corda.core.utilities.ByteSequence; +import net.corda.nodeapi.internal.serialization.AllWhitelist; +import net.corda.nodeapi.internal.serialization.SerializationContextImpl; + + +import java.util.HashMap; +import java.util.Map; + +public class TestSerializationContext { + + static private Map serializationProperties = new HashMap(); + + public static SerializationContext testSerializationContext = new SerializationContextImpl( + ByteSequence.of(new byte[] { 'c', 'o', 'r', 'd', 'a', (byte)0, (byte)0, (byte)1}), + ClassLoader.getSystemClassLoader(), + AllWhitelist.INSTANCE, + serializationProperties, + false, + SerializationContext.UseCase.Testing, + null); +} diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt deleted file mode 100644 index d7701aed52..0000000000 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt +++ /dev/null @@ -1,32 +0,0 @@ -package net.corda.nodeapi.internal.serialization.amqp - -import org.apache.qpid.proton.codec.Data -import net.corda.nodeapi.internal.serialization.AllWhitelist -import net.corda.nodeapi.internal.serialization.EmptyWhitelist - -fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) -fun testDefaultFactoryNoEvolution() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader(), - EvolutionSerializerGetterTesting()) -fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()) - -class TestSerializationOutput( - private val verbose: Boolean, - serializerFactory: SerializerFactory = testDefaultFactory()) - : SerializationOutput(serializerFactory) { - - override fun writeSchema(schema: Schema, data: Data) { - if (verbose) println(schema) - super.writeSchema(schema, data) - } - - override fun writeTransformSchema(transformsSchema: TransformsSchema, data: Data) { - if(verbose) { - println ("Writing Transform Schema") - println (transformsSchema) - } - super.writeTransformSchema(transformsSchema, data) - } -} - -fun testName(): String = Thread.currentThread().stackTrace[2].methodName - diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappSerializerTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappSerializerTests.kt index d809f7beda..8a4367792d 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappSerializerTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/CorDappSerializerTests.kt @@ -3,9 +3,15 @@ package net.corda.nodeapi.internal.serialization.amqp import org.junit.Test import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.SerializationCustomSerializer +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactory import org.assertj.core.api.Assertions import java.io.NotSerializableException import kotlin.test.assertEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize + class CorDappSerializerTests { data class NeedsProxy (val a: String) diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeAndReturnEnvelopeTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeAndReturnEnvelopeTests.kt index d793c9f0d2..f6a3f90439 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeAndReturnEnvelopeTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeAndReturnEnvelopeTests.kt @@ -1,10 +1,17 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.CordaSerializable +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryWithWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.testName import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNotEquals import kotlin.test.assertTrue +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class DeserializeAndReturnEnvelopeTests { // the 'this' reference means we can't just move this to the common test utils diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeMapTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeMapTests.kt index 2e910bf19c..58a2d33bd1 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeMapTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeMapTests.kt @@ -1,8 +1,14 @@ package net.corda.nodeapi.internal.serialization.amqp +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution import org.assertj.core.api.Assertions import org.junit.Test import java.util.* +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class DeserializeMapTests { companion object { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryOfEnumsTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryOfEnumsTest.kt index caa3e06c4f..c3855c73b2 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryOfEnumsTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryOfEnumsTest.kt @@ -1,9 +1,16 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryWithWhitelist import org.junit.Test import kotlin.test.* import net.corda.nodeapi.internal.serialization.carpenter.* +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class DeserializeNeedingCarpentryOfEnumsTest : AmqpCarpenterBase(AllWhitelist) { companion object { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentrySimpleTypesTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentrySimpleTypesTest.kt index 002adc5e24..c7a6b80913 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentrySimpleTypesTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentrySimpleTypesTest.kt @@ -1,9 +1,15 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution import org.junit.Test import kotlin.test.* import net.corda.nodeapi.internal.serialization.carpenter.* +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize // These tests work by having the class carpenter build the classes we serialise and then deserialise. Because // those classes don't exist within the system's Class Loader the deserialiser will be forced to carpent diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryTests.kt index f54112b2dc..c733422c8f 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeNeedingCarpentryTests.kt @@ -5,6 +5,11 @@ import org.junit.Test import kotlin.test.* import net.corda.nodeapi.internal.serialization.carpenter.* import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryWithWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize @CordaSerializable interface I { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeSimpleTypesTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeSimpleTypesTests.kt index 6f2dcd3bc2..85aeece991 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeSimpleTypesTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/DeserializeSimpleTypesTests.kt @@ -1,7 +1,11 @@ package net.corda.nodeapi.internal.serialization.amqp +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution import org.junit.Test import kotlin.test.assertEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize // Prior to certain fixes being made within the [PropertySerializaer] classes these simple // deserialization operations would've blown up with type mismatch errors where the deserlized diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt index 7e898aa46d..c2d919640d 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt @@ -1,6 +1,8 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.* +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactory import net.corda.testing.common.internal.ProjectStructure.projectRootDir import org.assertj.core.api.Assertions import org.junit.Test @@ -10,6 +12,9 @@ import java.util.* import java.util.concurrent.ConcurrentHashMap import kotlin.test.assertEquals import kotlin.test.assertTrue +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope class EnumEvolvabilityTests { @Suppress("UNUSED") diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt index 146eba4d2f..c19a1e8c42 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt @@ -4,6 +4,8 @@ import net.corda.core.internal.toPath import net.corda.core.serialization.CordaSerializationTransformEnumDefault import net.corda.core.serialization.CordaSerializationTransformEnumDefaults import net.corda.core.serialization.SerializedBytes +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactory +import net.corda.nodeapi.internal.serialization.amqp.testutils.testName import net.corda.testing.common.internal.ProjectStructure.projectRootDir import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy @@ -12,6 +14,8 @@ import java.io.NotSerializableException import java.net.URI import kotlin.test.assertEquals import kotlin.test.assertNotNull +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize // NOTE: To recreate the test files used by these tests uncomment the original test classes and comment // the new ones out, then change each test to write out the serialized bytes rather than read diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumTests.kt index 5cb337efa7..bf2c295f5c 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumTests.kt @@ -3,12 +3,19 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.SerializedBytes +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution +import net.corda.nodeapi.internal.serialization.amqp.testutils.testName import org.assertj.core.api.Assertions import org.junit.Test import java.io.NotSerializableException import java.time.DayOfWeek import kotlin.test.assertEquals import kotlin.test.assertNotNull +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class EnumTests { enum class Bras { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/ErrorMessagesTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/ErrorMessagesTests.kt index 6aab88660a..d0c6ac10ce 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/ErrorMessagesTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/ErrorMessagesTests.kt @@ -1,9 +1,16 @@ package net.corda.nodeapi.internal.serialization.amqp +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactory +import net.corda.nodeapi.internal.serialization.amqp.testutils.testName import org.assertj.core.api.Assertions import org.junit.Ignore import org.junit.Test import java.io.NotSerializableException +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class ErrorMessagesTests { companion object { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt index d126cd1df8..a0ab73d26c 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt @@ -8,6 +8,8 @@ import net.corda.core.node.NotaryInfo import net.corda.core.serialization.ConstructorForDeserialization import net.corda.core.serialization.DeprecatedConstructorForDeserialization import net.corda.core.serialization.SerializedBytes +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactory import net.corda.testing.common.internal.ProjectStructure.projectRootDir import net.corda.testing.core.DUMMY_NOTARY_NAME import net.corda.testing.core.TestIdentity @@ -18,6 +20,8 @@ import java.io.NotSerializableException import java.net.URI import java.time.Instant import kotlin.test.assertEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize // To regenerate any of the binary test files do the following // diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/FingerPrinterTesting.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/FingerPrinterTesting.kt index 9b5ceb24df..bb3d4517c9 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/FingerPrinterTesting.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/FingerPrinterTesting.kt @@ -4,6 +4,8 @@ import org.junit.Test import java.lang.reflect.Type import kotlin.test.assertEquals import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema class FingerPrinterTesting : FingerPrinter { private var index = 0 diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/GenericsTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/GenericsTests.kt index 21a26dde5d..41602754a4 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/GenericsTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/GenericsTests.kt @@ -7,12 +7,8 @@ import net.corda.testing.common.internal.ProjectStructure.projectRootDir import org.junit.Test import net.corda.core.identity.AbstractParty import net.corda.core.identity.CordaX500Name -import net.corda.core.identity.Party -import net.corda.core.transactions.WireTransaction +import net.corda.nodeapi.internal.serialization.amqp.testutils.* import net.corda.testing.core.TestIdentity -import org.hibernate.Transaction -import java.io.File -import java.net.URI import java.util.* import java.util.concurrent.ConcurrentHashMap import kotlin.test.assertEquals @@ -301,7 +297,6 @@ class GenericsTests { val factory4 = SerializerFactory(AllWhitelist, cl()) factory4.register(net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer) val des2 = DeserializationInput(factory4).deserializeAndReturnEnvelope(ser2.obj) - } @Test diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/OverridePKSerializerTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/OverridePKSerializerTest.kt index a08bcb5a3c..2eed1e0e00 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/OverridePKSerializerTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/OverridePKSerializerTest.kt @@ -13,11 +13,15 @@ class OverridePKSerializerTest { class SerializerTestException(message: String) : Exception(message) class TestPublicKeySerializer : CustomSerializer.Implements(PublicKey::class.java) { - override fun writeDescribedObject(obj: PublicKey, data: Data, type: Type, output: SerializationOutput) { + override fun writeDescribedObject(obj: PublicKey, data: Data, type: Type, output: SerializationOutput, + context: SerializationContext + ) { throw SerializerTestException("Custom write call") } - override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): PublicKey { + override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, + context: SerializationContext + ) : PublicKey { throw SerializerTestException("Custom read call") } diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt index 795ac1a12e..820b9d3171 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt @@ -3,11 +3,15 @@ package net.corda.nodeapi.internal.serialization.amqp import junit.framework.TestCase.assertTrue import junit.framework.TestCase.assertEquals import net.corda.core.serialization.ConstructorForDeserialization +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution import org.junit.Test import org.apache.qpid.proton.amqp.Symbol import org.assertj.core.api.Assertions import java.io.NotSerializableException import java.util.concurrent.ConcurrentHashMap +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class PrivatePropertyTests { private val factory = testDefaultFactoryNoEvolution() diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/RoundTripTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/RoundTripTests.kt index f42823a862..aeff6be5bd 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/RoundTripTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/RoundTripTests.kt @@ -1,8 +1,11 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.ConstructorForDeserialization +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution import org.assertj.core.api.Assertions import org.junit.Test +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class RoundTripTests { @Test diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutputTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutputTests.kt index 19fddfafe0..290b5e89f6 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutputTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationOutputTests.kt @@ -23,6 +23,7 @@ import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA import net.corda.nodeapi.internal.crypto.ContentSignerBuilder import net.corda.nodeapi.internal.serialization.* import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive +import net.corda.nodeapi.internal.serialization.amqp.testutils.* import net.corda.testing.contracts.DummyContract import net.corda.testing.core.BOB_NAME import net.corda.testing.core.SerializationEnvironmentRule @@ -480,12 +481,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi // Double check copy[valueIndex] = 0x03 - assertThat(des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java).value).isEqualTo(3) + assertThat(des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java, testSerializationContext).value).isEqualTo(3) // Now use the forbidden value copy[valueIndex] = 0x00 assertThatExceptionOfType(NotSerializableException::class.java).isThrownBy { - des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java) + des.deserialize(OpaqueBytes(copy), NonZeroByte::class.java, testSerializationContext) }.withMessageContaining("Zero not allowed") } @@ -650,14 +651,16 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi val scheme = AMQPServerSerializationScheme(emptyList()) val func = scheme::class.superclasses.single { it.simpleName == "AbstractAMQPSerializationScheme" } - .java.getDeclaredMethod("registerCustomSerializers", SerializerFactory::class.java) + .java.getDeclaredMethod("registerCustomSerializers", + SerializationContext::class.java, + SerializerFactory::class.java) func.isAccessible = true val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - func.invoke(scheme, factory) + func.invoke(scheme, testSerializationContext, factory) val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) - func.invoke(scheme, factory2) + func.invoke(scheme, testSerializationContext, factory2) val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false) assertTrue((desState as TransactionState<*>).data is FooState) diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationPropertyOrdering.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationPropertyOrdering.kt index 2fd435aa24..539fed083a 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationPropertyOrdering.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationPropertyOrdering.kt @@ -1,6 +1,8 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.ConstructorForDeserialization +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution import org.junit.Test import java.util.concurrent.ConcurrentHashMap import kotlin.test.assertEquals @@ -8,6 +10,10 @@ import org.apache.qpid.proton.amqp.Symbol import java.lang.reflect.Method import kotlin.test.assertNotNull import kotlin.test.assertTrue +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class SerializationPropertyOrdering { companion object { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializeAndReturnSchemaTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializeAndReturnSchemaTest.kt index 51248a4d4e..b6d8255927 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializeAndReturnSchemaTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializeAndReturnSchemaTest.kt @@ -1,9 +1,12 @@ package net.corda.nodeapi.internal.serialization.amqp +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactoryNoEvolution +import net.corda.nodeapi.internal.serialization.amqp.testutils.testName import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema class SerializeAndReturnSchemaTest { // the 'this' reference means we can't just move this to the common test utils diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/StaticInitialisationOfSerializedObjectTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/StaticInitialisationOfSerializedObjectTest.kt index d303f0dd52..8468bcb4b1 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/StaticInitialisationOfSerializedObjectTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/StaticInitialisationOfSerializedObjectTest.kt @@ -10,6 +10,10 @@ import java.io.NotSerializableException import java.lang.reflect.Type import java.util.concurrent.ConcurrentHashMap import kotlin.test.assertEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.serializeAndReturnSchema +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize class InStatic : Exception("Help!, help!, I'm being repressed") diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/testutils/AMQPTestUtils.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/testutils/AMQPTestUtils.kt new file mode 100644 index 0000000000..e8a02a80b4 --- /dev/null +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/testutils/AMQPTestUtils.kt @@ -0,0 +1,67 @@ +package net.corda.nodeapi.internal.serialization.amqp.testutils + +import net.corda.core.serialization.SerializationContext +import net.corda.core.serialization.SerializedBytes +import org.apache.qpid.proton.codec.Data +import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.EmptyWhitelist +import net.corda.nodeapi.internal.serialization.amqp.* +import java.io.NotSerializableException + +fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) +fun testDefaultFactoryNoEvolution() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader(), + EvolutionSerializerGetterTesting()) +fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()) + +class TestSerializationOutput( + private val verbose: Boolean, + serializerFactory: SerializerFactory = testDefaultFactory()) + : SerializationOutput(serializerFactory) { + + override fun writeSchema(schema: Schema, data: Data) { + if (verbose) println(schema) + super.writeSchema(schema, data) + } + + override fun writeTransformSchema(transformsSchema: TransformsSchema, data: Data) { + if(verbose) { + println ("Writing Transform Schema") + println (transformsSchema) + } + super.writeTransformSchema(transformsSchema, data) + } +} + +fun testName(): String = Thread.currentThread().stackTrace[2].methodName + + +@Throws(NotSerializableException::class) +inline fun DeserializationInput.deserializeAndReturnEnvelope( + bytes: SerializedBytes, + context: SerializationContext? = null +) : ObjectAndEnvelope { + return deserializeAndReturnEnvelope(bytes, T::class.java, + context ?: testSerializationContext) +} + +@Throws(NotSerializableException::class) +inline fun DeserializationInput.deserialize( + bytes: SerializedBytes, + context: SerializationContext? = null +) : T = deserialize(bytes, T::class.java, context ?: testSerializationContext) + + +@Throws(NotSerializableException::class) +fun SerializationOutput.serializeAndReturnSchema( + obj: T, context: SerializationContext? = null +): BytesAndSchemas = serializeAndReturnSchema(obj, context ?: testSerializationContext) + + +@Throws(NotSerializableException::class) +fun SerializationOutput.serialize(obj: T): SerializedBytes { + try { + return _serialize(obj, testSerializationContext) + } finally { + andFinally() + } +} diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/testutils/TestSerializationContext.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/testutils/TestSerializationContext.kt new file mode 100644 index 0000000000..237640a59a --- /dev/null +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/testutils/TestSerializationContext.kt @@ -0,0 +1,17 @@ +package net.corda.nodeapi.internal.serialization.amqp.testutils + +import net.corda.core.serialization.SerializationContext +import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.SerializationContextImpl +import net.corda.nodeapi.internal.serialization.amqp.amqpMagic + +val serializationProperties: MutableMap = mutableMapOf() + +val testSerializationContext = SerializationContextImpl( + preferredSerializationVersion = amqpMagic, + deserializationClassLoader = ClassLoader.getSystemClassLoader(), + whitelist = AllWhitelist, + properties = serializationProperties, + objectReferencesEnabled = false, + useCase = SerializationContext.UseCase.Testing, + encoding = null) \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CarpenterExceptionTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CarpenterExceptionTests.kt index c3ce2469a5..388f20517d 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CarpenterExceptionTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CarpenterExceptionTests.kt @@ -4,6 +4,8 @@ import com.google.common.reflect.TypeToken import junit.framework.Assert.assertTrue import net.corda.nodeapi.internal.serialization.AllWhitelist import net.corda.nodeapi.internal.serialization.amqp.* +import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationOutput +import net.corda.nodeapi.internal.serialization.amqp.testutils.testDefaultFactory import org.assertj.core.api.Assertions import org.junit.Test import java.io.NotSerializableException @@ -11,6 +13,8 @@ import java.lang.reflect.Type import java.net.URL import kotlin.reflect.jvm.jvmName import kotlin.test.assertEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserialize // Simple way to ensure we end up trying to carpent a class, "remove" it from the class loader (if only // actually doing that was simple) diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt index a27b6440d3..87c4ce8854 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt @@ -4,7 +4,7 @@ import net.corda.core.serialization.ClassWhitelist import net.corda.nodeapi.internal.serialization.amqp.* import net.corda.nodeapi.internal.serialization.amqp.Field import net.corda.nodeapi.internal.serialization.amqp.Schema -import net.corda.nodeapi.internal.serialization.AllWhitelist +import net.corda.nodeapi.internal.serialization.amqp.testutils.serialize fun mangleName(name: String) = "${name}__carpenter" diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CompositeMemberCompositeSchemaToClassCarpenterTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CompositeMemberCompositeSchemaToClassCarpenterTests.kt index e9e42e1cf4..992bcd6dff 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CompositeMemberCompositeSchemaToClassCarpenterTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/CompositeMemberCompositeSchemaToClassCarpenterTests.kt @@ -8,6 +8,7 @@ import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope @CordaSerializable interface I_ { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/InheritanceSchemaToClassCarpenterTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/InheritanceSchemaToClassCarpenterTests.kt index cbd35f8a3b..3f9111af3a 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/InheritanceSchemaToClassCarpenterTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/InheritanceSchemaToClassCarpenterTests.kt @@ -5,6 +5,7 @@ import net.corda.nodeapi.internal.serialization.AllWhitelist import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput import org.junit.Test import kotlin.test.* +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope @CordaSerializable interface J { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/MultiMemberCompositeSchemaToClassCarpenterTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/MultiMemberCompositeSchemaToClassCarpenterTests.kt index bc4cafdbb0..ad87f0c801 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/MultiMemberCompositeSchemaToClassCarpenterTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/MultiMemberCompositeSchemaToClassCarpenterTests.kt @@ -7,6 +7,7 @@ import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNotEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase(AllWhitelist) { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/SingleMemberCompositeSchemaToClassCarpenterTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/SingleMemberCompositeSchemaToClassCarpenterTests.kt index 2035afe5a7..6c714b48ac 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/SingleMemberCompositeSchemaToClassCarpenterTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/SingleMemberCompositeSchemaToClassCarpenterTests.kt @@ -6,6 +6,7 @@ import net.corda.nodeapi.internal.serialization.amqp.CompositeType import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput import org.junit.Test import kotlin.test.assertEquals +import net.corda.nodeapi.internal.serialization.amqp.testutils.deserializeAndReturnEnvelope class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase(AllWhitelist) { @Test