mirror of
https://github.com/corda/corda.git
synced 2025-02-21 17:56:54 +00:00
Merge pull request #1349 from corda/feature/kat/serialiseWithEnvelopeReturn
Add alt serialise method that returns the schema and the bytes
This commit is contained in:
commit
76ffd485ac
@ -8,6 +8,7 @@ import java.nio.ByteBuffer
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.LinkedHashSet
|
import kotlin.collections.LinkedHashSet
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point for serializing an object to AMQP.
|
* Main entry point for serializing an object to AMQP.
|
||||||
*
|
*
|
||||||
@ -18,37 +19,46 @@ open class SerializationOutput(internal val serializerFactory: SerializerFactory
|
|||||||
// TODO: we're not supporting object refs yet
|
// TODO: we're not supporting object refs yet
|
||||||
private val objectHistory: MutableMap<Any, Int> = IdentityHashMap()
|
private val objectHistory: MutableMap<Any, Int> = IdentityHashMap()
|
||||||
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()
|
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()
|
||||||
private val schemaHistory: MutableSet<TypeNotation> = LinkedHashSet()
|
internal val schemaHistory: MutableSet<TypeNotation> = LinkedHashSet()
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the given object to AMQP, wrapped in our [Envelope] wrapper which carries an AMQP 1.0 schema, and prefixed
|
* Serialize the given object to AMQP, wrapped in our [Envelope] wrapper which carries an AMQP 1.0 schema, and prefixed
|
||||||
* with a header to indicate that this is serialized with AMQP and not [Kryo], and what version of the Corda implementation
|
* with a header to indicate that this is serialized with AMQP and not [Kryo], and what version of the Corda implementation
|
||||||
* of AMQP serialization contructed the serialized form.
|
* of AMQP serialization constructed the serialized form.
|
||||||
*/
|
*/
|
||||||
@Throws(NotSerializableException::class)
|
@Throws(NotSerializableException::class)
|
||||||
fun <T : Any> serialize(obj: T): SerializedBytes<T> {
|
fun <T : Any> serialize(obj: T): SerializedBytes<T> {
|
||||||
try {
|
try {
|
||||||
val data = Data.Factory.create()
|
return _serialize(obj)
|
||||||
data.withDescribed(Envelope.DESCRIPTOR_OBJECT) {
|
|
||||||
withList {
|
|
||||||
// Our object
|
|
||||||
writeObject(obj, this)
|
|
||||||
// The schema
|
|
||||||
writeSchema(Schema(schemaHistory.toList()), this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val bytes = ByteArray(data.encodedSize().toInt() + 8)
|
|
||||||
val buf = ByteBuffer.wrap(bytes)
|
|
||||||
buf.put(AmqpHeaderV1_0.bytes)
|
|
||||||
data.encode(buf)
|
|
||||||
return SerializedBytes(bytes)
|
|
||||||
} finally {
|
} finally {
|
||||||
objectHistory.clear()
|
andFinally()
|
||||||
serializerHistory.clear()
|
|
||||||
schemaHistory.clear()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun andFinally() {
|
||||||
|
objectHistory.clear()
|
||||||
|
serializerHistory.clear()
|
||||||
|
schemaHistory.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : Any> _serialize(obj: T): SerializedBytes<T> {
|
||||||
|
val data = Data.Factory.create()
|
||||||
|
data.withDescribed(Envelope.DESCRIPTOR_OBJECT) {
|
||||||
|
withList {
|
||||||
|
// Our object
|
||||||
|
writeObject(obj, this)
|
||||||
|
// The schema
|
||||||
|
writeSchema(Schema(schemaHistory.toList()), this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val bytes = ByteArray(data.encodedSize().toInt() + 8)
|
||||||
|
val buf = ByteBuffer.wrap(bytes)
|
||||||
|
buf.put(AmqpHeaderV1_0.bytes)
|
||||||
|
data.encode(buf)
|
||||||
|
return SerializedBytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun writeObject(obj: Any, data: Data) {
|
internal fun writeObject(obj: Any, data: Data) {
|
||||||
writeObject(obj, data, obj.javaClass)
|
writeObject(obj, data, obj.javaClass)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package net.corda.nodeapi.internal.serialization.amqp
|
package net.corda.nodeapi.internal.serialization.amqp
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import org.apache.qpid.proton.codec.Data
|
import org.apache.qpid.proton.codec.Data
|
||||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||||
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
|
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
|
||||||
|
import java.io.NotSerializableException
|
||||||
|
|
||||||
|
|
||||||
fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||||
fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())
|
fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())
|
||||||
@ -17,3 +20,18 @@ class TestSerializationOutput(
|
|||||||
super.writeSchema(schema, data)
|
super.writeSchema(schema, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testName(): String = Thread.currentThread().stackTrace[2].methodName
|
||||||
|
|
||||||
|
data class BytesAndSchema<T : Any>(val obj: SerializedBytes<T>, val schema: Schema)
|
||||||
|
|
||||||
|
// Extension for the serialize routine that returns the scheme encoded into the
|
||||||
|
// bytes as well as the bytes for simple testing
|
||||||
|
@Throws(NotSerializableException::class)
|
||||||
|
fun <T : Any> SerializationOutput.serializeAndReturnSchema(obj: T): BytesAndSchema<T> {
|
||||||
|
try {
|
||||||
|
return BytesAndSchema(_serialize(obj), Schema(schemaHistory.toList()))
|
||||||
|
} finally {
|
||||||
|
andFinally()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,11 +7,9 @@ import kotlin.test.assertNotEquals
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class DeserializeAndReturnEnvelopeTests {
|
class DeserializeAndReturnEnvelopeTests {
|
||||||
|
// the 'this' reference means we can't just move this to the common test utils
|
||||||
fun testName(): String = Thread.currentThread().stackTrace[2].methodName
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
inline private fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun oneType() {
|
fun oneType() {
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.corda.nodeapi.internal.serialization.amqp
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class SerializeAndReturnSchemaTest {
|
||||||
|
// the 'this' reference means we can't just move this to the common test utils
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline private fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
||||||
|
|
||||||
|
val factory = testDefaultFactory()
|
||||||
|
|
||||||
|
// just a simple test to verify the internal test extension for serialize does
|
||||||
|
// indeed give us the correct schema back. This is more useful in support of other
|
||||||
|
// tests rather than by itself but for those to be reliable this also needs
|
||||||
|
// testing
|
||||||
|
@Test
|
||||||
|
fun getSchema() {
|
||||||
|
data class C(val a: Int, val b: Int)
|
||||||
|
val a = 1
|
||||||
|
val b = 2
|
||||||
|
|
||||||
|
val sc = SerializationOutput(factory).serializeAndReturnSchema(C(a, b))
|
||||||
|
|
||||||
|
assertEquals(1, sc.schema.types.size)
|
||||||
|
assertEquals(classTestName("C"), sc.schema.types.first().name)
|
||||||
|
assertTrue(sc.schema.types.first() is CompositeType)
|
||||||
|
assertEquals(2, (sc.schema.types.first() as CompositeType).fields.size)
|
||||||
|
assertNotNull((sc.schema.types.first() as CompositeType).fields.find { it.name == "a" })
|
||||||
|
assertNotNull((sc.schema.types.first() as CompositeType).fields.find { it.name == "b" })
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user