mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
OS merge (#806)
This commit is contained in:
@ -361,7 +361,7 @@ internal class ConnectionStateMachine(serverMode: Boolean,
|
||||
val connection = event.connection
|
||||
val channel = connection?.context as? Channel
|
||||
if (channel != null) {
|
||||
val appProperties = HashMap(amqpMessage.applicationProperties.value)
|
||||
val appProperties = HashMap(amqpMessage.applicationProperties.value as Map<String, Any?>)
|
||||
appProperties["_AMQ_VALIDATED_USER"] = remoteLegalName
|
||||
val localAddress = channel.localAddress() as InetSocketAddress
|
||||
val remoteAddress = channel.remoteAddress() as InetSocketAddress
|
||||
@ -438,7 +438,6 @@ internal class ConnectionStateMachine(serverMode: Boolean,
|
||||
}
|
||||
|
||||
fun transportWriteMessage(msg: SendableMessageImpl) {
|
||||
log.debug { "Queue application message write uuid: ${msg.applicationProperties["_AMQ_DUPL_ID"]} ${javax.xml.bind.DatatypeConverter.printHexBinary(msg.payload)}" }
|
||||
msg.buf = encodePayloadBytes(msg)
|
||||
val messageQueue = messageQueues.getOrPut(msg.topic, { LinkedList() })
|
||||
messageQueue.offer(msg)
|
||||
|
@ -130,7 +130,6 @@ internal class AMQPChannelHandler(private val serverMode: Boolean,
|
||||
|
||||
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
|
||||
try {
|
||||
log.debug { "Received $msg" }
|
||||
if (msg is ByteBuf) {
|
||||
eventProcessor!!.transportProcessInput(msg)
|
||||
}
|
||||
@ -143,7 +142,6 @@ internal class AMQPChannelHandler(private val serverMode: Boolean,
|
||||
override fun write(ctx: ChannelHandlerContext, msg: Any, promise: ChannelPromise) {
|
||||
try {
|
||||
try {
|
||||
log.debug { "Sent $msg" }
|
||||
when (msg) {
|
||||
// Transfers application packet into the AMQP engine.
|
||||
is SendableMessageImpl -> {
|
||||
|
@ -90,10 +90,10 @@ class CordaClassResolver(serializationContext: SerializationContext) : DefaultCl
|
||||
val objectInstance = try {
|
||||
targetType.declaredFields.singleOrNull {
|
||||
it.name == "INSTANCE" &&
|
||||
it.type == type &&
|
||||
Modifier.isStatic(it.modifiers) &&
|
||||
Modifier.isFinal(it.modifiers) &&
|
||||
Modifier.isPublic(it.modifiers)
|
||||
it.type == type &&
|
||||
Modifier.isStatic(it.modifiers) &&
|
||||
Modifier.isFinal(it.modifiers) &&
|
||||
Modifier.isPublic(it.modifiers)
|
||||
}?.let {
|
||||
it.isAccessible = true
|
||||
type.cast(it.get(null)!!)
|
||||
@ -172,7 +172,7 @@ object AllWhitelist : ClassWhitelist {
|
||||
override fun hasListed(type: Class<*>): Boolean = true
|
||||
}
|
||||
|
||||
sealed class AbstractMutableClassWhitelist(private val whitelist: MutableSet<String>, private val delegate: ClassWhitelist) : MutableClassWhitelist {
|
||||
sealed class AbstractMutableClassWhitelist(private val whitelist: MutableSet<String>, private val delegate: ClassWhitelist) : MutableClassWhitelist {
|
||||
|
||||
override fun hasListed(type: Class<*>): Boolean {
|
||||
/**
|
||||
|
@ -76,5 +76,5 @@ object DefaultWhitelist : SerializationWhitelist {
|
||||
// Implementation of X509Certificate.
|
||||
X509CertImpl::class.java,
|
||||
CRLReason::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.nodeapi.internal.serialization.OrdinalBits.OrdinalWriter
|
||||
import org.iq80.snappy.SnappyFramedInputStream
|
||||
import org.iq80.snappy.SnappyFramedOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.zip.DeflaterOutputStream
|
||||
import java.util.zip.InflaterInputStream
|
||||
|
@ -49,13 +49,15 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
|
||||
*/
|
||||
override fun withAttachmentsClassLoader(attachmentHashes: List<SecureHash>): 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<SecureHash>()
|
||||
val attachments = ArrayList<Attachment>()
|
||||
attachmentHashes.forEach { id ->
|
||||
serializationContext.serviceHub.attachments.openAttachment(id)?.let { attachments += it } ?: run { missing += id }
|
||||
serializationContext.serviceHub.attachments.openAttachment(id)?.let { attachments += it }
|
||||
?: run { missing += id }
|
||||
}
|
||||
missing.isNotEmpty() && throw MissingAttachmentsException(missing)
|
||||
AttachmentsClassLoader(attachments, parent = deserializationClassLoader)
|
||||
@ -90,7 +92,7 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
|
||||
|
||||
open class SerializationFactoryImpl : SerializationFactory() {
|
||||
companion object {
|
||||
private val magicSize = sequenceOf(kryoMagic, amqpMagic).map { it.size }.distinct().single()
|
||||
val magicSize = sequenceOf(kryoMagic, amqpMagic).map { it.size }.distinct().single()
|
||||
}
|
||||
|
||||
private val creator: List<StackTraceElement> = Exception().stackTrace.asList()
|
||||
@ -153,8 +155,6 @@ open class SerializationFactoryImpl : SerializationFactory() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
interface SerializationScheme {
|
||||
fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean
|
||||
@Throws(NotSerializableException::class)
|
||||
|
@ -62,5 +62,6 @@ class SerializeAsTokenContextImpl(override val serviceHub: ServiceHub, init: Ser
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSingleton(className: String) = classNameToSingleton[className] ?: throw IllegalStateException("Unable to find tokenized instance of $className in context $this")
|
||||
override fun getSingleton(className: String) = classNameToSingleton[className]
|
||||
?: throw IllegalStateException("Unable to find tokenized instance of $className in context $this")
|
||||
}
|
@ -15,7 +15,8 @@ import net.corda.core.serialization.SerializationFactory
|
||||
import java.util.*
|
||||
|
||||
internal fun checkUseCase(allowedUseCases: EnumSet<SerializationContext.UseCase>) {
|
||||
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'")
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import org.apache.qpid.proton.amqp.UnsignedLong
|
||||
* Repeated here for brevity:
|
||||
* 50530 - R3 - Mike Hearn - mike&r3.com
|
||||
*/
|
||||
const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl(32 + 16)
|
||||
const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl (32 + 16)
|
||||
|
||||
/**
|
||||
* AMQP descriptor ID's for our custom types.
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Binary
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -28,7 +29,14 @@ class AMQPPrimitiveSerializer(clazz: Class<*>) : AMQPSerializer<Any> {
|
||||
override fun writeClassInfo(output: SerializationOutput) {
|
||||
}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(
|
||||
obj: Any,
|
||||
data: Data,
|
||||
type: Type,
|
||||
output: SerializationOutput,
|
||||
context: SerializationContext,
|
||||
debugIndent: Int
|
||||
) {
|
||||
if (obj is ByteArray) {
|
||||
data.putObject(Binary(obj))
|
||||
} else {
|
||||
@ -39,5 +47,6 @@ class AMQPPrimitiveSerializer(clazz: Class<*>) : AMQPSerializer<Any> {
|
||||
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
|
||||
}
|
@ -16,8 +16,8 @@ import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
||||
import net.corda.core.cordapp.Cordapp
|
||||
import net.corda.core.internal.objectOrNewInstance
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
||||
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.MutableClassWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.SerializationScheme
|
||||
@ -41,12 +41,12 @@ fun SerializerFactory.addToWhitelist(vararg types: Class<*>) {
|
||||
|
||||
open class SerializerFactoryFactory {
|
||||
open fun make(context: SerializationContext) =
|
||||
SerializerFactory(context.whitelist, context.deserializationClassLoader)
|
||||
SerializerFactory(context.whitelist, context.deserializationClassLoader)
|
||||
}
|
||||
|
||||
abstract class AbstractAMQPSerializationScheme(
|
||||
val cordappLoader: List<Cordapp>,
|
||||
val sff : SerializerFactoryFactory = SerializerFactoryFactory()
|
||||
val sff: SerializerFactoryFactory = SerializerFactoryFactory()
|
||||
) : SerializationScheme {
|
||||
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
|
||||
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
|
||||
@ -62,7 +62,7 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
|
||||
val scanSpec: String? = System.getProperty(SCAN_SPEC_PROP_NAME)
|
||||
|
||||
if(scanSpec == null) {
|
||||
if (scanSpec == null) {
|
||||
emptyList()
|
||||
} else {
|
||||
FastClasspathScanner(scanSpec).addClassLoader(this::class.java.classLoader).scan()
|
||||
@ -74,7 +74,7 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerCustomSerializers(factory: SerializerFactory) {
|
||||
private fun registerCustomSerializers(context: SerializationContext, factory: SerializerFactory) {
|
||||
with(factory) {
|
||||
register(publicKeySerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PrivateKeySerializer)
|
||||
@ -131,8 +131,7 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
|
||||
protected abstract fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory
|
||||
protected abstract fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory
|
||||
open protected val publicKeySerializer: CustomSerializer.Implements<PublicKey>
|
||||
= net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer
|
||||
protected open val publicKeySerializer: CustomSerializer.Implements<PublicKey> = net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer
|
||||
|
||||
private fun getSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||
return serializerFactoriesForContexts.computeIfAbsent(Pair(context.whitelist, context.deserializationClassLoader)) {
|
||||
@ -145,19 +144,20 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
rpcServerSerializerFactory(context)
|
||||
else -> sff.make(context)
|
||||
}.also {
|
||||
registerCustomSerializers(it)
|
||||
registerCustomSerializers(context, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T {
|
||||
val serializerFactory = getSerializerFactory(context)
|
||||
return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz)
|
||||
return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz, context)
|
||||
}
|
||||
|
||||
override fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
||||
val serializerFactory = getSerializerFactory(context)
|
||||
return SerializationOutput(serializerFactory).serialize(obj)
|
||||
|
||||
return SerializationOutput(serializerFactory).serialize(obj, context)
|
||||
}
|
||||
|
||||
protected fun canDeserializeVersion(magic: CordaSerializationMagic) = magic == amqpMagic
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
@ -40,10 +41,11 @@ interface AMQPSerializer<out T> {
|
||||
/**
|
||||
* 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
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
@ -42,7 +43,8 @@ open class ArraySerializer(override val type: Type, factory: SerializerFactory)
|
||||
}
|
||||
|
||||
override val typeDescriptor by lazy {
|
||||
Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}") }
|
||||
Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
|
||||
}
|
||||
internal val elementType: Type by lazy { type.componentType() }
|
||||
internal open val typeName by lazy { calcTypeName(type) }
|
||||
|
||||
@ -56,20 +58,24 @@ open class ArraySerializer(override val type: Type, factory: SerializerFactory)
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
// Write described
|
||||
data.withDescribed(typeNotation.descriptor) {
|
||||
withList {
|
||||
for (entry in obj as Array<*>) {
|
||||
output.writeObjectOrNull(entry, this, elementType, debugIndent)
|
||||
output.writeObjectOrNull(entry, this, elementType, context, debugIndent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): Any {
|
||||
if (obj is List<*>) {
|
||||
return obj.map { input.readObjectOrNull(it, schemas, elementType) }.toArrayOfType(elementType)
|
||||
return obj.map { input.readObjectOrNull(it, schemas, elementType, context) }.toArrayOfType(elementType)
|
||||
} else throw NotSerializableException("Expected a List but found $obj")
|
||||
}
|
||||
|
||||
@ -118,20 +124,24 @@ abstract class PrimArraySerializer(type: Type, factory: SerializerFactory) : Arr
|
||||
}
|
||||
}
|
||||
|
||||
class PrimIntArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(IntArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
class PrimIntArraySerializer(factory: SerializerFactory) : PrimArraySerializer(IntArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
localWriteObject(data) {
|
||||
(obj as IntArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
(obj as IntArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PrimCharArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(CharArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
localWriteObject(data) { (obj as CharArray).forEach {
|
||||
output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
class PrimCharArraySerializer(factory: SerializerFactory) : PrimArraySerializer(CharArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
localWriteObject(data) {
|
||||
(obj as CharArray).forEach {
|
||||
output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,47 +155,55 @@ class PrimCharArraySerializer(factory: SerializerFactory) :
|
||||
}
|
||||
}
|
||||
|
||||
class PrimBooleanArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(BooleanArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
class PrimBooleanArraySerializer(factory: SerializerFactory) : PrimArraySerializer(BooleanArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
localWriteObject(data) {
|
||||
(obj as BooleanArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
(obj as BooleanArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PrimDoubleArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(DoubleArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
localWriteObject(data) {
|
||||
(obj as DoubleArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
(obj as DoubleArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PrimFloatArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(FloatArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int) {
|
||||
localWriteObject(data) {
|
||||
(obj as FloatArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
(obj as FloatArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PrimShortArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(ShortArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
localWriteObject(data) {
|
||||
(obj as ShortArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
(obj as ShortArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PrimLongArraySerializer(factory: SerializerFactory) :
|
||||
PrimArraySerializer(LongArray::class.java, factory) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
localWriteObject(data) {
|
||||
(obj as LongArray).forEach { output.writeObjectOrNull(it, data, elementType, debugIndent+1) }
|
||||
(obj as LongArray).forEach { output.writeObjectOrNull(it, data, elementType, context, debugIndent + 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.utilities.NonEmptySet
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -18,15 +19,14 @@ import java.io.NotSerializableException
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
import java.util.*
|
||||
import kotlin.collections.Collection
|
||||
import kotlin.collections.LinkedHashSet
|
||||
import kotlin.collections.Set
|
||||
|
||||
/**
|
||||
* Serialization / deserialization of predefined set of supported [Collection] types covering mostly [List]s and [Set]s.
|
||||
*/
|
||||
class CollectionSerializer(val declaredType: ParameterizedType, factory: SerializerFactory) : AMQPSerializer<Any> {
|
||||
override val type: Type = declaredType as? DeserializedParameterizedType ?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType))
|
||||
override val type: Type = declaredType as? DeserializedParameterizedType
|
||||
?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType))
|
||||
override val typeDescriptor by lazy {
|
||||
Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
|
||||
}
|
||||
@ -60,7 +60,8 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
|
||||
}
|
||||
|
||||
private fun deriveParametrizedType(declaredType: Type, collectionClass: Class<out Collection<*>>): ParameterizedType =
|
||||
(declaredType as? ParameterizedType) ?: DeserializedParameterizedType(collectionClass, arrayOf(SerializerFactory.AnyType))
|
||||
(declaredType as? ParameterizedType)
|
||||
?: DeserializedParameterizedType(collectionClass, arrayOf(SerializerFactory.AnyType))
|
||||
|
||||
|
||||
private fun findMostSuitableCollectionType(actualClass: Class<*>): Class<out Collection<*>> =
|
||||
@ -83,12 +84,13 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
|
||||
data: Data,
|
||||
type: Type,
|
||||
output: SerializationOutput,
|
||||
context: SerializationContext,
|
||||
debugIndent: Int) = ifThrowsAppend({ declaredType.typeName }) {
|
||||
// Write described
|
||||
data.withDescribed(typeNotation.descriptor) {
|
||||
withList {
|
||||
for (entry in obj as Collection<*>) {
|
||||
output.writeObjectOrNull(entry, this, declaredType.actualTypeArguments[0], debugIndent)
|
||||
output.writeObjectOrNull(entry, this, declaredType.actualTypeArguments[0], context, debugIndent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,8 +99,11 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
|
||||
override fun readObject(
|
||||
obj: Any,
|
||||
schemas: SerializationSchemas,
|
||||
input: DeserializationInput): Any = ifThrowsAppend({ declaredType.typeName }) {
|
||||
input: DeserializationInput,
|
||||
context: SerializationContext): Any = ifThrowsAppend({ declaredType.typeName }) {
|
||||
// TODO: Can we verify the entries in the list?
|
||||
concreteBuilder((obj as List<*>).map { input.readObjectOrNull(it, schemas, declaredType.actualTypeArguments[0]) })
|
||||
concreteBuilder((obj as List<*>).map {
|
||||
input.readObjectOrNull(it, schemas, declaredType.actualTypeArguments[0], context)
|
||||
})
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationCustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
@ -74,22 +75,25 @@ class CorDappCustomSerializer(
|
||||
|
||||
override fun writeClassInfo(output: SerializationOutput) {}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
val proxy = uncheckedCast<SerializationCustomSerializer<*, *>,
|
||||
SerializationCustomSerializer<Any?, Any?>>(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<*, *>, SerializationCustomSerializer<Any?, Any?>>(
|
||||
serializer).fromProxy(uncheckedCast(proxySerializer.readObject(obj, schemas, input)))!!
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
) = uncheckedCast<SerializationCustomSerializer<*, *>, SerializationCustomSerializer<Any?, Any?>>(
|
||||
serializer).fromProxy(uncheckedCast(proxySerializer.readObject(obj, schemas, input, context)))!!
|
||||
|
||||
override fun isSerializerFor(clazz: Class<*>) = clazz == type
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -50,13 +51,16 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
*/
|
||||
override val revealSubclassesInSchema: Boolean get() = false
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
data.withDescribed(descriptor) {
|
||||
writeDescribedObject(uncheckedCast(obj), data, type, output)
|
||||
writeDescribedObject(uncheckedCast(obj), data, type, output, context)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput)
|
||||
abstract fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext)
|
||||
|
||||
/**
|
||||
* This custom serializer represents a sort of symbolic link from a subclass to a super class, where the super
|
||||
@ -87,12 +91,16 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
|
||||
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
|
||||
superClassSerializer.writeDescribedObject(obj, data, type, output)
|
||||
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext
|
||||
) {
|
||||
superClassSerializer.writeDescribedObject(obj, data, type, output, context)
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T {
|
||||
return superClassSerializer.readObject(obj, schemas, input)
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): T {
|
||||
return superClassSerializer.readObject(obj, schemas, input, context)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +142,12 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
private val proxySerializer: ObjectSerializer by lazy { ObjectSerializer(proxyClass, factory) }
|
||||
|
||||
override val schemaForDocumentation: Schema by lazy {
|
||||
val typeNotations = mutableSetOf<TypeNotation>(CompositeType(nameForType(type), null, emptyList(), descriptor, (proxySerializer.typeNotation as CompositeType).fields))
|
||||
val typeNotations = mutableSetOf<TypeNotation>(
|
||||
CompositeType(
|
||||
nameForType(type),
|
||||
null,
|
||||
emptyList(),
|
||||
descriptor, (proxySerializer.typeNotation as CompositeType).fields))
|
||||
for (additional in additionalSerializers) {
|
||||
typeNotations.addAll(additional.schemaForDocumentation.types)
|
||||
}
|
||||
@ -148,17 +161,21 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
|
||||
protected abstract fun fromProxy(proxy: P): T
|
||||
|
||||
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
|
||||
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext
|
||||
) {
|
||||
val proxy = toProxy(obj)
|
||||
data.withList {
|
||||
proxySerializer.propertySerializers.serializationOrder.forEach {
|
||||
it.getter.writeProperty(proxy, this, output)
|
||||
it.getter.writeProperty(proxy, this, output, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T {
|
||||
val proxy: P = uncheckedCast(proxySerializer.readObject(obj, schemas, input))
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): T {
|
||||
val proxy: P = uncheckedCast(proxySerializer.readObject(obj, schemas, input, context))
|
||||
return fromProxy(proxy)
|
||||
}
|
||||
}
|
||||
@ -186,11 +203,15 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, 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)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import com.esotericsoftware.kryo.io.ByteBufferInputStream
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.getStackTraceAsString
|
||||
import net.corda.core.serialization.EncodingWhitelist
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.nodeapi.internal.serialization.CordaSerializationEncoding
|
||||
@ -45,7 +46,7 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
private val encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist) {
|
||||
private val objectHistory: MutableList<Any> = mutableListOf()
|
||||
|
||||
internal companion object {
|
||||
companion object {
|
||||
private val BYTES_NEEDED_TO_PEEK: Int = 23
|
||||
|
||||
fun peekSize(bytes: ByteArray): Int {
|
||||
@ -70,9 +71,10 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
|
||||
@VisibleForTesting
|
||||
@Throws(NotSerializableException::class)
|
||||
internal fun <T> withDataBytes(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist, task: (ByteBuffer) -> T): T {
|
||||
fun <T> withDataBytes(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist, task: (ByteBuffer) -> T): T {
|
||||
// Check that the lead bytes match expected header
|
||||
val amqpSequence = amqpMagic.consume(byteSequence) ?: throw NotSerializableException("Serialization header does not match.")
|
||||
val amqpSequence = amqpMagic.consume(byteSequence)
|
||||
?: throw NotSerializableException("Serialization header does not match.")
|
||||
var stream: InputStream = ByteBufferInputStream(amqpSequence)
|
||||
try {
|
||||
while (true) {
|
||||
@ -89,25 +91,27 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
stream.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline fun <reified T : Any> deserialize(bytes: SerializedBytes<T>): T = deserialize(bytes, T::class.java)
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline internal fun <reified T : Any> deserializeAndReturnEnvelope(bytes: SerializedBytes<T>): ObjectAndEnvelope<T> =
|
||||
deserializeAndReturnEnvelope(bytes, T::class.java)
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
internal fun getEnvelope(byteSequence: ByteSequence): Envelope {
|
||||
return withDataBytes(byteSequence, encodingWhitelist) { dataBytes ->
|
||||
val data = Data.Factory.create()
|
||||
val expectedSize = dataBytes.remaining()
|
||||
if (data.decode(dataBytes) != expectedSize.toLong()) throw NotSerializableException("Unexpected size of data")
|
||||
Envelope.get(data)
|
||||
@Throws(NotSerializableException::class)
|
||||
fun getEnvelope(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist): Envelope {
|
||||
return withDataBytes(byteSequence, encodingWhitelist) { dataBytes ->
|
||||
val data = Data.Factory.create()
|
||||
val expectedSize = dataBytes.remaining()
|
||||
if (data.decode(dataBytes) != expectedSize.toLong()) throw NotSerializableException("Unexpected size of data")
|
||||
Envelope.get(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun getEnvelope(byteSequence: ByteSequence) = Companion.getEnvelope(byteSequence, encodingWhitelist)
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline fun <reified T : Any> deserialize(bytes: SerializedBytes<T>, context: SerializationContext): T =
|
||||
deserialize(bytes, T::class.java, context)
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
private fun <R> des(generator: () -> R): R {
|
||||
try {
|
||||
@ -127,23 +131,37 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
* be deserialized and a schema describing the types of the objects.
|
||||
*/
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> deserialize(bytes: ByteSequence, clazz: Class<T>): T = des {
|
||||
val envelope = getEnvelope(bytes)
|
||||
clazz.cast(readObjectOrNull(envelope.obj, SerializationSchemas(envelope.schema, envelope.transformsSchema), clazz))
|
||||
}
|
||||
fun <T : Any> deserialize(bytes: ByteSequence, clazz: Class<T>, 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 <T : Any> deserializeAndReturnEnvelope(bytes: SerializedBytes<T>, clazz: Class<T>): ObjectAndEnvelope<T> = des {
|
||||
val envelope = getEnvelope(bytes)
|
||||
fun <T : Any> deserializeAndReturnEnvelope(
|
||||
bytes: SerializedBytes<T>,
|
||||
clazz: Class<T>,
|
||||
context: SerializationContext
|
||||
): ObjectAndEnvelope<T> = des {
|
||||
val envelope = getEnvelope(bytes, encodingWhitelist)
|
||||
// Now pick out the obj and schema from the envelope.
|
||||
ObjectAndEnvelope(clazz.cast(readObjectOrNull(envelope.obj, SerializationSchemas(envelope.schema, envelope.transformsSchema), clazz)), envelope)
|
||||
ObjectAndEnvelope(
|
||||
clazz.cast(readObjectOrNull(
|
||||
envelope.obj,
|
||||
SerializationSchemas(envelope.schema, envelope.transformsSchema),
|
||||
clazz,
|
||||
context)),
|
||||
envelope)
|
||||
}
|
||||
|
||||
internal fun readObjectOrNull(obj: Any?, schema: SerializationSchemas, type: Type, offset: Int = 0): Any? {
|
||||
return if (obj == null) null else readObject(obj, schema, type, offset)
|
||||
internal fun readObjectOrNull(obj: Any?, schema: SerializationSchemas, type: Type, context: SerializationContext,
|
||||
offset: Int = 0
|
||||
): Any? {
|
||||
return if (obj == null) null else readObject(obj, schema, type, context, offset)
|
||||
}
|
||||
|
||||
internal fun readObject(obj: Any, schemas: SerializationSchemas, type: Type, debugIndent: Int = 0): Any =
|
||||
internal fun readObject(obj: Any, schemas: SerializationSchemas, type: Type, context: SerializationContext, debugIndent: Int = 0): Any =
|
||||
if (obj is DescribedType && ReferencedObject.DESCRIPTOR == obj.descriptor) {
|
||||
// It must be a reference to an instance that has already been read, cheaply and quickly returning it by reference.
|
||||
val objectIndex = (obj.described as UnsignedInteger).toInt()
|
||||
@ -164,19 +182,20 @@ class DeserializationInput @JvmOverloads constructor(private val serializerFacto
|
||||
// Look up serializer in factory by descriptor
|
||||
val serializer = serializerFactory.get(obj.descriptor, schemas)
|
||||
if (SerializerFactory.AnyType != type && serializer.type != type && with(serializer.type) {
|
||||
!isSubClassOf(type) && !materiallyEquivalentTo(type)
|
||||
}) {
|
||||
!isSubClassOf(type) && !materiallyEquivalentTo(type)
|
||||
}) {
|
||||
throw NotSerializableException("Described type with descriptor ${obj.descriptor} was " +
|
||||
"expected to be of type $type but was ${serializer.type}")
|
||||
}
|
||||
serializer.readObject(obj.described, schemas, this)
|
||||
serializer.readObject(obj.described, schemas, this, context)
|
||||
}
|
||||
is Binary -> obj.array
|
||||
else -> obj // this will be the case for primitive types like [boolean] et al.
|
||||
}
|
||||
|
||||
// Store the reference in case we need it later on.
|
||||
// Skip for primitive types as they are too small and overhead of referencing them will be much higher than their content
|
||||
// Skip for primitive types as they are too small and overhead of referencing them will be much higher
|
||||
// than their content
|
||||
if (suitableForObjectReference(objectRead.javaClass)) {
|
||||
objectHistory.add(objectRead)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
@ -75,7 +76,8 @@ class EnumEvolutionSerializer(
|
||||
new: AMQPSerializer<Any>,
|
||||
factory: SerializerFactory,
|
||||
schemas: SerializationSchemas): AMQPSerializer<Any> {
|
||||
val wireTransforms = schemas.transforms.types[old.name] ?: EnumMap<TransformTypes, MutableList<Transform>>(TransformTypes::class.java)
|
||||
val wireTransforms = schemas.transforms.types[old.name]
|
||||
?: EnumMap<TransformTypes, MutableList<Transform>>(TransformTypes::class.java)
|
||||
val localTransforms = TransformsSchema.get(old.name, factory)
|
||||
|
||||
// remember, the longer the list the newer we're assuming the transform set it as we assume
|
||||
@ -127,7 +129,9 @@ class EnumEvolutionSerializer(
|
||||
}
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): Any {
|
||||
val enumName = (obj as List<*>)[0] as String
|
||||
|
||||
if (enumName !in conversions) {
|
||||
@ -141,7 +145,9 @@ class EnumEvolutionSerializer(
|
||||
throw UnsupportedOperationException("It should be impossible to write an evolution serializer")
|
||||
}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
throw UnsupportedOperationException("It should be impossible to write an evolution serializer")
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
@ -38,7 +39,9 @@ class EnumSerializer(declaredType: Type, declaredClass: Class<*>, factory: Seria
|
||||
output.writeTypeNotations(typeNotation)
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): Any {
|
||||
val enumName = (obj as List<*>)[0] as String
|
||||
val enumOrd = obj[1] as Int
|
||||
val fromOrd = type.asClass()!!.enumConstants[enumOrd] as Enum<*>?
|
||||
@ -50,7 +53,9 @@ class EnumSerializer(declaredType: Type, declaredClass: Class<*>, factory: Seria
|
||||
return fromOrd
|
||||
}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
if (obj !is Enum<*>) throw NotSerializableException("Serializing $obj as enum when it isn't")
|
||||
|
||||
data.withDescribed(typeNotation.descriptor) {
|
||||
|
@ -39,7 +39,7 @@ data class Envelope(val obj: Any?, val schema: Schema, val transformsSchema: Tra
|
||||
fun get(data: Data): Envelope {
|
||||
val describedType = data.`object` as DescribedType
|
||||
if (describedType.descriptor != DESCRIPTOR) {
|
||||
throw NotSerializableException("Unexpected descriptor ${describedType.descriptor}.")
|
||||
throw NotSerializableException("Unexpected descriptor ${describedType.descriptor}, should be $DESCRIPTOR.")
|
||||
}
|
||||
val list = describedType.described as List<*>
|
||||
|
||||
|
@ -11,10 +11,11 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.serialization.carpenter.getTypeAsClass
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.jvm.javaType
|
||||
@ -49,12 +50,13 @@ abstract class EvolutionSerializer(
|
||||
* @param property object to read the actual property value
|
||||
*/
|
||||
data class OldParam(var resultsIndex: Int, val property: PropertySerializer) {
|
||||
fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput, new: Array<Any?>) =
|
||||
property.readProperty(obj, schemas, input).apply {
|
||||
if(resultsIndex >= 0) {
|
||||
new[resultsIndex] = this
|
||||
}
|
||||
}
|
||||
fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
new: Array<Any?>, context: SerializationContext
|
||||
) = property.readProperty(obj, schemas, input, context).apply {
|
||||
if (resultsIndex >= 0) {
|
||||
new[resultsIndex] = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -106,7 +108,7 @@ abstract class EvolutionSerializer(
|
||||
"New parameter ${it.value.name} is mandatory, should be nullable for evolution to worK")
|
||||
}
|
||||
}
|
||||
return EvolutionSerializerViaConstructor (new.type, factory, readersAsSerialized, constructor, constructorArgs)
|
||||
return EvolutionSerializerViaConstructor(new.type, factory, readersAsSerialized, constructor, constructorArgs)
|
||||
}
|
||||
|
||||
private fun makeWithSetters(
|
||||
@ -118,7 +120,7 @@ abstract class EvolutionSerializer(
|
||||
val setters = propertiesForSerializationFromSetters(classProperties,
|
||||
new.type,
|
||||
factory).associateBy({ it.getter.name }, { it })
|
||||
return EvolutionSerializerViaSetters (new.type, factory, readersAsSerialized, constructor, setters)
|
||||
return EvolutionSerializerViaSetters(new.type, factory, readersAsSerialized, constructor, setters)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,14 +155,15 @@ abstract class EvolutionSerializer(
|
||||
|
||||
return if (classProperties.isNotEmpty() && constructor.parameters.isEmpty()) {
|
||||
makeWithSetters(new, factory, constructor, readersAsSerialized, classProperties)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
makeWithConstructor(new, factory, constructor, readersAsSerialized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
throw UnsupportedOperationException("It should be impossible to write an evolution serializer")
|
||||
}
|
||||
}
|
||||
@ -170,7 +173,7 @@ class EvolutionSerializerViaConstructor(
|
||||
factory: SerializerFactory,
|
||||
oldReaders: Map<String, EvolutionSerializer.OldParam>,
|
||||
kotlinConstructor: KFunction<Any>?,
|
||||
private val constructorArgs: Array<Any?>) : EvolutionSerializer (clazz, factory, oldReaders, kotlinConstructor) {
|
||||
private val constructorArgs: Array<Any?>) : EvolutionSerializer(clazz, factory, oldReaders, kotlinConstructor) {
|
||||
/**
|
||||
* Unlike a normal [readObject] call where we simply apply the parameter deserialisers
|
||||
* to the object list of values we need to map that list, which is ordered per the
|
||||
@ -180,15 +183,16 @@ class EvolutionSerializerViaConstructor(
|
||||
*
|
||||
* TODO: Object references
|
||||
*/
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): Any {
|
||||
if (obj !is List<*>) throw NotSerializableException("Body of described type is unexpected $obj")
|
||||
|
||||
// *must* read all the parameters in the order they were serialized
|
||||
oldReaders.values.zip(obj).map { it.first.readProperty(it.second, schemas, input, constructorArgs) }
|
||||
oldReaders.values.zip(obj).map { it.first.readProperty(it.second, schemas, input, constructorArgs, context) }
|
||||
|
||||
return javaConstructor?.newInstance(*(constructorArgs)) ?:
|
||||
throw NotSerializableException(
|
||||
"Attempt to deserialize an interface: $clazz. Serialized form is invalid.")
|
||||
return javaConstructor?.newInstance(*(constructorArgs)) ?: throw NotSerializableException(
|
||||
"Attempt to deserialize an interface: $clazz. Serialized form is invalid.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,18 +205,20 @@ class EvolutionSerializerViaSetters(
|
||||
factory: SerializerFactory,
|
||||
oldReaders: Map<String, EvolutionSerializer.OldParam>,
|
||||
kotlinConstructor: KFunction<Any>?,
|
||||
private val setters: Map<String, PropertyAccessor>) : EvolutionSerializer (clazz, factory, oldReaders, kotlinConstructor) {
|
||||
private val setters: Map<String, PropertyAccessor>) : 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)
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
@ -18,9 +19,6 @@ import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
import java.util.*
|
||||
import kotlin.collections.LinkedHashMap
|
||||
import kotlin.collections.Map
|
||||
import kotlin.collections.iterator
|
||||
import kotlin.collections.map
|
||||
|
||||
private typealias MapCreationFunction = (Map<*, *>) -> Map<*, *>
|
||||
|
||||
@ -28,8 +26,8 @@ private typealias MapCreationFunction = (Map<*, *>) -> Map<*, *>
|
||||
* Serialization / deserialization of certain supported [Map] types.
|
||||
*/
|
||||
class MapSerializer(private val declaredType: ParameterizedType, factory: SerializerFactory) : AMQPSerializer<Any> {
|
||||
override val type: Type = (declaredType as? DeserializedParameterizedType) ?:
|
||||
DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType), factory.classloader)
|
||||
override val type: Type = (declaredType as? DeserializedParameterizedType)
|
||||
?: DeserializedParameterizedType.make(SerializerFactory.nameForType(declaredType), factory.classloader)
|
||||
override val typeDescriptor: Symbol = Symbol.valueOf(
|
||||
"$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
|
||||
|
||||
@ -67,7 +65,8 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
|
||||
}
|
||||
|
||||
private fun deriveParametrizedType(declaredType: Type, collectionClass: Class<out Map<*, *>>): 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<out Map<*, *>> =
|
||||
@ -90,6 +89,7 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
|
||||
data: Data,
|
||||
type: Type,
|
||||
output: SerializationOutput,
|
||||
context: SerializationContext,
|
||||
debugIndent: Int) = ifThrowsAppend({ declaredType.typeName }) {
|
||||
obj.javaClass.checkSupportedMapType()
|
||||
// Write described
|
||||
@ -98,22 +98,25 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
|
||||
data.putMap()
|
||||
data.enter()
|
||||
for ((key, value) in obj as Map<*, *>) {
|
||||
output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0], debugIndent)
|
||||
output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1], debugIndent)
|
||||
output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0], context, debugIndent)
|
||||
output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1], context, debugIndent)
|
||||
}
|
||||
data.exit() // exit map
|
||||
}
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any = ifThrowsAppend({ declaredType.typeName }) {
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
): Any = ifThrowsAppend({ declaredType.typeName }) {
|
||||
// TODO: General generics question. Do we need to validate that entries in Maps and Collections match the generic type? Is it a security hole?
|
||||
val entries: Iterable<Pair<Any?, Any?>> = (obj as Map<*, *>).map { readEntry(schemas, input, it) }
|
||||
val entries: Iterable<Pair<Any?, Any?>> = (obj as Map<*, *>).map { readEntry(schemas, input, it, context) }
|
||||
concreteBuilder(entries.toMap())
|
||||
}
|
||||
|
||||
private fun readEntry(schemas: SerializationSchemas, input: DeserializationInput, entry: Map.Entry<Any?, Any?>) =
|
||||
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<Any?, Any?>,
|
||||
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.
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
|
||||
@ -67,6 +68,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
|
||||
data: Data,
|
||||
type: Type,
|
||||
output: SerializationOutput,
|
||||
context: SerializationContext,
|
||||
debugIndent: Int) = ifThrowsAppend({ clazz.typeName }
|
||||
) {
|
||||
if (propertySerializers.size != javaConstructor?.parameterCount &&
|
||||
@ -82,7 +84,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
|
||||
// Write list
|
||||
withList {
|
||||
propertySerializers.serializationOrder.forEach { property ->
|
||||
property.getter.writeProperty(obj, this, output, debugIndent + 1)
|
||||
property.getter.writeProperty(obj, this, output, context, debugIndent + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,16 +93,17 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
|
||||
override fun readObject(
|
||||
obj: Any,
|
||||
schemas: SerializationSchemas,
|
||||
input: DeserializationInput): Any = ifThrowsAppend({ clazz.typeName }) {
|
||||
input: DeserializationInput,
|
||||
context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
|
||||
if (obj is List<*>) {
|
||||
if (obj.size > propertySerializers.size) {
|
||||
throw NotSerializableException("Too many properties in described type $typeName")
|
||||
}
|
||||
|
||||
return if (propertySerializers.byConstructor) {
|
||||
readObjectBuildViaConstructor(obj, schemas, input)
|
||||
readObjectBuildViaConstructor(obj, schemas, input, context)
|
||||
} else {
|
||||
readObjectBuildViaSetters(obj, schemas, input)
|
||||
readObjectBuildViaSetters(obj, schemas, input, context)
|
||||
}
|
||||
} else {
|
||||
throw NotSerializableException("Body of described type is unexpected $obj")
|
||||
@ -110,12 +113,13 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
|
||||
private fun readObjectBuildViaConstructor(
|
||||
obj: List<*>,
|
||||
schemas: SerializationSchemas,
|
||||
input: DeserializationInput): Any = ifThrowsAppend({ clazz.typeName }) {
|
||||
input: DeserializationInput,
|
||||
context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
|
||||
logger.trace { "Calling construction based construction for ${clazz.typeName}" }
|
||||
|
||||
return construct(propertySerializers.serializationOrder
|
||||
.zip(obj)
|
||||
.map { Pair(it.first.initialPosition, it.first.getter.readProperty(it.second, schemas, input)) }
|
||||
.map { Pair(it.first.initialPosition, it.first.getter.readProperty(it.second, schemas, input, context)) }
|
||||
.sortedWith(compareBy({ it.first }))
|
||||
.map { it.second })
|
||||
}
|
||||
@ -123,7 +127,8 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
|
||||
private fun readObjectBuildViaSetters(
|
||||
obj: List<*>,
|
||||
schemas: SerializationSchemas,
|
||||
input: DeserializationInput): Any = ifThrowsAppend({ clazz.typeName }) {
|
||||
input: DeserializationInput,
|
||||
context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
|
||||
logger.trace { "Calling setter based construction for ${clazz.typeName}" }
|
||||
|
||||
val instance: Any = javaConstructor?.newInstance() ?: throw NotSerializableException(
|
||||
@ -133,7 +138,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
|
||||
// do it in doesn't matter
|
||||
val propertiesFromBlob = obj
|
||||
.zip(propertySerializers.serializationOrder)
|
||||
.map { it.second.getter.readProperty(it.first, schemas, input) }
|
||||
.map { it.second.getter.readProperty(it.first, schemas, input, context) }
|
||||
|
||||
// one by one take a property and invoke the setter on the class
|
||||
propertySerializers.serializationOrder.zip(propertiesFromBlob).forEach {
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Binary
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
@ -19,8 +20,8 @@ import java.lang.reflect.Type
|
||||
*/
|
||||
sealed class PropertySerializer(val name: String, val propertyReader: PropertyReader, val resolvedType: Type) {
|
||||
abstract fun writeClassInfo(output: SerializationOutput)
|
||||
abstract fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int = 0)
|
||||
abstract fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any?
|
||||
abstract fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, context: SerializationContext, debugIndent: Int = 0)
|
||||
abstract fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any?
|
||||
|
||||
val type: String = generateType()
|
||||
val requires: List<String> = generateRequires()
|
||||
@ -86,12 +87,15 @@ sealed class PropertySerializer(val name: String, val propertyReader: PropertyRe
|
||||
override fun readProperty(
|
||||
obj: Any?,
|
||||
schemas: SerializationSchemas,
|
||||
input: DeserializationInput): Any? = ifThrowsAppend({ nameForDebug }) {
|
||||
input.readObjectOrNull(obj, schemas, resolvedType)
|
||||
input: DeserializationInput,
|
||||
context: SerializationContext): Any? = ifThrowsAppend({ nameForDebug }) {
|
||||
input.readObjectOrNull(obj, schemas, resolvedType, context)
|
||||
}
|
||||
|
||||
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int) = ifThrowsAppend({ nameForDebug }) {
|
||||
output.writeObjectOrNull(propertyReader.read(obj), data, resolvedType, debugIndent)
|
||||
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int) = ifThrowsAppend({ nameForDebug }
|
||||
) {
|
||||
output.writeObjectOrNull(propertyReader.read(obj), data, resolvedType, context, debugIndent)
|
||||
}
|
||||
|
||||
private val nameForDebug = "$name(${resolvedType.typeName})"
|
||||
@ -106,11 +110,15 @@ sealed class PropertySerializer(val name: String, val propertyReader: PropertyRe
|
||||
resolvedType: Type) : PropertySerializer(name, readMethod, resolvedType) {
|
||||
override fun writeClassInfo(output: SerializationOutput) {}
|
||||
|
||||
override fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? {
|
||||
override fun readProperty(obj: Any?, schemas: SerializationSchemas,
|
||||
input: DeserializationInput, context: SerializationContext
|
||||
): Any? {
|
||||
return if (obj is Binary) obj.array else obj
|
||||
}
|
||||
|
||||
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
val value = propertyReader.read(obj)
|
||||
if (value is ByteArray) {
|
||||
data.putObject(Binary(value))
|
||||
@ -122,18 +130,22 @@ sealed class PropertySerializer(val name: String, val propertyReader: PropertyRe
|
||||
|
||||
/**
|
||||
* A property serializer for the AMQP char type, needed as a specialisation as the underlying
|
||||
* value of the character is stored in numeric UTF-16 form and on deserialisation requires explicit
|
||||
* value of the character is stored in numeric UTF-16 form and on deserialization requires explicit
|
||||
* casting back to a char otherwise it's treated as an Integer and a TypeMismatch occurs
|
||||
*/
|
||||
class AMQPCharPropertySerializer(name: String, readMethod: PropertyReader) :
|
||||
PropertySerializer(name, readMethod, Character::class.java) {
|
||||
override fun writeClassInfo(output: SerializationOutput) {}
|
||||
|
||||
override fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? {
|
||||
override fun readProperty(obj: Any?, schemas: SerializationSchemas,
|
||||
input: DeserializationInput, context: SerializationContext
|
||||
): Any? {
|
||||
return if (obj == null) null else (obj as Short).toChar()
|
||||
}
|
||||
|
||||
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
val input = propertyReader.read(obj)
|
||||
if (input != null) data.putShort((input as Char).toShort()) else data.putNull()
|
||||
}
|
||||
|
@ -12,12 +12,12 @@ package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaGetter
|
||||
import kotlin.reflect.jvm.kotlinProperty
|
||||
import java.lang.reflect.Field
|
||||
|
||||
abstract class PropertyReader {
|
||||
abstract fun read(obj: Any?): Any?
|
||||
@ -151,6 +151,7 @@ class PropertyAccessorGetterSetter(
|
||||
*/
|
||||
setter.isAccessible = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the setter on the underlying object passing in the serialized value.
|
||||
*/
|
||||
@ -172,7 +173,7 @@ class PropertyAccessorConstructor(
|
||||
* calls to the explicit setter should be an error.
|
||||
*/
|
||||
override fun set(instance: Any, obj: Any?) {
|
||||
NotSerializableException ("Attempting to access a setter on an object being instantiated " +
|
||||
NotSerializableException("Attempting to access a setter on an object being instantiated " +
|
||||
"via its constructor.")
|
||||
}
|
||||
}
|
||||
@ -197,7 +198,7 @@ abstract class PropertySerializers(
|
||||
is PropertyAccessorGetterSetter -> PropertySerializersSetter(serializationOrder)
|
||||
null -> PropertySerializersNoProperties()
|
||||
else -> {
|
||||
throw NotSerializableException ("Unknown Property Accessor type, cannot create set")
|
||||
throw NotSerializableException("Unknown Property Accessor type, cannot create set")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,7 +207,7 @@ abstract class PropertySerializers(
|
||||
abstract val byConstructor: Boolean
|
||||
}
|
||||
|
||||
class PropertySerializersNoProperties : PropertySerializers (emptyList()) {
|
||||
class PropertySerializersNoProperties : PropertySerializers(emptyList()) {
|
||||
override val byConstructor get() = true
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ data class PropertyDescriptor(var field: Field?, var setter: Method?, var getter
|
||||
|
||||
constructor() : this(null, null, null, null)
|
||||
|
||||
fun preferredGetter() : Method? = getter ?: iser
|
||||
fun preferredGetter(): Method? = getter ?: iser
|
||||
}
|
||||
|
||||
object PropertyDescriptorsRegex {
|
||||
@ -173,8 +173,7 @@ fun Class<out Any?>.propertyDescriptors(): Map<String, PropertyDescriptor> {
|
||||
// fails the getter doesn't refer to a property directly, but may refer to a constructor
|
||||
// parameter that shadows a property
|
||||
val properties =
|
||||
classProperties[groups[2]!!.value] ?:
|
||||
classProperties[groups[2]!!.value.decapitalize()] ?:
|
||||
classProperties[groups[2]!!.value] ?: classProperties[groups[2]!!.value.decapitalize()] ?:
|
||||
// take into account those constructor properties that don't directly map to a named
|
||||
// property which are, by default, already added to the map
|
||||
classProperties.computeIfAbsent(groups[2]!!.value) { PropertyDescriptor() }
|
||||
@ -255,9 +254,9 @@ internal fun <T : Any> propertiesForSerializationFromConstructor(
|
||||
// We will already have disambiguated getA for property A or a but we still need to cope
|
||||
// with the case we don't know the case of A when the parameter doesn't match a property
|
||||
// but has a getter
|
||||
val matchingProperty = classProperties[name] ?: classProperties[name.capitalize()] ?:
|
||||
throw NotSerializableException(
|
||||
"Constructor parameter - \"$name\" - doesn't refer to a property of \"$clazz\"")
|
||||
val matchingProperty = classProperties[name] ?: classProperties[name.capitalize()]
|
||||
?: throw NotSerializableException(
|
||||
"Constructor parameter - \"$name\" - doesn't refer to a property of \"$clazz\"")
|
||||
|
||||
// If the property has a getter we'll use that to retrieve it's value from the instance, if it doesn't
|
||||
// *for *know* we switch to a reflection based method
|
||||
@ -277,8 +276,8 @@ internal fun <T : Any> propertiesForSerializationFromConstructor(
|
||||
|
||||
Pair(PublicPropertyReader(getter), returnType)
|
||||
} else {
|
||||
val field = classProperties[name]!!.field ?:
|
||||
throw NotSerializableException("No property matching constructor parameter named - \"$name\" - " +
|
||||
val field = classProperties[name]!!.field
|
||||
?: throw NotSerializableException("No property matching constructor parameter named - \"$name\" - " +
|
||||
"of \"$clazz\". If using Java, check that you have the -parameters option specified " +
|
||||
"in the Java compiler. Alternately, provide a proxy serializer " +
|
||||
"(SerializationCustomSerializer) if recompiling isn't an option")
|
||||
@ -325,7 +324,7 @@ fun propertiesForSerializationFromSetters(
|
||||
}
|
||||
|
||||
// Make sure the getter returns the same type (within inheritance bounds) the setter accepts.
|
||||
if (!(TypeToken.of (getter.genericReturnType).isSupertypeOf(setterType))) {
|
||||
if (!(TypeToken.of(getter.genericReturnType).isSupertypeOf(setterType))) {
|
||||
throw NotSerializableException("Defined setter for parameter ${property.value.field?.name} " +
|
||||
"takes parameter of type $setterType yet the defined getter returns a value of type " +
|
||||
"${getter.returnType} [${getter.genericReturnType}]")
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationEncoding
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.nodeapi.internal.serialization.CordaSerializationEncoding
|
||||
@ -33,7 +34,10 @@ data class BytesAndSchemas<T : Any>(
|
||||
* @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<Any, Int> = IdentityHashMap()
|
||||
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()
|
||||
internal val schemaHistory: MutableSet<TypeNotation> = LinkedHashSet()
|
||||
@ -44,19 +48,18 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
|
||||
* of AMQP serialization constructed the serialized form.
|
||||
*/
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> serialize(obj: T): SerializedBytes<T> {
|
||||
fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
||||
try {
|
||||
return _serialize(obj)
|
||||
return _serialize(obj, context)
|
||||
} finally {
|
||||
andFinally()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> serializeAndReturnSchema(obj: T): BytesAndSchemas<T> {
|
||||
fun <T : Any> serializeAndReturnSchema(obj: T, context: SerializationContext): BytesAndSchemas<T> {
|
||||
try {
|
||||
val blob = _serialize(obj)
|
||||
val blob = _serialize(obj, context)
|
||||
val schema = Schema(schemaHistory.toList())
|
||||
return BytesAndSchemas(blob, schema, TransformsSchema.build(schema, serializerFactory))
|
||||
} finally {
|
||||
@ -70,11 +73,11 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
|
||||
schemaHistory.clear()
|
||||
}
|
||||
|
||||
internal fun <T : Any> _serialize(obj: T): SerializedBytes<T> {
|
||||
internal fun <T : Any> _serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
||||
val data = Data.Factory.create()
|
||||
data.withDescribed(Envelope.DESCRIPTOR_OBJECT) {
|
||||
withList {
|
||||
writeObject(obj, this)
|
||||
writeObject(obj, this, context)
|
||||
val schema = Schema(schemaHistory.toList())
|
||||
writeSchema(schema, this)
|
||||
writeTransformSchema(TransformsSchema.build(schema, serializerFactory), this)
|
||||
@ -97,8 +100,8 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
|
||||
})
|
||||
}
|
||||
|
||||
internal fun writeObject(obj: Any, data: Data) {
|
||||
writeObject(obj, data, obj.javaClass)
|
||||
internal fun writeObject(obj: Any, data: Data, context: SerializationContext) {
|
||||
writeObject(obj, data, obj.javaClass, context)
|
||||
}
|
||||
|
||||
open fun writeSchema(schema: Schema, data: Data) {
|
||||
@ -109,15 +112,15 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
|
||||
data.putObject(transformsSchema)
|
||||
}
|
||||
|
||||
internal fun writeObjectOrNull(obj: Any?, data: Data, type: Type, debugIndent: Int) {
|
||||
internal fun writeObjectOrNull(obj: Any?, data: Data, type: Type, context: SerializationContext, debugIndent: Int) {
|
||||
if (obj == null) {
|
||||
data.putNull()
|
||||
} else {
|
||||
writeObject(obj, data, if (type == SerializerFactory.AnyType) obj.javaClass else type, debugIndent)
|
||||
writeObject(obj, data, if (type == SerializerFactory.AnyType) obj.javaClass else type, context, debugIndent)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun writeObject(obj: Any, data: Data, type: Type, debugIndent: Int = 0) {
|
||||
internal fun writeObject(obj: Any, data: Data, type: Type, context: SerializationContext, debugIndent: Int = 0) {
|
||||
val serializer = serializerFactory.get(obj.javaClass, type)
|
||||
if (serializer !in serializerHistory) {
|
||||
serializerHistory.add(serializer)
|
||||
@ -126,7 +129,7 @@ open class SerializationOutput @JvmOverloads constructor(internal val serializer
|
||||
|
||||
val retrievedRefCount = objectHistory[obj]
|
||||
if (retrievedRefCount == null) {
|
||||
serializer.writeObject(obj, data, type, this, debugIndent)
|
||||
serializer.writeObject(obj, data, type, this, context, debugIndent)
|
||||
// Important to do it after serialization such that dependent object will have preceding reference numbers
|
||||
// assigned to them first as they will be first read from the stream on receiving end.
|
||||
// Skip for primitive types as they are too small and overhead of referencing them will be much higher than their content
|
||||
|
@ -15,9 +15,11 @@ import com.google.common.reflect.TypeResolver
|
||||
import net.corda.core.internal.getStackTraceAsString
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.nodeapi.internal.serialization.carpenter.*
|
||||
import net.corda.nodeapi.internal.serialization.carpenter.CarpenterMetaSchema
|
||||
import net.corda.nodeapi.internal.serialization.carpenter.ClassCarpenter
|
||||
import net.corda.nodeapi.internal.serialization.carpenter.MetaCarpenter
|
||||
import net.corda.nodeapi.internal.serialization.carpenter.MetaCarpenterException
|
||||
import org.apache.qpid.proton.amqp.*
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.*
|
||||
@ -69,8 +71,7 @@ open class SerializerFactory(
|
||||
get() = classCarpenter.classloader
|
||||
|
||||
private fun getEvolutionSerializer(typeNotation: TypeNotation, newSerializer: AMQPSerializer<Any>,
|
||||
schemas: SerializationSchemas)
|
||||
= evolutionSerializerGetter.getEvolutionSerializer(this, typeNotation, newSerializer, schemas)
|
||||
schemas: SerializationSchemas) = evolutionSerializerGetter.getEvolutionSerializer(this, typeNotation, newSerializer, schemas)
|
||||
|
||||
fun getSerializersByDescriptor() = serializersByDescriptor
|
||||
|
||||
@ -109,7 +110,8 @@ open class SerializerFactory(
|
||||
makeMapSerializer(declaredTypeAmended)
|
||||
}
|
||||
}
|
||||
Enum::class.java.isAssignableFrom(actualClass ?: declaredClass) -> serializersByType.computeIfAbsent(actualClass ?: declaredClass) {
|
||||
Enum::class.java.isAssignableFrom(actualClass
|
||||
?: declaredClass) -> serializersByType.computeIfAbsent(actualClass ?: declaredClass) {
|
||||
whitelist.requireWhitelisted(actualType)
|
||||
EnumSerializer(actualType, actualClass ?: declaredClass, this)
|
||||
}
|
||||
@ -254,8 +256,8 @@ open class SerializerFactory(
|
||||
} catch (e: MetaCarpenterException) {
|
||||
// preserve the actual message locally
|
||||
loggerFor<SerializerFactory>().apply {
|
||||
error ("${e.message} [hint: enable trace debugging for the stack trace]")
|
||||
trace (e.getStackTraceAsString())
|
||||
error("${e.message} [hint: enable trace debugging for the stack trace]")
|
||||
trace(e.getStackTraceAsString())
|
||||
}
|
||||
|
||||
// prevent carpenter exceptions escaping into the world, convert things into a nice
|
||||
@ -293,12 +295,12 @@ open class SerializerFactory(
|
||||
} else {
|
||||
val singleton = clazz.objectInstance()
|
||||
if (singleton != null) {
|
||||
whitelist.requireWhitelisted(clazz)
|
||||
SingletonSerializer(clazz, singleton, this)
|
||||
} else {
|
||||
whitelist.requireWhitelisted(type)
|
||||
ObjectSerializer(type, this)
|
||||
}
|
||||
whitelist.requireWhitelisted(clazz)
|
||||
SingletonSerializer(clazz, singleton, this)
|
||||
} else {
|
||||
whitelist.requireWhitelisted(type)
|
||||
ObjectSerializer(type, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
@ -33,13 +34,16 @@ class SingletonSerializer(override val type: Class<*>, val singleton: Any, facto
|
||||
output.writeTypeNotations(typeNotation)
|
||||
}
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, debugIndent: Int) {
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext, debugIndent: Int
|
||||
) {
|
||||
data.withDescribed(typeNotation.descriptor) {
|
||||
data.putBoolean(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any {
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext
|
||||
): Any {
|
||||
return singleton
|
||||
}
|
||||
}
|
@ -224,8 +224,8 @@ data class TransformsSchema(val types: Map<String, EnumMap<TransformTypes, Mutab
|
||||
// ignore them it feels like a good thing to alert the user to since this is
|
||||
// more than likely a typo in their code so best make it an actual error
|
||||
if (transforms.computeIfAbsent(transform.enum) { mutableListOf() }
|
||||
.filter { t == it }
|
||||
.isNotEmpty()) {
|
||||
.filter { t == it }
|
||||
.isNotEmpty()) {
|
||||
throw NotSerializableException(
|
||||
"Repeated unique transformation annotation of type ${t.name}")
|
||||
}
|
||||
@ -284,12 +284,12 @@ data class TransformsSchema(val types: Map<String, EnumMap<TransformTypes, Mutab
|
||||
throw NotSerializableException("Unexpected descriptor ${describedType.descriptor}.")
|
||||
}
|
||||
|
||||
val map = describedType.described as? 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, MutableList<Transform>>(TransformTypes::class.java)
|
||||
|
||||
@ -298,8 +298,8 @@ data class TransformsSchema(val types: Map<String, EnumMap<TransformTypes, Mutab
|
||||
|
||||
rtn[fingerprint]!![transform] = mutableListOf()
|
||||
(transforms as List<*>).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}")
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import net.corda.nodeapi.internal.serialization.amqp.custom.ClassSerializer.ClassProxy
|
||||
|
||||
/**
|
||||
* A serializer for [Class] that uses [ClassProxy] proxy object to write out
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.amqp.Binary
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -25,7 +26,9 @@ object InputStreamSerializer : CustomSerializer.Implements<InputStream>(InputStr
|
||||
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
|
||||
|
||||
override fun writeDescribedObject(obj: InputStream, data: Data, type: Type, output: SerializationOutput) {
|
||||
override fun writeDescribedObject(obj: InputStream, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext
|
||||
) {
|
||||
val startingSize = maxOf(4096, obj.available() + 1)
|
||||
var buffer = ByteArray(startingSize)
|
||||
var pos = 0
|
||||
@ -44,8 +47,10 @@ object InputStreamSerializer : CustomSerializer.Implements<InputStream>(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()
|
||||
}
|
||||
}
|
@ -12,12 +12,15 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.MonthDay
|
||||
|
||||
/**
|
||||
* A serializer for [MonthDay] that uses a proxy object to write out the integer form.
|
||||
*/
|
||||
class MonthDaySerializer(factory: SerializerFactory) : CustomSerializer.Proxy<MonthDay, MonthDaySerializer.MonthDayProxy>(MonthDay::class.java, MonthDayProxy::class.java, factory) {
|
||||
class MonthDaySerializer(factory: SerializerFactory)
|
||||
: CustomSerializer.Proxy<MonthDay, MonthDaySerializer.MonthDayProxy>(
|
||||
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())
|
||||
|
@ -12,7 +12,9 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.LocalDateTime
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* A serializer for [OffsetDateTime] that uses a proxy object to write out the date and zone offset.
|
||||
|
@ -12,7 +12,9 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.LocalTime
|
||||
import java.time.OffsetTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* A serializer for [OffsetTime] that uses a proxy object to write out the time and zone offset.
|
||||
|
@ -12,7 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.Period
|
||||
|
||||
/**
|
||||
* A serializer for [Period] that uses a proxy object to write out the integer form.
|
||||
|
@ -11,7 +11,9 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.*
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.Checkpoint
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.Storage
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import net.corda.nodeapi.internal.serialization.checkUseCase
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -25,13 +27,17 @@ object PrivateKeySerializer : CustomSerializer.Implements<PrivateKey>(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)
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
@ -22,13 +23,17 @@ import java.security.PublicKey
|
||||
object PublicKeySerializer : CustomSerializer.Implements<PublicKey>(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)
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -26,12 +27,16 @@ object X509CRLSerializer : CustomSerializer.Implements<X509CRL>(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
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
@ -26,12 +27,16 @@ object X509CertificateSerializer : CustomSerializer.Implements<X509Certificate>(
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.YearMonth
|
||||
|
||||
/**
|
||||
* A serializer for [YearMonth] that uses a proxy object to write out the integer form.
|
||||
|
@ -12,7 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.Year
|
||||
|
||||
/**
|
||||
* A serializer for [Year] that uses a proxy object to write out the integer form.
|
||||
|
@ -12,7 +12,10 @@ package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
|
||||
import java.time.*
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
/**
|
||||
* A serializer for [ZonedDateTime] that uses a proxy object to write out the date, time, offset and zone.
|
||||
|
@ -12,11 +12,11 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.carpenter
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.nodeapi.internal.serialization.amqp.CompositeType
|
||||
import net.corda.nodeapi.internal.serialization.amqp.RestrictedType
|
||||
import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField
|
||||
import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
|
||||
fun AMQPSchema.carpenterSchema(classloader: ClassLoader): CarpenterMetaSchema {
|
||||
val rtn = CarpenterMetaSchema.newInstance()
|
||||
@ -130,7 +130,7 @@ val typeStrToType: Map<Pair<String, Boolean>, Class<out Any?>> = 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
|
||||
|
||||
|
@ -36,11 +36,11 @@ class CarpenterClassLoader(parentClassLoader: ClassLoader = Thread.currentThread
|
||||
fun load(name: String, bytes: ByteArray) = defineClass(name, bytes, 0, bytes.size)
|
||||
}
|
||||
|
||||
class InterfaceMismatchNonGetterException (val clazz: Class<*>, val method: Method) : InterfaceMismatchException(
|
||||
"Requested interfaces must consist only of methods that start with 'get': ${clazz.name}.${method.name}")
|
||||
class InterfaceMismatchNonGetterException(val clazz: Class<*>, val method: Method) : InterfaceMismatchException(
|
||||
"Requested interfaces must consist only of methods that start with 'get': ${clazz.name}.${method.name}")
|
||||
|
||||
class InterfaceMismatchMissingAMQPFieldException (val clazz: Class<*>, val field: String) : InterfaceMismatchException(
|
||||
"Interface ${clazz.name} requires a field named $field but that isn't found in the schema or any superclass schemas")
|
||||
class InterfaceMismatchMissingAMQPFieldException(val clazz: Class<*>, val field: String) : InterfaceMismatchException(
|
||||
"Interface ${clazz.name} requires a field named $field but that isn't found in the schema or any superclass schemas")
|
||||
|
||||
/**
|
||||
* Which version of the java runtime are we constructing objects against
|
||||
|
@ -19,18 +19,18 @@ import org.objectweb.asm.Type
|
||||
abstract class ClassCarpenterException(msg: String) : CordaRuntimeException(msg)
|
||||
|
||||
/**
|
||||
* Thrown by the [ClassCarpenter] when trying to build
|
||||
* Thrown by the [ClassCarpenter] when trying to build
|
||||
*/
|
||||
abstract class InterfaceMismatchException(msg: String) : ClassCarpenterException(msg)
|
||||
|
||||
class DuplicateNameException(val name : String) : ClassCarpenterException (
|
||||
class DuplicateNameException(val name: String) : ClassCarpenterException(
|
||||
"An attempt was made to register two classes with the name '$name' within the same ClassCarpenter namespace.")
|
||||
|
||||
class NullablePrimitiveException(val name: String, val field: Class<out Any>) : 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
|
||||
|
@ -268,7 +268,7 @@ object NotaryChangeWireTransactionSerializer : Serializer<NotaryChangeWireTransa
|
||||
}
|
||||
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<NotaryChangeWireTransaction>): NotaryChangeWireTransaction {
|
||||
val components : List<OpaqueBytes> = uncheckedCast(kryo.readClassAndObject(input))
|
||||
val components: List<OpaqueBytes> = uncheckedCast(kryo.readClassAndObject(input))
|
||||
return NotaryChangeWireTransaction(components)
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.kryo
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import co.paralleluniverse.fibers.Fiber
|
||||
import co.paralleluniverse.io.serialization.kryo.KryoSerializer
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
@ -22,14 +21,14 @@ import com.esotericsoftware.kryo.io.Output
|
||||
import com.esotericsoftware.kryo.pool.KryoPool
|
||||
import com.esotericsoftware.kryo.serializers.ClosureSerializer
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
||||
import net.corda.nodeapi.internal.serialization.CordaClassResolver
|
||||
import net.corda.nodeapi.internal.serialization.SectionId
|
||||
import net.corda.nodeapi.internal.serialization.SerializationScheme
|
||||
import net.corda.nodeapi.internal.serialization.*
|
||||
import net.corda.nodeapi.internal.serialization.SectionId
|
||||
import java.security.PublicKey
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
val kryoMagic = CordaSerializationMagic("corda".toByteArray() + byteArrayOf(0, 0))
|
||||
|
||||
@ -96,7 +95,8 @@ abstract class AbstractKryoSerializationScheme : SerializationScheme {
|
||||
}
|
||||
|
||||
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, 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
|
||||
|
@ -13,7 +13,10 @@ package net.corda.nodeapi.internal.serialization.kryo
|
||||
import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
import net.corda.core.internal.LazyPool
|
||||
import java.io.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.SequenceInputStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
class ByteBufferOutputStream(size: Int) : ByteArrayOutputStream(size) {
|
||||
|
@ -24,12 +24,16 @@ import net.corda.core.serialization.SerializeAsToken
|
||||
*/
|
||||
class SerializeAsTokenSerializer<T : SerializeAsToken> : Serializer<T>() {
|
||||
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>): 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}")
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp;
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist;
|
||||
import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
|
||||
import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContextKt;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
@ -51,7 +53,7 @@ public class ErrorMessageTests {
|
||||
|
||||
SerializationOutput ser = new SerializationOutput(factory1);
|
||||
|
||||
Assertions.assertThatThrownBy(() -> ser.serialize(new C(1)))
|
||||
Assertions.assertThatThrownBy(() -> ser.serialize(new C(1), TestSerializationContext.testSerializationContext))
|
||||
.isInstanceOf(NotSerializableException.class)
|
||||
.hasMessage(errMsg("a", getClass().getName()));
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp;
|
||||
|
||||
import net.corda.core.serialization.SerializedBytes;
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist;
|
||||
import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
|
||||
import org.junit.Test;
|
||||
import java.io.NotSerializableException;
|
||||
|
||||
@ -43,10 +44,10 @@ public class JavaGenericsTest {
|
||||
new SerializerFingerPrinter());
|
||||
|
||||
SerializationOutput ser = new SerializationOutput(factory);
|
||||
SerializedBytes<?> bytes = ser.serialize(a1);
|
||||
SerializedBytes<?> bytes = ser.serialize(a1, TestSerializationContext.testSerializationContext);
|
||||
|
||||
DeserializationInput des = new DeserializationInput(factory);
|
||||
A a2 = des.deserialize(bytes, A.class);
|
||||
A a2 = des.deserialize(bytes, A.class, TestSerializationContext.testSerializationContext);
|
||||
|
||||
assertEquals(1, a2.getT());
|
||||
}
|
||||
@ -58,13 +59,13 @@ public class JavaGenericsTest {
|
||||
new EvolutionSerializerGetter(),
|
||||
new SerializerFingerPrinter());
|
||||
|
||||
return (new SerializationOutput(factory)).serialize(a);
|
||||
return (new SerializationOutput(factory)).serialize(a, TestSerializationContext.testSerializationContext);
|
||||
}
|
||||
|
||||
private SerializedBytes<?> forceWildcardSerializeFactory(
|
||||
A<?> a,
|
||||
SerializerFactory factory) throws NotSerializableException {
|
||||
return (new SerializationOutput(factory)).serialize(a);
|
||||
return (new SerializationOutput(factory)).serialize(a, TestSerializationContext.testSerializationContext);
|
||||
}
|
||||
|
||||
private A<?> forceWildcardDeserialize(SerializedBytes<?> bytes) throws NotSerializableException {
|
||||
@ -75,13 +76,14 @@ public class JavaGenericsTest {
|
||||
new SerializerFingerPrinter());
|
||||
|
||||
DeserializationInput des = new DeserializationInput(factory);
|
||||
return des.deserialize(bytes, A.class);
|
||||
return des.deserialize(bytes, A.class, TestSerializationContext.testSerializationContext);
|
||||
}
|
||||
|
||||
private A<?> forceWildcardDeserializeFactory(
|
||||
SerializedBytes<?> bytes,
|
||||
SerializerFactory factory) throws NotSerializableException {
|
||||
return (new DeserializationInput(factory)).deserialize(bytes, A.class);
|
||||
return (new DeserializationInput(factory)).deserialize(bytes, A.class,
|
||||
TestSerializationContext.testSerializationContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<ContractState> (new DummyState()))).isInstanceOf(
|
||||
Assertions.assertThatThrownBy(() -> ser.serialize(new TemplateWrapper<ContractState> (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf(
|
||||
NotSerializableException.class).hasMessageContaining(
|
||||
"has synthetic fields and is likely a nested inner class");
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp;
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist;
|
||||
import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -93,7 +94,7 @@ public class JavaPrivatePropertyTests {
|
||||
DeserializationInput des = new DeserializationInput(factory);
|
||||
|
||||
B b = new B(true);
|
||||
B b2 = des.deserialize(ser.serialize(b), B.class);
|
||||
B b2 = des.deserialize(ser.serialize(b, TestSerializationContext.testSerializationContext), B.class, TestSerializationContext.testSerializationContext);
|
||||
assertEquals (b.b, b2.b);
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ public class JavaPrivatePropertyTests {
|
||||
|
||||
B2 b = new B2();
|
||||
b.setB(false);
|
||||
B2 b2 = des.deserialize(ser.serialize(b), B2.class);
|
||||
B2 b2 = des.deserialize(ser.serialize(b, TestSerializationContext.testSerializationContext), B2.class, TestSerializationContext.testSerializationContext);
|
||||
assertEquals (b.b, b2.b);
|
||||
}
|
||||
|
||||
@ -122,7 +123,7 @@ public class JavaPrivatePropertyTests {
|
||||
|
||||
B3 b = new B3();
|
||||
b.setB(false);
|
||||
B3 b2 = des.deserialize(ser.serialize(b), B3.class);
|
||||
B3 b2 = des.deserialize(ser.serialize(b, TestSerializationContext.testSerializationContext), B3.class, TestSerializationContext.testSerializationContext);
|
||||
|
||||
// since we can't find a getter for b (isb != isB) then we won't serialize that parameter
|
||||
assertEquals (null, b2.b);
|
||||
@ -138,7 +139,7 @@ public class JavaPrivatePropertyTests {
|
||||
|
||||
C3 c = new C3();
|
||||
c.setA(12345);
|
||||
C3 c2 = des.deserialize(ser.serialize(c), C3.class);
|
||||
C3 c2 = des.deserialize(ser.serialize(c, TestSerializationContext.testSerializationContext), C3.class, TestSerializationContext.testSerializationContext);
|
||||
|
||||
assertEquals (c.a, c2.a);
|
||||
}
|
||||
@ -153,7 +154,7 @@ public class JavaPrivatePropertyTests {
|
||||
DeserializationInput des = new DeserializationInput(factory);
|
||||
|
||||
C c = new C("dripping taps");
|
||||
C c2 = des.deserialize(ser.serialize(c), C.class);
|
||||
C c2 = des.deserialize(ser.serialize(c, TestSerializationContext.testSerializationContext), C.class, TestSerializationContext.testSerializationContext);
|
||||
|
||||
assertEquals (c.a, c2.a);
|
||||
|
||||
@ -185,7 +186,7 @@ public class JavaPrivatePropertyTests {
|
||||
DeserializationInput des = new DeserializationInput(factory);
|
||||
|
||||
C2 c = new C2("dripping taps");
|
||||
C2 c2 = des.deserialize(ser.serialize(c), C2.class);
|
||||
C2 c2 = des.deserialize(ser.serialize(c, TestSerializationContext.testSerializationContext), C2.class, TestSerializationContext.testSerializationContext);
|
||||
|
||||
assertEquals (c.a, c2.a);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal.serialization.amqp;
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist;
|
||||
@ -43,6 +44,6 @@ public class JavaSerialiseEnumTests {
|
||||
new EvolutionSerializerGetter(),
|
||||
new SerializerFingerPrinter());
|
||||
SerializationOutput ser = new SerializationOutput(factory1);
|
||||
SerializedBytes<Object> bytes = ser.serialize(bra);
|
||||
SerializedBytes<Object> bytes = ser.serialize(bra, TestSerializationContext.testSerializationContext);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,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;
|
||||
@ -199,7 +200,7 @@ public class JavaSerializationOutputTests {
|
||||
evolutionSerialiserGetter,
|
||||
fingerPrinter);
|
||||
SerializationOutput ser = new SerializationOutput(factory1);
|
||||
SerializedBytes<Object> bytes = ser.serialize(obj);
|
||||
SerializedBytes<Object> bytes = ser.serialize(obj, TestSerializationContext.testSerializationContext);
|
||||
|
||||
DecoderImpl decoder = new DecoderImpl();
|
||||
|
||||
@ -219,13 +220,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;
|
||||
|
@ -13,6 +13,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;
|
||||
|
||||
@ -142,9 +143,9 @@ public class ListsSerializationJavaTest {
|
||||
evolutionSerializerGetter,
|
||||
fingerPrinter);
|
||||
SerializationOutput ser = new SerializationOutput(factory1);
|
||||
SerializedBytes<Object> bytes = ser.serialize(container);
|
||||
SerializedBytes<Object> 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);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ package net.corda.nodeapi.internal.serialization.amqp;
|
||||
|
||||
import net.corda.core.serialization.SerializedBytes;
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist;
|
||||
import net.corda.nodeapi.internal.serialization.amqp.testutils.TestSerializationContext;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
@ -142,7 +143,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());
|
||||
|
||||
@ -157,7 +158,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());
|
||||
@ -174,7 +175,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());
|
||||
@ -190,7 +191,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());
|
||||
@ -222,9 +223,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);
|
||||
@ -234,8 +235,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);
|
||||
@ -249,8 +250,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);
|
||||
|
||||
@ -263,8 +265,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);
|
||||
@ -290,8 +295,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);
|
||||
@ -300,7 +307,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(
|
||||
@ -313,12 +320,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(
|
||||
@ -331,7 +339,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);
|
||||
}
|
||||
|
||||
@ -357,6 +366,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);
|
||||
}
|
||||
}
|
||||
|
@ -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<Object, Object> serializationProperties = new HashMap<Object, Object>();
|
||||
|
||||
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);
|
||||
}
|
@ -13,9 +13,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)
|
||||
|
@ -11,10 +11,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
|
||||
|
@ -10,9 +10,15 @@
|
||||
|
||||
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 {
|
||||
|
@ -11,9 +11,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 {
|
||||
|
@ -11,9 +11,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
|
||||
|
@ -15,6 +15,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 {
|
||||
|
@ -10,8 +10,12 @@
|
||||
|
||||
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
|
||||
|
@ -11,6 +11,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
|
||||
@ -20,6 +22,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")
|
||||
|
@ -14,6 +14,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
|
||||
@ -22,6 +24,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
|
||||
|
@ -13,12 +13,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 {
|
||||
|
@ -10,10 +10,17 @@
|
||||
|
||||
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 {
|
||||
|
@ -18,6 +18,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
|
||||
@ -28,6 +30,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
|
||||
//
|
||||
|
@ -14,6 +14,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
|
||||
|
@ -17,12 +17,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
|
||||
@ -311,7 +307,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
|
||||
|
@ -23,11 +23,15 @@ class OverridePKSerializerTest {
|
||||
class SerializerTestException(message: String) : Exception(message)
|
||||
|
||||
class TestPublicKeySerializer : CustomSerializer.Implements<PublicKey>(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")
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,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()
|
||||
|
@ -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
|
||||
|
@ -33,6 +33,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
|
||||
@ -490,12 +491,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")
|
||||
}
|
||||
|
||||
@ -660,14 +661,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)
|
||||
|
@ -11,6 +11,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
|
||||
@ -18,6 +20,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 {
|
||||
|
@ -10,10 +10,13 @@
|
||||
|
||||
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
|
||||
|
@ -20,6 +20,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")
|
||||
|
||||
|
@ -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 <reified T : Any> DeserializationInput.deserializeAndReturnEnvelope(
|
||||
bytes: SerializedBytes<T>,
|
||||
context: SerializationContext? = null
|
||||
) : ObjectAndEnvelope<T> {
|
||||
return deserializeAndReturnEnvelope(bytes, T::class.java,
|
||||
context ?: testSerializationContext)
|
||||
}
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline fun <reified T : Any> DeserializationInput.deserialize(
|
||||
bytes: SerializedBytes<T>,
|
||||
context: SerializationContext? = null
|
||||
) : T = deserialize(bytes, T::class.java, context ?: testSerializationContext)
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> SerializationOutput.serializeAndReturnSchema(
|
||||
obj: T, context: SerializationContext? = null
|
||||
): BytesAndSchemas<T> = serializeAndReturnSchema(obj, context ?: testSerializationContext)
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> SerializationOutput.serialize(obj: T): SerializedBytes<T> {
|
||||
try {
|
||||
return _serialize(obj, testSerializationContext)
|
||||
} finally {
|
||||
andFinally()
|
||||
}
|
||||
}
|
@ -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<Any, Any> = mutableMapOf()
|
||||
|
||||
val testSerializationContext = SerializationContextImpl(
|
||||
preferredSerializationVersion = amqpMagic,
|
||||
deserializationClassLoader = ClassLoader.getSystemClassLoader(),
|
||||
whitelist = AllWhitelist,
|
||||
properties = serializationProperties,
|
||||
objectReferencesEnabled = false,
|
||||
useCase = SerializationContext.UseCase.Testing,
|
||||
encoding = null)
|
@ -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)
|
||||
|
@ -14,7 +14,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"
|
||||
|
||||
|
@ -18,6 +18,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_ {
|
||||
|
@ -15,6 +15,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 {
|
||||
|
@ -17,6 +17,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) {
|
||||
|
||||
|
@ -16,6 +16,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
|
||||
|
Reference in New Issue
Block a user