mirror of
https://github.com/corda/corda.git
synced 2025-01-18 02:39:51 +00:00
Add secondry deserializer to return amqp envelope
Useful for testing the carpenter by giving access to a cosntructed envelope rather than manually building one every time
This commit is contained in:
parent
ecc96b29b0
commit
04d7432622
@ -11,6 +11,9 @@ import java.lang.reflect.Type
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
|
||||
|
||||
data class classAndEnvelope<T>(val obj: T, val envelope: Envelope)
|
||||
|
||||
/**
|
||||
* Main entry point for deserializing an AMQP encoded object.
|
||||
*
|
||||
@ -57,7 +60,44 @@ class DeserializationInput(internal val serializerFactory: SerializerFactory = S
|
||||
}
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline fun <reified T : Any> deserialize(bytes: SerializedBytes<T>): T = deserialize(bytes, T::class.java)
|
||||
inline fun <reified T : Any> deserialize(bytes: SerializedBytes<T>): T =
|
||||
deserialize(bytes, T::class.java)
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
inline fun <reified T : Any> deserializeAndReturnEnvelope(bytes: SerializedBytes<T>): classAndEnvelope<T> =
|
||||
deserializeAndReturnEnvelope(bytes, T::class.java)
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> getEnvelope(bytes: SerializedBytes<T>): Envelope {
|
||||
// Check that the lead bytes match expected header
|
||||
if (!subArraysEqual(bytes.bytes, 0, 8, AmqpHeaderV1_0.bytes, 0)) {
|
||||
throw NotSerializableException("Serialization header does not match.")
|
||||
}
|
||||
|
||||
val data = Data.Factory.create()
|
||||
val size = data.decode(ByteBuffer.wrap(bytes.bytes, 8, bytes.size - 8))
|
||||
if (size.toInt() != bytes.size - 8) {
|
||||
throw NotSerializableException("Unexpected size of data")
|
||||
}
|
||||
|
||||
return Envelope.get(data)
|
||||
}
|
||||
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any, R> des(bytes: SerializedBytes<T>, clazz: Class<T>, generator: (SerializedBytes<T>, Class<T>) -> R): R {
|
||||
try {
|
||||
return generator(bytes, clazz)
|
||||
} catch(nse: NotSerializableException) {
|
||||
throw nse
|
||||
} catch(t: Throwable) {
|
||||
throw NotSerializableException("Unexpected throwable: ${t.message} ${Throwables.getStackTraceAsString(t)}")
|
||||
} finally {
|
||||
objectHistory.clear()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main entry point for deserialization of AMQP payloads, and expects a byte sequence involving a header
|
||||
@ -66,25 +106,18 @@ class DeserializationInput(internal val serializerFactory: SerializerFactory = S
|
||||
*/
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> deserialize(bytes: SerializedBytes<T>, clazz: Class<T>): T {
|
||||
try {
|
||||
// Check that the lead bytes match expected header
|
||||
if (!subArraysEqual(bytes.bytes, 0, 8, AmqpHeaderV1_0.bytes, 0)) {
|
||||
throw NotSerializableException("Serialization header does not match.")
|
||||
}
|
||||
val data = Data.Factory.create()
|
||||
val size = data.decode(ByteBuffer.wrap(bytes.bytes, 8, bytes.size - 8))
|
||||
if (size.toInt() != bytes.size - 8) {
|
||||
throw NotSerializableException("Unexpected size of data")
|
||||
}
|
||||
val envelope = Envelope.get(data)
|
||||
return des<T, T>(bytes, clazz) { bytes, clazz ->
|
||||
var envelope = getEnvelope(bytes)
|
||||
clazz.cast(readObjectOrNull(envelope.obj, envelope.schema, clazz))
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> deserializeAndReturnEnvelope(bytes: SerializedBytes<T>, clazz: Class<T>): classAndEnvelope<T> {
|
||||
return des<T, classAndEnvelope<T>>(bytes, clazz) { bytes, clazz ->
|
||||
val envelope = getEnvelope(bytes)
|
||||
// Now pick out the obj and schema from the envelope.
|
||||
return clazz.cast(readObjectOrNull(envelope.obj, envelope.schema, clazz))
|
||||
} catch(nse: NotSerializableException) {
|
||||
throw nse
|
||||
} catch(t: Throwable) {
|
||||
throw NotSerializableException("Unexpected throwable: ${t.message} ${Throwables.getStackTraceAsString(t)}")
|
||||
} finally {
|
||||
objectHistory.clear()
|
||||
classAndEnvelope(clazz.cast(readObjectOrNull(envelope.obj, envelope.schema, clazz)), envelope)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,4 +142,4 @@ class DeserializationInput(internal val serializerFactory: SerializerFactory = S
|
||||
return obj
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package net.corda.core.serialization.amqp
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
|
||||
class DeserializeAndReturnEnvelope {
|
||||
|
||||
fun testName() = Thread.currentThread().stackTrace[2].methodName
|
||||
inline fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
||||
|
||||
@Test
|
||||
fun oneType() {
|
||||
data class A(val a: Int, val b: String)
|
||||
|
||||
val a = A(10, "20")
|
||||
|
||||
var factory = SerializerFactory()
|
||||
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
|
||||
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
|
||||
|
||||
assertTrue(obj.obj is A)
|
||||
assertEquals(1, obj.envelope.schema.types.size)
|
||||
assertEquals(classTestName("A"), obj.envelope.schema.types.first().name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun twoTypes() {
|
||||
data class A(val a: Int, val b: String)
|
||||
data class B(val a: A, val b: Float)
|
||||
|
||||
val b = B(A(10, "20"), 30.0F)
|
||||
|
||||
var factory = SerializerFactory()
|
||||
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
|
||||
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
|
||||
|
||||
assertTrue(obj.obj is B)
|
||||
assertEquals(2, obj.envelope.schema.types.size)
|
||||
assertNotEquals(null, obj.envelope.schema.types.find { it.name == classTestName("A") })
|
||||
assertNotEquals(null, obj.envelope.schema.types.find { it.name == classTestName("B") })
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user