mirror of
https://github.com/corda/corda.git
synced 2024-12-24 07:06:44 +00:00
Ability to write single outer schema. Some groundwork for using Descriptor code for custom serializers (but lots of places still do descriptor?.name, which needs replacing with a toShortString() implementation)
This commit is contained in:
parent
3332973183
commit
84bf3d5639
@ -397,7 +397,7 @@ fun SerializationContext.withWhitelist(classes: List<Class<*>>): SerializationCo
|
||||
|
||||
// EXPERIMENTAL
|
||||
@KeepForDJVM
|
||||
class ExternalSchema()
|
||||
data class ExternalSchema(val flush: Boolean = false, val externalSchemaForDeserialization: Any? = null, val typeNotations: MutableList<List<Any>> = ArrayList())
|
||||
|
||||
@KeepForDJVM
|
||||
class IntegerFingerprints() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.finance.flows
|
||||
|
||||
import net.corda.core.serialization.ExternalSchema
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.SerializationFactory
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
@ -59,14 +60,15 @@ class CompatibilityTest {
|
||||
assertEquals(1, commands.size)
|
||||
assertTrue(commands.first().value is Cash.Commands.Issue)
|
||||
|
||||
val context = SerializationDefaults.STORAGE_CONTEXT.withExternalSchema(ExternalSchema()).withIntegerFingerprint()
|
||||
val newWtx = SerializationFactory.defaultFactory.asCurrent {
|
||||
withCurrentContext(SerializationDefaults.STORAGE_CONTEXT) {
|
||||
withCurrentContext(context) {
|
||||
WireTransaction(transaction.tx.componentGroups.map { cg: ComponentGroup ->
|
||||
ComponentGroup(cg.groupIndex, cg.components.map { bytes ->
|
||||
val componentInput = DeserializationInput(serializerFactory)
|
||||
val component = componentInput.deserialize(SerializedBytes<Any>(bytes.bytes), SerializationDefaults.STORAGE_CONTEXT)
|
||||
val componentOutput = SerializationOutput(serializerFactory)
|
||||
val componentOutputBytes = componentOutput.serialize(component, SerializationDefaults.STORAGE_CONTEXT.withIntegerFingerprint()).bytes
|
||||
val componentOutputBytes = componentOutput.serialize(component, context).bytes
|
||||
OpaqueBytes(componentOutputBytes)
|
||||
})
|
||||
})
|
||||
@ -76,8 +78,8 @@ class CompatibilityTest {
|
||||
|
||||
// Serialize back and check that representation is byte-to-byte identical to what it was originally.
|
||||
val output = SerializationOutput(serializerFactory)
|
||||
val outByteArray = output.serialize(newTransaction, SerializationDefaults.STORAGE_CONTEXT.withEncoding(CordaSerializationEncoding.SNAPPY)
|
||||
.withIntegerFingerprint()).bytes
|
||||
val outByteArray = output.serialize(newTransaction, context.withExternalSchema(context.externalSchema!!.copy(flush = true))
|
||||
.withEncoding(CordaSerializationEncoding.SNAPPY)).bytes
|
||||
//val (serializedBytes, schema) = output.serializeAndReturnSchema(transaction, SerializationDefaults.STORAGE_CONTEXT)
|
||||
println("Output size = ${outByteArray.size}")
|
||||
|
||||
|
@ -2,12 +2,12 @@ package net.corda.serialization.djvm.serializers
|
||||
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.serialization.internal.amqp.AMQPSerializer
|
||||
import net.corda.serialization.internal.amqp.Descriptor
|
||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||
import net.corda.serialization.internal.amqp.SerializationOutput
|
||||
import net.corda.serialization.internal.amqp.SerializationSchemas
|
||||
import net.corda.serialization.internal.amqp.typeDescriptorFor
|
||||
import org.apache.qpid.proton.amqp.Binary
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
import java.util.function.Function
|
||||
@ -16,8 +16,7 @@ class PrimitiveSerializer(
|
||||
override val type: Class<*>,
|
||||
private val sandboxBasicInput: Function<in Any?, out Any?>
|
||||
) : AMQPSerializer<Any> {
|
||||
override val typeDescriptor: Symbol = typeDescriptorFor(type)
|
||||
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptorFor(type))
|
||||
override fun readObject(
|
||||
obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext
|
||||
): Any {
|
||||
|
@ -7,6 +7,7 @@ import net.corda.serialization.djvm.deserializers.CreateCollection
|
||||
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||
import net.corda.serialization.internal.amqp.AMQPSerializer
|
||||
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||
import net.corda.serialization.internal.amqp.Descriptor
|
||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||
import net.corda.serialization.internal.amqp.LocalSerializerFactory
|
||||
import net.corda.serialization.internal.amqp.Schema
|
||||
@ -15,7 +16,6 @@ import net.corda.serialization.internal.amqp.SerializationSchemas
|
||||
import net.corda.serialization.internal.amqp.redescribe
|
||||
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
@ -92,14 +92,14 @@ private class ConcreteCollectionSerializer(
|
||||
) : AMQPSerializer<Any> {
|
||||
override val type: ParameterizedType = declaredType
|
||||
|
||||
override val typeDescriptor: Symbol by lazy {
|
||||
factory.createDescriptor(
|
||||
override val descriptor: Descriptor by lazy {
|
||||
Descriptor(factory.createDescriptor(
|
||||
LocalTypeInformation.ACollection(
|
||||
observedType = declaredType,
|
||||
typeIdentifier = TypeIdentifier.forGenericType(declaredType),
|
||||
elementType = factory.getTypeInformation(declaredType.actualTypeArguments[0])
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
override fun readObject(
|
||||
|
@ -20,7 +20,6 @@ import net.corda.serialization.internal.amqp.SerializationSchemas
|
||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
import net.corda.serialization.internal.amqp.typeDescriptorFor
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
@ -65,8 +64,7 @@ class SandboxCorDappCustomSerializer(
|
||||
private val deserializationAlias: TypeIdentifier get() =
|
||||
TypeIdentifier.Erased(AMQPTypeIdentifiers.nameForType(type).replace("sandbox.", ""), 0)
|
||||
|
||||
override val typeDescriptor: Symbol = typeDescriptorFor(type)
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptorFor(type))
|
||||
override val deserializationAliases: Set<TypeIdentifier> = singleton(deserializationAlias)
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,7 @@ import net.corda.serialization.djvm.toSandboxAnyClass
|
||||
import net.corda.serialization.internal.amqp.AMQPNotSerializableException
|
||||
import net.corda.serialization.internal.amqp.AMQPSerializer
|
||||
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||
import net.corda.serialization.internal.amqp.Descriptor
|
||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||
import net.corda.serialization.internal.amqp.LocalSerializerFactory
|
||||
import net.corda.serialization.internal.amqp.Schema
|
||||
@ -17,7 +18,6 @@ import net.corda.serialization.internal.amqp.SerializationSchemas
|
||||
import net.corda.serialization.internal.model.EnumTransforms
|
||||
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
import java.util.function.Function
|
||||
@ -76,8 +76,8 @@ private class ConcreteEnumSerializer(
|
||||
) : AMQPSerializer<Any> {
|
||||
override val type: Class<*> = declaredType
|
||||
|
||||
override val typeDescriptor: Symbol by lazy {
|
||||
factory.createDescriptor(
|
||||
override val descriptor: Descriptor by lazy {
|
||||
Descriptor(factory.createDescriptor(
|
||||
/*
|
||||
* Partially populated, providing just the information
|
||||
* required by the fingerprinter.
|
||||
@ -90,7 +90,7 @@ private class ConcreteEnumSerializer(
|
||||
emptyList(),
|
||||
EnumTransforms.empty
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
override fun readObject(
|
||||
|
@ -6,6 +6,7 @@ import net.corda.serialization.djvm.deserializers.CreateMap
|
||||
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||
import net.corda.serialization.internal.amqp.AMQPSerializer
|
||||
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||
import net.corda.serialization.internal.amqp.Descriptor
|
||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||
import net.corda.serialization.internal.amqp.LocalSerializerFactory
|
||||
import net.corda.serialization.internal.amqp.Schema
|
||||
@ -14,7 +15,6 @@ import net.corda.serialization.internal.amqp.SerializationSchemas
|
||||
import net.corda.serialization.internal.amqp.redescribe
|
||||
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
@ -82,15 +82,15 @@ private class ConcreteMapSerializer(
|
||||
) : AMQPSerializer<Any> {
|
||||
override val type: ParameterizedType = declaredType
|
||||
|
||||
override val typeDescriptor: Symbol by lazy {
|
||||
factory.createDescriptor(
|
||||
override val descriptor: Descriptor by lazy {
|
||||
Descriptor(factory.createDescriptor(
|
||||
LocalTypeInformation.AMap(
|
||||
observedType = declaredType,
|
||||
typeIdentifier = TypeIdentifier.forGenericType(declaredType),
|
||||
keyType = factory.getTypeInformation(declaredType.actualTypeArguments[0]),
|
||||
valueType = factory.getTypeInformation(declaredType.actualTypeArguments[1])
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
override fun readObject(
|
||||
|
@ -62,7 +62,7 @@ class DeserializeEnumWithEvolutionTest : TestBase(KOTLIN) {
|
||||
}
|
||||
|
||||
private fun SerializedBytes<*>.devolve(context: SerializationContext): SerializedBytes<Any> {
|
||||
val envelope = DeserializationInput.getEnvelope(this, context.encodingWhitelist).apply {
|
||||
val envelope = DeserializationInput.getEnvelope(this, context).apply {
|
||||
val schemaTypes = schema.types.map(::devolveType)
|
||||
with(schema.types as MutableList<TypeNotation>) {
|
||||
clear()
|
||||
|
@ -47,7 +47,7 @@ class DeserializeRemoteCustomisedEnumTest : TestBase(KOTLIN) {
|
||||
*/
|
||||
@Suppress("unchecked_cast")
|
||||
private fun SerializedBytes<Broken>.rewriteEnumAsWorking(): SerializedBytes<Working> {
|
||||
val envelope = DeserializationInput.getEnvelope(this).apply {
|
||||
val envelope = DeserializationInput.getEnvelope(this, AMQP_STORAGE_CONTEXT).apply {
|
||||
val restrictedType = schema.types[0] as RestrictedType
|
||||
(schema.types as MutableList<TypeNotation>)[0] = restrictedType.copy(
|
||||
name = toWorking(restrictedType.name)
|
||||
@ -92,7 +92,7 @@ class DeserializeRemoteCustomisedEnumTest : TestBase(KOTLIN) {
|
||||
*/
|
||||
@Suppress("unchecked_cast")
|
||||
private fun SerializedBytes<BrokenContainer>.rewriteContainerAsWorking(): SerializedBytes<WorkingContainer> {
|
||||
val envelope = DeserializationInput.getEnvelope(this).apply {
|
||||
val envelope = DeserializationInput.getEnvelope(this, AMQP_STORAGE_CONTEXT).apply {
|
||||
val compositeType = schema.types[0] as CompositeType
|
||||
(schema.types as MutableList<TypeNotation>)[0] = compositeType.copy(
|
||||
name = toWorking(compositeType.name),
|
||||
|
@ -27,7 +27,7 @@ class SafeDeserialisationTest : TestBase(KOTLIN) {
|
||||
|
||||
val innocent = InnocentData(MESSAGE, NUMBER)
|
||||
val innocentData = innocent.serialize()
|
||||
val envelope = DeserializationInput.getEnvelope(innocentData, context.encodingWhitelist).apply {
|
||||
val envelope = DeserializationInput.getEnvelope(innocentData, context).apply {
|
||||
val innocentType = schema.types[0] as CompositeType
|
||||
(schema.types as MutableList<TypeNotation>)[0] = innocentType.copy(
|
||||
name = innocentType.name.replace("Innocent", "VeryEvil")
|
||||
|
@ -12,6 +12,9 @@ import org.apache.qpid.proton.amqp.UnsignedLong
|
||||
*/
|
||||
const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl (32 + 16)
|
||||
|
||||
const val DESCRIPTOR_USER_START: Long = 256L
|
||||
const val DESCRIPTOR_CUSTOM_SERIALIZER_START: Long = 32L
|
||||
|
||||
/**
|
||||
* AMQP descriptor ID's for our custom types.
|
||||
*
|
||||
|
@ -12,7 +12,7 @@ import java.lang.reflect.Type
|
||||
* [ByteArray] is automatically marshalled to/from the Proton-J wrapper, [Binary].
|
||||
*/
|
||||
class AMQPPrimitiveSerializer(clazz: Class<*>) : AMQPSerializer<Any> {
|
||||
override val typeDescriptor = Symbol.valueOf(AMQPTypeIdentifiers.primitiveTypeName(clazz))!!
|
||||
override val descriptor: Descriptor = Descriptor(Symbol.valueOf(AMQPTypeIdentifiers.primitiveTypeName(clazz))!!)
|
||||
override val type: Type = clazz
|
||||
|
||||
// NOOP since this is a primitive type.
|
||||
|
@ -2,7 +2,6 @@ package net.corda.serialization.internal.amqp
|
||||
|
||||
import net.corda.core.KeepForDJVM
|
||||
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
|
||||
|
||||
@ -22,7 +21,8 @@ interface AMQPSerializer<out T> {
|
||||
*
|
||||
* This should be unique enough that we can use one global cache of [AMQPSerializer]s and use this as the look up key.
|
||||
*/
|
||||
val typeDescriptor: Symbol
|
||||
//val typeDescriptor: Symbol
|
||||
val descriptor: Descriptor
|
||||
|
||||
/**
|
||||
* Add anything required to the AMQP schema via [SerializationOutput.writeTypeNotations] and any dependent serializers
|
||||
|
@ -7,7 +7,6 @@ import net.corda.core.utilities.debug
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.serialization.internal.model.resolveAgainst
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
|
||||
@ -56,15 +55,13 @@ open class ArraySerializer(override val type: Type, factory: LocalSerializerFact
|
||||
}
|
||||
}
|
||||
|
||||
override val typeDescriptor: Symbol by lazy {
|
||||
factory.createDescriptor(type)
|
||||
}
|
||||
|
||||
internal val elementType: Type by lazy { type.componentType().resolveAgainst(type) }
|
||||
internal open val typeName by lazy { calcTypeName(type) }
|
||||
|
||||
override val descriptor: Descriptor by lazy { Descriptor(factory.createDescriptor(type)) }
|
||||
|
||||
internal val typeNotation: TypeNotation by lazy {
|
||||
RestrictedType(typeName, null, emptyList(), "list", Descriptor(typeDescriptor), emptyList())
|
||||
RestrictedType(typeName, null, emptyList(), "list", Descriptor(factory.createDescriptor(type)), emptyList())
|
||||
}
|
||||
|
||||
override fun writeClassInfo(output: SerializationOutput) {
|
||||
|
@ -5,7 +5,6 @@ import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.utilities.NonEmptySet
|
||||
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.ParameterizedType
|
||||
@ -22,8 +21,8 @@ import java.util.TreeSet
|
||||
class CollectionSerializer(private val declaredType: ParameterizedType, factory: LocalSerializerFactory) : AMQPSerializer<Any> {
|
||||
override val type: Type = declaredType
|
||||
|
||||
override val typeDescriptor: Symbol by lazy {
|
||||
factory.createDescriptor(type)
|
||||
override val descriptor: Descriptor by lazy {
|
||||
Descriptor(factory.createDescriptor(type))
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -90,7 +89,7 @@ class CollectionSerializer(private val declaredType: ParameterizedType, factory:
|
||||
|
||||
private val concreteBuilder: (List<*>) -> Collection<*> = findConcreteType(declaredType.rawType as Class<*>)
|
||||
|
||||
private val typeNotation: TypeNotation = RestrictedType(AMQPTypeIdentifiers.nameForType(declaredType), null, emptyList(), "list", Descriptor(typeDescriptor), emptyList())
|
||||
private val typeNotation: TypeNotation = RestrictedType(AMQPTypeIdentifiers.nameForType(declaredType), null, emptyList(), "list", descriptor, emptyList())
|
||||
|
||||
private val outboundType = resolveTypeVariables(declaredType.actualTypeArguments[0], null)
|
||||
private val inboundType = declaredType.actualTypeArguments[0]
|
||||
|
@ -4,7 +4,6 @@ import com.google.common.reflect.TypeToken
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationCustomSerializer
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.jvm.javaType
|
||||
@ -62,8 +61,7 @@ class CorDappCustomSerializer(
|
||||
|
||||
override val type = types[CORDAPP_TYPE]
|
||||
val proxyType = types[PROXY_TYPE]
|
||||
override val typeDescriptor: Symbol = typeDescriptorFor(type)
|
||||
val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptorFor(type))
|
||||
private val proxySerializer: ObjectSerializer by lazy {
|
||||
ObjectSerializer.make(factory.getTypeInformation(proxyType), factory)
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
*/
|
||||
open val deserializationAliases: Set<TypeIdentifier> = emptySet()
|
||||
|
||||
protected abstract val descriptor: Descriptor
|
||||
/**
|
||||
* This exists purely for documentation and cross-platform purposes. It is not used by our serialization / deserialization
|
||||
* code path.
|
||||
@ -82,12 +81,16 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
|
||||
override val type: Type get() = clazz
|
||||
|
||||
override val typeDescriptor: Symbol by lazy {
|
||||
override fun writeClassInfo(output: SerializationOutput) {
|
||||
output.writeTypeNotations(typeNotation)
|
||||
}
|
||||
|
||||
override val descriptor: Descriptor by lazy {
|
||||
val fingerprint = FingerprintWriter()
|
||||
.write(superClassSerializer.typeDescriptor)
|
||||
.write(superClassSerializer.descriptor.name!!)
|
||||
.write(AMQPTypeIdentifiers.nameForType(clazz))
|
||||
.fingerprint
|
||||
Symbol.valueOf("$DESCRIPTOR_DOMAIN:$fingerprint")
|
||||
Descriptor(Symbol.valueOf("$DESCRIPTOR_DOMAIN:$fingerprint"))
|
||||
}
|
||||
|
||||
private val typeNotation: TypeNotation = RestrictedType(
|
||||
@ -95,16 +98,10 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
null,
|
||||
emptyList(),
|
||||
AMQPTypeIdentifiers.nameForType(superClassSerializer.type),
|
||||
Descriptor(typeDescriptor),
|
||||
descriptor,
|
||||
emptyList()
|
||||
)
|
||||
|
||||
override fun writeClassInfo(output: SerializationOutput) {
|
||||
output.writeTypeNotations(typeNotation)
|
||||
}
|
||||
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
|
||||
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext
|
||||
) {
|
||||
@ -124,9 +121,8 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T>, SerializerFor {
|
||||
*/
|
||||
abstract class CustomSerializerImp<T : Any>(protected val clazz: Class<T>, protected val withInheritance: Boolean) : CustomSerializer<T>() {
|
||||
override val type: Type get() = clazz
|
||||
override val typeDescriptor: Symbol = typeDescriptorFor(clazz)
|
||||
override fun writeClassInfo(output: SerializationOutput) {}
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptorFor(clazz))
|
||||
override fun isSerializerFor(clazz: Class<*>): Boolean = if (withInheritance) this.clazz.isAssignableFrom(clazz) else this.clazz == clazz
|
||||
}
|
||||
|
||||
|
@ -102,16 +102,16 @@ class CachingCustomSerializerRegistry(
|
||||
"All serializers should be registered before the cache comes into use.")
|
||||
}
|
||||
|
||||
descriptorBasedSerializerRegistry.getOrBuild(customSerializer.typeDescriptor.toString()) {
|
||||
descriptorBasedSerializerRegistry.getOrBuild(customSerializer.descriptor.name.toString()) {
|
||||
customSerializers += customSerializer
|
||||
for (additional in customSerializer.additionalSerializers) {
|
||||
register(additional)
|
||||
}
|
||||
|
||||
for (alias in customSerializer.deserializationAliases) {
|
||||
val aliasDescriptor = typeDescriptorFor(alias)
|
||||
if (aliasDescriptor != customSerializer.typeDescriptor) {
|
||||
descriptorBasedSerializerRegistry[aliasDescriptor.toString()] = customSerializer
|
||||
val aliasDescriptor = Descriptor(typeDescriptorFor(alias))
|
||||
if (aliasDescriptor != customSerializer.descriptor) {
|
||||
descriptorBasedSerializerRegistry[aliasDescriptor.name.toString()] = customSerializer
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ class CachingCustomSerializerRegistry(
|
||||
"All serializers must be registered before the cache comes into use.")
|
||||
}
|
||||
|
||||
descriptorBasedSerializerRegistry.getOrBuild(customSerializer.typeDescriptor.toString()) {
|
||||
descriptorBasedSerializerRegistry.getOrBuild(customSerializer.descriptor.name.toString()) {
|
||||
customSerializers += customSerializer
|
||||
customSerializer
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package net.corda.serialization.internal.amqp
|
||||
|
||||
import net.corda.core.KeepForDJVM
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.serialization.EncodingWhitelist
|
||||
import net.corda.core.serialization.AMQP_ENVELOPE_CACHE_PROPERTY
|
||||
import net.corda.core.serialization.EncodingWhitelist
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
@ -11,7 +11,6 @@ import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.serialization.internal.ByteBufferInputStream
|
||||
import net.corda.serialization.internal.CordaSerializationEncoding
|
||||
import net.corda.serialization.internal.NullEncodingWhitelist
|
||||
import net.corda.serialization.internal.SectionId
|
||||
import net.corda.serialization.internal.encodingNotPermittedFormat
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
@ -21,7 +20,6 @@ import org.apache.qpid.proton.amqp.UnsignedInteger
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.InputStream
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.Exception
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
import java.lang.reflect.TypeVariable
|
||||
@ -73,8 +71,8 @@ class DeserializationInput constructor(
|
||||
}
|
||||
|
||||
@Throws(AMQPNoTypeNotSerializableException::class)
|
||||
fun getEnvelope(byteSequence: ByteSequence, encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist): Envelope {
|
||||
return withDataBytes(byteSequence, encodingWhitelist) { dataBytes ->
|
||||
fun getEnvelope(byteSequence: ByteSequence, context: SerializationContext): Envelope {
|
||||
return withDataBytes(byteSequence, context.encodingWhitelist) { dataBytes ->
|
||||
val data = Data.Factory.create()
|
||||
val expectedSize = dataBytes.remaining()
|
||||
if (data.decode(dataBytes) != expectedSize.toLong()) {
|
||||
@ -82,14 +80,17 @@ class DeserializationInput constructor(
|
||||
"Unexpected size of data",
|
||||
"Blob is corrupted!.")
|
||||
}
|
||||
Envelope.get(data)
|
||||
val envelope = Envelope.get(data)
|
||||
if (context.externalSchema == null || envelope.schema.types.isNotEmpty()) {
|
||||
envelope
|
||||
} else {
|
||||
Envelope(envelope.obj, context.externalSchema?.externalSchemaForDeserialization as? Schema
|
||||
?: Schema.newInstance(listOf(context.externalSchema?.typeNotations?.flatten()
|
||||
?.toList() as List<TypeNotation>)), TransformsSchema.newInstance(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Throws(AMQPNoTypeNotSerializableException::class)
|
||||
fun getEnvelope(byteSequence: ByteSequence, context: SerializationContext) = getEnvelope(byteSequence, context.encodingWhitelist)
|
||||
|
||||
@Throws(
|
||||
AMQPNotSerializableException::class,
|
||||
@ -134,8 +135,8 @@ class DeserializationInput constructor(
|
||||
@Suppress("unchecked_cast")
|
||||
val envelope = (context.properties[AMQP_ENVELOPE_CACHE_PROPERTY] as? MutableMap<IdentityKey, Envelope>)
|
||||
?.computeIfAbsent(IdentityKey(bytes)) { key ->
|
||||
getEnvelope(key.bytes, context.encodingWhitelist)
|
||||
} ?: getEnvelope(bytes, context.encodingWhitelist)
|
||||
getEnvelope(key.bytes, context)
|
||||
} ?: getEnvelope(bytes, context)
|
||||
|
||||
logger.trace { "deserialize blob scheme=\"${envelope.schema}\"" }
|
||||
|
||||
@ -148,7 +149,7 @@ class DeserializationInput constructor(
|
||||
clazz: Class<T>,
|
||||
context: SerializationContext
|
||||
): ObjectAndEnvelope<T> = des {
|
||||
val envelope = getEnvelope(bytes, context.encodingWhitelist)
|
||||
val envelope = getEnvelope(bytes, context)
|
||||
// Now pick out the obj and schema from the envelope.
|
||||
ObjectAndEnvelope(doReadObject(envelope, clazz, context), envelope)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package net.corda.serialization.internal.amqp
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.serialization.internal.model.BaseLocalTypes
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@ -38,7 +37,7 @@ class EnumEvolutionSerializer(
|
||||
private val baseLocalTypes: BaseLocalTypes,
|
||||
private val conversions: Map<String, String>,
|
||||
private val ordinals: Map<String, Int>) : AMQPSerializer<Any> {
|
||||
override val typeDescriptor = factory.createDescriptor(type)
|
||||
override val descriptor: Descriptor = Descriptor(factory.createDescriptor(type))
|
||||
|
||||
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput,
|
||||
context: SerializationContext
|
||||
|
@ -11,13 +11,13 @@ import java.lang.reflect.Type
|
||||
class EnumSerializer(declaredType: Type, declaredClass: Class<*>, factory: LocalSerializerFactory) : AMQPSerializer<Any> {
|
||||
override val type: Type = declaredType
|
||||
private val typeNotation: TypeNotation
|
||||
override val typeDescriptor = factory.createDescriptor(type)
|
||||
override val descriptor: Descriptor = Descriptor(factory.createDescriptor(type))
|
||||
|
||||
init {
|
||||
@Suppress("unchecked_cast")
|
||||
typeNotation = RestrictedType(
|
||||
AMQPTypeIdentifiers.nameForType(declaredType),
|
||||
null, emptyList(), "list", Descriptor(typeDescriptor),
|
||||
null, emptyList(), "list", descriptor,
|
||||
(declaredClass as Class<out Enum<*>>).enumConstants.zip(IntRange(0, declaredClass.enumConstants.size)).map {
|
||||
Choice(it.first.name, it.second.toString())
|
||||
})
|
||||
|
@ -19,6 +19,7 @@ data class Envelope(val obj: Any?, val schema: Schema, val transformsSchema: Tra
|
||||
val DESCRIPTOR_OBJECT = Descriptor(null, DESCRIPTOR)
|
||||
|
||||
// described list should either be two or three elements long
|
||||
private const val ENVELOPE_WITHOUT_SCHEMA = 1
|
||||
private const val ENVELOPE_WITHOUT_TRANSFORMS = 2
|
||||
private const val ENVELOPE_WITH_TRANSFORMS = 3
|
||||
private const val ENVELOPE_WITH_TRANSFORMS_AND_EXTERNAL_SCHEMA = 3
|
||||
@ -36,27 +37,39 @@ data class Envelope(val obj: Any?, val schema: Schema, val transformsSchema: Tra
|
||||
}
|
||||
val list = describedType.described as List<*>
|
||||
|
||||
// We need to cope with objects serialised without the schema header element in the
|
||||
// envelope
|
||||
val schema: Any? = when (list.size) {
|
||||
ENVELOPE_WITHOUT_SCHEMA -> Schema(emptyList())
|
||||
ENVELOPE_WITHOUT_TRANSFORMS -> Schema.get(list[SCHEMA_IDX]!!)
|
||||
ENVELOPE_WITH_TRANSFORMS -> Schema.get(list[SCHEMA_IDX]!!)
|
||||
ENVELOPE_WITH_TRANSFORMS_AND_EXTERNAL_SCHEMA -> Schema.get(list[SCHEMA_IDX]!!)
|
||||
else -> throw AMQPNoTypeNotSerializableException(
|
||||
"Malformed list, bad length of ${list.size} (should be 1, 2, 3 or 4)")
|
||||
}
|
||||
// We need to cope with objects serialised without the transforms header element in the
|
||||
// envelope
|
||||
val transformSchema: Any? = when (list.size) {
|
||||
ENVELOPE_WITHOUT_SCHEMA -> null
|
||||
ENVELOPE_WITHOUT_TRANSFORMS -> null
|
||||
ENVELOPE_WITH_TRANSFORMS -> list[TRANSFORMS_SCHEMA_IDX]
|
||||
ENVELOPE_WITH_TRANSFORMS_AND_EXTERNAL_SCHEMA -> list[TRANSFORMS_SCHEMA_IDX]
|
||||
else -> throw AMQPNoTypeNotSerializableException(
|
||||
"Malformed list, bad length of ${list.size} (should be 2, 3 or 4)")
|
||||
"Malformed list, bad length of ${list.size} (should be 1, 2, 3 or 4)")
|
||||
}
|
||||
|
||||
/*
|
||||
// We need to cope with objects serialised without the external schema header element in the
|
||||
// envelope
|
||||
val externalSchema: Any? = when (list.size) {
|
||||
ENVELOPE_WITHOUT_SCHEMA -> null
|
||||
ENVELOPE_WITHOUT_TRANSFORMS -> null
|
||||
ENVELOPE_WITH_TRANSFORMS -> null
|
||||
ENVELOPE_WITH_TRANSFORMS_AND_EXTERNAL_SCHEMA -> list[EXTERNAL_SCHEMA_IDX]
|
||||
else -> throw AMQPNoTypeNotSerializableException(
|
||||
"Malformed list, bad length of ${list.size} (should be 2, 3 or 4)")
|
||||
}
|
||||
"Malformed list, bad length of ${list.size} (should be 1, 2, 3 or 4)")
|
||||
}*/
|
||||
|
||||
return newInstance(listOf(list[BLOB_IDX], Schema.get(list[SCHEMA_IDX]!!),
|
||||
return newInstance(listOf(list[BLOB_IDX], schema,
|
||||
TransformsSchema.newInstance(transformSchema)))
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,16 @@ import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.debug
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.serialization.internal.model.*
|
||||
import net.corda.serialization.internal.model.TypeIdentifier.*
|
||||
import net.corda.serialization.internal.model.DefaultCacheProvider
|
||||
import net.corda.serialization.internal.model.FingerPrinter
|
||||
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import net.corda.serialization.internal.model.LocalTypeModel
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import net.corda.serialization.internal.model.TypeIdentifier.Parameterised
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
import java.util.*
|
||||
import java.util.Optional
|
||||
import java.util.function.Function
|
||||
import java.util.function.Predicate
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
@ -146,7 +150,7 @@ class DefaultLocalSerializerFactory(
|
||||
private fun makeAndCache(typeIdentifier: TypeIdentifier, build: () -> AMQPSerializer<Any>) =
|
||||
serializersByTypeId.getOrPut(typeIdentifier) {
|
||||
build().also { serializer ->
|
||||
descriptorBasedSerializerRegistry[serializer.typeDescriptor.toString()] = serializer
|
||||
descriptorBasedSerializerRegistry[serializer.descriptor.name.toString()] = serializer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import net.corda.serialization.internal.model.TypeIdentifier
|
||||
import org.apache.qpid.proton.amqp.Symbol
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.ParameterizedType
|
||||
@ -29,7 +28,7 @@ private typealias MapCreationFunction = (Map<*, *>) -> Map<*, *>
|
||||
class MapSerializer(private val declaredType: ParameterizedType, factory: LocalSerializerFactory) : AMQPSerializer<Any> {
|
||||
override val type: Type = declaredType
|
||||
|
||||
override val typeDescriptor: Symbol = factory.createDescriptor(type)
|
||||
override val descriptor: Descriptor = Descriptor(factory.createDescriptor(type))
|
||||
|
||||
companion object {
|
||||
// NB: Order matters in this map, the most specific classes should be listed at the end
|
||||
@ -90,7 +89,7 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: LocalS
|
||||
|
||||
private val concreteBuilder: MapCreationFunction = findConcreteType(declaredType.rawType as Class<*>)
|
||||
|
||||
private val typeNotation: TypeNotation = RestrictedType(AMQPTypeIdentifiers.nameForType(declaredType), null, emptyList(), "map", Descriptor(typeDescriptor), emptyList())
|
||||
private val typeNotation: TypeNotation = RestrictedType(AMQPTypeIdentifiers.nameForType(declaredType), null, emptyList(), "map", descriptor, emptyList())
|
||||
|
||||
private val inboundKeyType = declaredType.actualTypeArguments[0]
|
||||
private val outboundKeyType = resolveTypeVariables(inboundKeyType, null)
|
||||
|
@ -102,12 +102,14 @@ interface ObjectSerializer : AMQPSerializer<Any> {
|
||||
|
||||
class ComposableObjectSerializer(
|
||||
override val type: Type,
|
||||
override val typeDescriptor: Symbol,
|
||||
typeDescriptor: Symbol,
|
||||
override val propertySerializers: Map<PropertyName, PropertySerializer>,
|
||||
override val fields: List<Field>,
|
||||
private val reader: ComposableObjectReader,
|
||||
private val writer: ComposableObjectWriter): ObjectSerializer {
|
||||
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
|
||||
override fun writeClassInfo(output: SerializationOutput) = writer.writeClassInfo(output)
|
||||
|
||||
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int) =
|
||||
@ -178,10 +180,12 @@ class ComposableObjectReader(
|
||||
|
||||
class AbstractObjectSerializer(
|
||||
override val type: Type,
|
||||
override val typeDescriptor: Symbol,
|
||||
typeDescriptor: Symbol,
|
||||
override val propertySerializers: Map<PropertyName, PropertySerializer>,
|
||||
override val fields: List<Field>,
|
||||
private val writer: ComposableObjectWriter): ObjectSerializer {
|
||||
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
override fun writeClassInfo(output: SerializationOutput) =
|
||||
writer.writeClassInfo(output)
|
||||
|
||||
@ -194,10 +198,12 @@ class AbstractObjectSerializer(
|
||||
|
||||
class EvolutionObjectSerializer(
|
||||
override val type: Type,
|
||||
override val typeDescriptor: Symbol,
|
||||
typeDescriptor: Symbol,
|
||||
override val propertySerializers: Map<PropertyName, PropertySerializer>,
|
||||
private val reader: ComposableObjectReader): ObjectSerializer {
|
||||
|
||||
override val descriptor: Descriptor = Descriptor(typeDescriptor)
|
||||
|
||||
companion object {
|
||||
fun make(localTypeInformation: LocalTypeInformation.Composable,
|
||||
remoteTypeInformation: RemoteTypeInformation.Composable,
|
||||
|
@ -97,7 +97,7 @@ class DefaultRemoteSerializerFactory(
|
||||
|
||||
// Obtain a serializer and descriptor for the local type.
|
||||
val localSerializer = localSerializerFactory.get(localTypeInformation)
|
||||
val localDescriptor = localSerializer.typeDescriptor.toString()
|
||||
val localDescriptor = localSerializer.descriptor.name.toString()
|
||||
|
||||
return when {
|
||||
// If descriptors match, we can return the local serializer straight away.
|
||||
|
@ -35,7 +35,7 @@ fun Descriptor.maybeConvertToInteger(context: SerializationContext): Descriptor
|
||||
val descriptorMappings = context.integerFingerprints?.descriptorMappings
|
||||
if (descriptorMappings == null) return this
|
||||
return context.integerFingerprints!!.descriptorMappings.computeIfAbsent(this) {
|
||||
Descriptor(null, UnsignedLong(32L + descriptorMappings.size or DESCRIPTOR_TOP_32BITS))
|
||||
Descriptor(null, UnsignedLong(DESCRIPTOR_USER_START + descriptorMappings.size or DESCRIPTOR_TOP_32BITS))
|
||||
} as Descriptor
|
||||
}
|
||||
|
||||
|
@ -80,9 +80,22 @@ open class SerializationOutput constructor(
|
||||
data.withDescribed(Envelope.DESCRIPTOR_OBJECT, context) {
|
||||
withList {
|
||||
writeObject(obj, this, context)
|
||||
val schema = Schema(schemaHistory.map { it.maybeConvertDescriptorToInteger(context) }.toList())
|
||||
if (context.externalSchema == null) {
|
||||
val types = schemaHistory.map { it.maybeConvertDescriptorToInteger(context) }.toList()
|
||||
val schema = Schema(types)
|
||||
writeSchema(schema, this)
|
||||
writeTransformSchema(TransformsSchema.build(schema, serializerFactory), this)
|
||||
} else {
|
||||
context.externalSchema?.typeNotations?.add(schemaHistory.map { it.maybeConvertDescriptorToInteger(context) }.toList())
|
||||
if (context.externalSchema!!.flush) {
|
||||
val descriptors: MutableSet<Descriptor> = HashSet()
|
||||
val schema = Schema((context.externalSchema?.typeNotations?.flatten()?.toList() as List<TypeNotation>).filter {
|
||||
descriptors.add(it.descriptor)
|
||||
})
|
||||
writeSchema(schema, this)
|
||||
writeTransformSchema(TransformsSchema.build(schema, serializerFactory), this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SerializedBytes(byteArrayOutput {
|
||||
|
@ -11,13 +11,13 @@ import java.lang.reflect.Type
|
||||
* want converting back to that singleton instance on the receiving JVM.
|
||||
*/
|
||||
class SingletonSerializer(override val type: Class<*>, val singleton: Any, factory: LocalSerializerFactory) : AMQPSerializer<Any> {
|
||||
override val typeDescriptor = factory.createDescriptor(type)
|
||||
override val descriptor: Descriptor = Descriptor(factory.createDescriptor(type))
|
||||
|
||||
private val interfaces = (factory.getTypeInformation(type) as LocalTypeInformation.Singleton).interfaces
|
||||
|
||||
private fun generateProvides(): List<String> = interfaces.map { it.typeIdentifier.name }
|
||||
|
||||
internal val typeNotation: TypeNotation = RestrictedType(type.typeName, "Singleton", generateProvides(), "boolean", Descriptor(typeDescriptor), emptyList())
|
||||
internal val typeNotation: TypeNotation = RestrictedType(type.typeName, "Singleton", generateProvides(), "boolean", descriptor, emptyList())
|
||||
|
||||
override fun writeClassInfo(output: SerializationOutput) {
|
||||
output.writeTypeNotations(typeNotation)
|
||||
|
@ -248,7 +248,7 @@ private class FingerPrintingState(
|
||||
val customTypeDescriptor = customSerializerRegistry.findCustomSerializer(
|
||||
clazz = observedClass,
|
||||
declaredType = observedGenericType
|
||||
)?.typeDescriptor?.toString()
|
||||
)?.descriptor?.name?.toString()
|
||||
if (customTypeDescriptor != null) writer.write(customTypeDescriptor)
|
||||
else defaultAction()
|
||||
}
|
||||
|
@ -9,6 +9,6 @@ class SerializationCompatibilityTests {
|
||||
@Test(timeout=300_000)
|
||||
fun `fingerprint is stable`() {
|
||||
val factory = testDefaultFactoryNoEvolution().apply { register(ThrowableSerializer(this)) }
|
||||
assertThat(factory.get(Exception::class.java).typeDescriptor.toString()).isEqualTo("net.corda:ApZ2a/36VVskaoDZMbiZ8A==")
|
||||
assertThat(factory.get(Exception::class.java).descriptor.name.toString()).isEqualTo("net.corda:ApZ2a/36VVskaoDZMbiZ8A==")
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.corda.serialization.internal.amqp
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationContext.UseCase.Testing
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.serialization.internal.AMQP_STORAGE_CONTEXT
|
||||
import net.corda.serialization.internal.AllWhitelist
|
||||
import net.corda.serialization.internal.SerializationContextImpl
|
||||
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
|
||||
@ -51,7 +52,7 @@ class EnumToStringFallbackTest {
|
||||
*/
|
||||
@Suppress("unchecked_cast")
|
||||
private fun SerializedBytes<BrokenContainer>.rewriteAsWorking(): SerializedBytes<WorkingContainer> {
|
||||
val envelope = DeserializationInput.getEnvelope(this).apply {
|
||||
val envelope = DeserializationInput.getEnvelope(this, AMQP_STORAGE_CONTEXT).apply {
|
||||
val compositeType = schema.types[0] as CompositeType
|
||||
(schema.types as MutableList<TypeNotation>)[0] = compositeType.copy(
|
||||
name = toWorking(compositeType.name),
|
||||
|
@ -22,7 +22,9 @@ import net.corda.serialization.internal.SerializationFactoryImpl
|
||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import picocli.CommandLine.*
|
||||
import picocli.CommandLine.ITypeConverter
|
||||
import picocli.CommandLine.Option
|
||||
import picocli.CommandLine.Parameters
|
||||
import java.io.PrintStream
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
@ -59,7 +61,7 @@ class BlobInspector : CordaCliWrapper("blob-inspector", "Convert AMQP serialised
|
||||
initialiseSerialization()
|
||||
|
||||
if (schema) {
|
||||
val envelope = DeserializationInput.getEnvelope(bytes.sequence(), SerializationDefaults.STORAGE_CONTEXT.encodingWhitelist)
|
||||
val envelope = DeserializationInput.getEnvelope(bytes.sequence(), SerializationDefaults.STORAGE_CONTEXT)
|
||||
out.println(envelope.schema)
|
||||
out.println()
|
||||
out.println(envelope.transformsSchema)
|
||||
|
Loading…
Reference in New Issue
Block a user