mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
CORDA-3152: Register custom serializers for jackson as well as amqp
This commit is contained in:
parent
22a8108099
commit
bfa460bc07
@ -51,6 +51,7 @@ import net.corda.core.utilities.toHexString
|
||||
import net.corda.serialization.internal.AllWhitelist
|
||||
import net.corda.serialization.internal.amqp.SerializerFactoryBuilder
|
||||
import net.corda.serialization.internal.amqp.hasCordaSerializable
|
||||
import net.corda.serialization.internal.amqp.registerCustomSerializers
|
||||
import java.math.BigDecimal
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
@ -116,8 +117,10 @@ private class CordaSerializableClassIntrospector(private val context: Module.Set
|
||||
}
|
||||
|
||||
private class CordaSerializableBeanSerializerModifier : BeanSerializerModifier() {
|
||||
// We need to pass in a SerializerFactory when scanning for properties, but don't actually do any serialisation so any will do.
|
||||
private val serializerFactory = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader)
|
||||
// We need to pass in a SerializerFactory when scanning for properties, but don't actually do any serialisation so any will do.
|
||||
private val serializerFactory = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).also {
|
||||
registerCustomSerializers(it)
|
||||
}
|
||||
|
||||
override fun changeProperties(config: SerializationConfig,
|
||||
beanDesc: BeanDescription,
|
||||
@ -125,7 +128,9 @@ private class CordaSerializableBeanSerializerModifier : BeanSerializerModifier()
|
||||
val beanClass = beanDesc.beanClass
|
||||
if (hasCordaSerializable(beanClass) && !SerializeAsToken::class.java.isAssignableFrom(beanClass)) {
|
||||
val typeInformation = serializerFactory.getTypeInformation(beanClass)
|
||||
val propertyNames = typeInformation.propertiesOrEmptyMap.mapNotNull { if (it.value.isCalculated) null else it.key }
|
||||
val propertyNames = typeInformation.propertiesOrEmptyMap.mapNotNull {
|
||||
if (it.value.isCalculated) null else it.key
|
||||
}
|
||||
beanProperties.removeIf { it.name !in propertyNames }
|
||||
}
|
||||
return beanProperties
|
||||
|
@ -85,7 +85,12 @@ val _inheritableContextSerializationEnv = InheritableThreadLocalToggleField<Seri
|
||||
}
|
||||
}
|
||||
|
||||
private val serializationEnvFields = listOf(_nodeSerializationEnv, _driverSerializationEnv, _contextSerializationEnv, _inheritableContextSerializationEnv)
|
||||
private val serializationEnvFields = listOf(
|
||||
_nodeSerializationEnv,
|
||||
_driverSerializationEnv,
|
||||
_contextSerializationEnv,
|
||||
_inheritableContextSerializationEnv
|
||||
)
|
||||
|
||||
val _allEnabledSerializationEnvs: List<Pair<String, SerializationEnvironment>>
|
||||
get() = serializationEnvFields.mapNotNull { it.get()?.let { env -> Pair(it.name, env) } }
|
||||
@ -94,7 +99,8 @@ val effectiveSerializationEnv: SerializationEnvironment
|
||||
get() {
|
||||
return _allEnabledSerializationEnvs.let {
|
||||
checkNotNull(it.singleOrNull()?.second) {
|
||||
"Expected exactly 1 of {${serializationEnvFields.joinToString(", ") { it.name }}} but got: {${it.joinToString(", ") { it.first }}}"
|
||||
"Expected exactly 1 of {${serializationEnvFields.joinToString(", ") { it.name }}} " +
|
||||
"but got: {${it.joinToString(", ") { it.first }}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ import net.corda.core.DeleteForDJVM
|
||||
import net.corda.core.KeepForDJVM
|
||||
import net.corda.core.StubOutForDJVM
|
||||
import net.corda.core.cordapp.Cordapp
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.toSynchronised
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.serialization.internal.CordaSerializationMagic
|
||||
@ -46,14 +47,20 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
val sff: SerializerFactoryFactory = createSerializerFactoryFactory()
|
||||
) : SerializationScheme {
|
||||
@DeleteForDJVM
|
||||
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, cordapps.serializationWhitelists, AccessOrderLinkedHashMap<SerializationFactoryCacheKey, SerializerFactory>(128).toSynchronised())
|
||||
constructor(cordapps: List<Cordapp>) : this(
|
||||
cordapps.customSerializers,
|
||||
cordapps.serializationWhitelists,
|
||||
AccessOrderLinkedHashMap<SerializationFactoryCacheKey, SerializerFactory>(128).toSynchronised()
|
||||
)
|
||||
|
||||
// This is a bit gross but a broader check for ConcurrentMap is not allowed inside DJVM.
|
||||
private val serializerFactoriesForContexts: MutableMap<SerializationFactoryCacheKey, SerializerFactory> = if (maybeNotConcurrentSerializerFactoriesForContexts is AccessOrderLinkedHashMap<*, *>) {
|
||||
Collections.synchronizedMap(maybeNotConcurrentSerializerFactoriesForContexts)
|
||||
} else {
|
||||
maybeNotConcurrentSerializerFactoriesForContexts
|
||||
}
|
||||
private val serializerFactoriesForContexts: MutableMap<SerializationFactoryCacheKey, SerializerFactory> =
|
||||
if (maybeNotConcurrentSerializerFactoriesForContexts is
|
||||
AccessOrderLinkedHashMap<SerializationFactoryCacheKey, SerializerFactory>) {
|
||||
Collections.synchronizedMap(maybeNotConcurrentSerializerFactoriesForContexts)
|
||||
} else {
|
||||
maybeNotConcurrentSerializerFactoriesForContexts
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val serializationWhitelists: List<SerializationWhitelist> by lazy { listOf(DefaultWhitelist) }
|
||||
@ -68,45 +75,16 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
}
|
||||
|
||||
private fun registerCustomSerializers(context: SerializationContext, factory: SerializerFactory) {
|
||||
with(factory) {
|
||||
register(publicKeySerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.PrivateKeySerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.CurrencySerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.OpaqueBytesSubSequenceSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.InstantSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.DurationSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ZoneIdSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.OptionalSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.YearSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ClassSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(this))
|
||||
registerNonDeterministicSerializers(factory)
|
||||
}
|
||||
factory.register(publicKeySerializer)
|
||||
registerCustomSerializers(factory)
|
||||
|
||||
// This step is registering custom serializers, which have been added after node initialisation (i.e. via attachments during transaction verification).
|
||||
// Note: the order between the registration of customSerializers and cordappCustomSerializers must be preserved as-is. The reason is the following:
|
||||
// Currently, the serialization infrastructure does not support multiple versions of a class (the first one that is registered dominates).
|
||||
// As a result, when inside a context with attachments class loader, we prioritize serializers loaded on-demand from attachments to serializers that had been
|
||||
// loaded during node initialisation, by scanning the cordapps folder.
|
||||
// This step is registering custom serializers, which have been added after node initialisation (i.e. via attachments during
|
||||
// transaction verification).
|
||||
// Note: the order between the registration of customSerializers and cordappCustomSerializers must be preserved as-is. The reason
|
||||
// is the following:
|
||||
// Currently, the serialization infrastructure does not support multiple versions of a class (the first one that is
|
||||
// registered dominates). As a result, when inside a context with attachments class loader, we prioritize serializers loaded
|
||||
// on-demand from attachments to serializers that had been loaded during node initialisation, by scanning the cordapps folder.
|
||||
context.customSerializers.forEach { customSerializer ->
|
||||
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
||||
}
|
||||
@ -126,22 +104,12 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
factory.addToWhitelist(*it.whitelist.toTypedArray())
|
||||
}
|
||||
cordappSerializationWhitelists.forEach {
|
||||
it.whitelist.forEach {
|
||||
clazz -> factory.addToWhitelist(clazz)
|
||||
it.whitelist.forEach { clazz ->
|
||||
factory.addToWhitelist(clazz)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the serializers which will be excluded from the DJVM.
|
||||
*/
|
||||
@StubOutForDJVM
|
||||
private fun registerNonDeterministicSerializers(factory: SerializerFactory) {
|
||||
with(factory) {
|
||||
register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory
|
||||
protected abstract fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory
|
||||
|
||||
@ -189,3 +157,49 @@ abstract class AbstractAMQPSerializationScheme(
|
||||
|
||||
protected fun canDeserializeVersion(magic: CordaSerializationMagic) = magic == amqpMagic
|
||||
}
|
||||
|
||||
fun registerCustomSerializers(factory: SerializerFactory) {
|
||||
with(factory) {
|
||||
register(net.corda.serialization.internal.amqp.custom.PrivateKeySerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.CurrencySerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.OpaqueBytesSubSequenceSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.InstantSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.DurationSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ZoneIdSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.OptionalSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.YearSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ClassSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer)
|
||||
register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(this))
|
||||
register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(this))
|
||||
}
|
||||
registerNonDeterministicSerializers(factory)
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the serializers which will be excluded from the DJVM.
|
||||
*/
|
||||
@StubOutForDJVM
|
||||
private fun registerNonDeterministicSerializers(factory: SerializerFactory) {
|
||||
with(factory) {
|
||||
register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,13 @@ import java.util.*
|
||||
* A serializer that writes out a [BitSet] as an integer number of bits, plus the necessary number of bytes to encode that
|
||||
* many bits.
|
||||
*/
|
||||
class BitSetSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<BitSet, BitSetSerializer.BitSetProxy>(BitSet::class.java, BitSetProxy::class.java, factory) {
|
||||
class BitSetSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<BitSet, BitSetSerializer.BitSetProxy>(
|
||||
BitSet::class.java,
|
||||
BitSetProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: BitSet): BitSetProxy = BitSetProxy(obj.toByteArray())
|
||||
|
||||
override fun fromProxy(proxy: BitSetProxy): BitSet = BitSet.valueOf(proxy.bytes)
|
||||
|
@ -8,8 +8,13 @@ import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.CertificateFactory
|
||||
|
||||
class CertPathSerializer(factory: SerializerFactory)
|
||||
: CustomSerializer.Proxy<CertPath, CertPathSerializer.CertPathProxy>(CertPath::class.java, CertPathProxy::class.java, factory) {
|
||||
class CertPathSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<CertPath, CertPathSerializer.CertPathProxy>(
|
||||
CertPath::class.java,
|
||||
CertPathProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: CertPath): CertPathProxy = CertPathProxy(obj.type, obj.encoded)
|
||||
|
||||
override fun fromProxy(proxy: CertPathProxy): CertPath {
|
||||
|
@ -6,7 +6,6 @@ import net.corda.core.utilities.trace
|
||||
import net.corda.serialization.internal.amqp.AMQPNotSerializableException
|
||||
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||
import net.corda.serialization.internal.amqp.LocalSerializerFactory
|
||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
import net.corda.serialization.internal.amqp.custom.ClassSerializer.ClassProxy
|
||||
|
||||
/**
|
||||
|
@ -15,16 +15,27 @@ import java.security.PublicKey
|
||||
* A serializer for [ContractAttachment] that uses a proxy object to write out the full attachment eagerly.
|
||||
* @param factory the serializerFactory
|
||||
*/
|
||||
class ContractAttachmentSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<ContractAttachment,
|
||||
ContractAttachmentSerializer.ContractAttachmentProxy>(ContractAttachment::class.java,
|
||||
ContractAttachmentProxy::class.java, factory) {
|
||||
class ContractAttachmentSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<ContractAttachment, ContractAttachmentSerializer.ContractAttachmentProxy>(
|
||||
ContractAttachment::class.java,
|
||||
ContractAttachmentProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: ContractAttachment): ContractAttachmentProxy {
|
||||
val bytes = try {
|
||||
obj.attachment.open().readFully()
|
||||
} catch (e: Exception) {
|
||||
throw MissingAttachmentsException(listOf(obj.id))
|
||||
}
|
||||
return ContractAttachmentProxy(GeneratedAttachment(bytes, obj.uploader), obj.contract, obj.additionalContracts, obj.uploader, obj.signerKeys, obj.version)
|
||||
return ContractAttachmentProxy(
|
||||
GeneratedAttachment(bytes, obj.uploader),
|
||||
obj.contract,
|
||||
obj.additionalContracts,
|
||||
obj.uploader,
|
||||
obj.signerKeys,
|
||||
obj.version
|
||||
)
|
||||
}
|
||||
|
||||
override fun fromProxy(proxy: ContractAttachmentProxy): ContractAttachment {
|
||||
@ -32,5 +43,12 @@ class ContractAttachmentSerializer(factory: SerializerFactory) : CustomSerialize
|
||||
}
|
||||
|
||||
@KeepForDJVM
|
||||
data class ContractAttachmentProxy(val attachment: Attachment, val contract: ContractClassName, val contracts: Set<ContractClassName>, val uploader: String?, val signers: List<PublicKey>, val version: Int)
|
||||
data class ContractAttachmentProxy(
|
||||
val attachment: Attachment,
|
||||
val contract: ContractClassName,
|
||||
val contracts: Set<ContractClassName>,
|
||||
val uploader: String?,
|
||||
val signers: List<PublicKey>,
|
||||
val version: Int
|
||||
)
|
||||
}
|
@ -6,7 +6,10 @@ import java.util.*
|
||||
/**
|
||||
* A custom serializer for the [Currency] class, utilizing the currency code string representation.
|
||||
*/
|
||||
object CurrencySerializer : CustomSerializer.ToString<Currency>(Currency::class.java,
|
||||
object CurrencySerializer
|
||||
: CustomSerializer.ToString<Currency>(
|
||||
Currency::class.java,
|
||||
withInheritance = false,
|
||||
maker = { Currency.getInstance(it) },
|
||||
unmaker = { it.currencyCode })
|
||||
unmaker = { it.currencyCode }
|
||||
)
|
||||
|
@ -8,7 +8,13 @@ import java.time.Duration
|
||||
/**
|
||||
* A serializer for [Duration] that uses a proxy object to write out the seconds and the nanos.
|
||||
*/
|
||||
class DurationSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Duration, DurationSerializer.DurationProxy>(Duration::class.java, DurationProxy::class.java, factory) {
|
||||
class DurationSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<Duration, DurationSerializer.DurationProxy>(
|
||||
Duration::class.java,
|
||||
DurationProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: Duration): DurationProxy = DurationProxy(obj.seconds, obj.nano)
|
||||
|
||||
override fun fromProxy(proxy: DurationProxy): Duration = Duration.ofSeconds(proxy.seconds, proxy.nanos.toLong())
|
||||
|
@ -10,7 +10,13 @@ import java.util.*
|
||||
/**
|
||||
* A serializer that writes out an [EnumSet] as a type, plus list of instances in the set.
|
||||
*/
|
||||
class EnumSetSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<EnumSet<*>, EnumSetSerializer.EnumSetProxy>(EnumSet::class.java, EnumSetProxy::class.java, factory) {
|
||||
class EnumSetSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<EnumSet<*>, EnumSetSerializer.EnumSetProxy>(
|
||||
EnumSet::class.java,
|
||||
EnumSetProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(ClassSerializer(factory))
|
||||
|
||||
override fun toProxy(obj: EnumSet<*>): EnumSetProxy = EnumSetProxy(elementType(obj), obj.toList())
|
||||
|
@ -11,7 +11,10 @@ import java.lang.reflect.Type
|
||||
/**
|
||||
* A serializer that writes out the content of an input stream as bytes and deserializes into a [ByteArrayInputStream].
|
||||
*/
|
||||
object InputStreamSerializer : CustomSerializer.Implements<InputStream>(InputStream::class.java) {
|
||||
object InputStreamSerializer
|
||||
: CustomSerializer.Implements<InputStream>(
|
||||
InputStream::class.java
|
||||
) {
|
||||
override val revealSubclassesInSchema: Boolean = true
|
||||
|
||||
override val schemaForDocumentation = Schema(
|
||||
|
@ -8,7 +8,13 @@ import java.time.Instant
|
||||
/**
|
||||
* A serializer for [Instant] that uses a proxy object to write out the seconds since the epoch and the nanos.
|
||||
*/
|
||||
class InstantSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Instant, InstantSerializer.InstantProxy>(Instant::class.java, InstantProxy::class.java, factory) {
|
||||
class InstantSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<Instant, InstantSerializer.InstantProxy>(
|
||||
Instant::class.java,
|
||||
InstantProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: Instant): InstantProxy = InstantProxy(obj.epochSecond, obj.nano)
|
||||
|
||||
override fun fromProxy(proxy: InstantProxy): Instant = Instant.ofEpochSecond(proxy.epochSeconds, proxy.nanos.toLong())
|
||||
|
@ -8,7 +8,13 @@ import java.time.LocalDate
|
||||
/**
|
||||
* A serializer for [LocalDate] that uses a proxy object to write out the year, month and day.
|
||||
*/
|
||||
class LocalDateSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<LocalDate, LocalDateSerializer.LocalDateProxy>(LocalDate::class.java, LocalDateProxy::class.java, factory) {
|
||||
class LocalDateSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<LocalDate, LocalDateSerializer.LocalDateProxy>(
|
||||
LocalDate::class.java,
|
||||
LocalDateProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: LocalDate): LocalDateProxy = LocalDateProxy(obj.year, obj.monthValue.toByte(), obj.dayOfMonth.toByte())
|
||||
|
||||
override fun fromProxy(proxy: LocalDateProxy): LocalDate = LocalDate.of(proxy.year, proxy.month.toInt(), proxy.day.toInt())
|
||||
|
@ -10,8 +10,17 @@ import java.time.LocalTime
|
||||
/**
|
||||
* A serializer for [LocalDateTime] that uses a proxy object to write out the date and time.
|
||||
*/
|
||||
class LocalDateTimeSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<LocalDateTime, LocalDateTimeSerializer.LocalDateTimeProxy>(LocalDateTime::class.java, LocalDateTimeProxy::class.java, factory) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(LocalDateSerializer(factory), LocalTimeSerializer(factory))
|
||||
class LocalDateTimeSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<LocalDateTime, LocalDateTimeSerializer.LocalDateTimeProxy>(
|
||||
LocalDateTime::class.java,
|
||||
LocalDateTimeProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(
|
||||
LocalDateSerializer(factory),
|
||||
LocalTimeSerializer(factory)
|
||||
)
|
||||
|
||||
override fun toProxy(obj: LocalDateTime): LocalDateTimeProxy = LocalDateTimeProxy(obj.toLocalDate(), obj.toLocalTime())
|
||||
|
||||
|
@ -8,10 +8,26 @@ import java.time.LocalTime
|
||||
/**
|
||||
* A serializer for [LocalTime] that uses a proxy object to write out the hours, minutes, seconds and the nanos.
|
||||
*/
|
||||
class LocalTimeSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<LocalTime, LocalTimeSerializer.LocalTimeProxy>(LocalTime::class.java, LocalTimeProxy::class.java, factory) {
|
||||
override fun toProxy(obj: LocalTime): LocalTimeProxy = LocalTimeProxy(obj.hour.toByte(), obj.minute.toByte(), obj.second.toByte(), obj.nano)
|
||||
class LocalTimeSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<LocalTime, LocalTimeSerializer.LocalTimeProxy>(
|
||||
LocalTime::class.java,
|
||||
LocalTimeProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: LocalTime): LocalTimeProxy = LocalTimeProxy(
|
||||
obj.hour.toByte(),
|
||||
obj.minute.toByte(),
|
||||
obj.second.toByte(),
|
||||
obj.nano
|
||||
)
|
||||
|
||||
override fun fromProxy(proxy: LocalTimeProxy): LocalTime = LocalTime.of(proxy.hour.toInt(), proxy.minute.toInt(), proxy.second.toInt(), proxy.nano)
|
||||
override fun fromProxy(proxy: LocalTimeProxy): LocalTime = LocalTime.of(
|
||||
proxy.hour.toInt(),
|
||||
proxy.minute.toInt(),
|
||||
proxy.second.toInt(),
|
||||
proxy.nano
|
||||
)
|
||||
|
||||
@KeepForDJVM
|
||||
data class LocalTimeProxy(val hour: Byte, val minute: Byte, val second: Byte, val nano: Int)
|
||||
|
@ -8,8 +8,9 @@ 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>(
|
||||
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())
|
||||
|
@ -10,8 +10,17 @@ import java.time.ZoneOffset
|
||||
/**
|
||||
* A serializer for [OffsetDateTime] that uses a proxy object to write out the date and zone offset.
|
||||
*/
|
||||
class OffsetDateTimeSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<OffsetDateTime, OffsetDateTimeSerializer.OffsetDateTimeProxy>(OffsetDateTime::class.java, OffsetDateTimeProxy::class.java, factory) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(LocalDateTimeSerializer(factory), ZoneIdSerializer(factory))
|
||||
class OffsetDateTimeSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<OffsetDateTime, OffsetDateTimeSerializer.OffsetDateTimeProxy>(
|
||||
OffsetDateTime::class.java,
|
||||
OffsetDateTimeProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(
|
||||
LocalDateTimeSerializer(factory),
|
||||
ZoneIdSerializer(factory)
|
||||
)
|
||||
|
||||
override fun toProxy(obj: OffsetDateTime): OffsetDateTimeProxy = OffsetDateTimeProxy(obj.toLocalDateTime(), obj.offset)
|
||||
|
||||
|
@ -10,8 +10,17 @@ import java.time.ZoneOffset
|
||||
/**
|
||||
* A serializer for [OffsetTime] that uses a proxy object to write out the time and zone offset.
|
||||
*/
|
||||
class OffsetTimeSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<OffsetTime, OffsetTimeSerializer.OffsetTimeProxy>(OffsetTime::class.java, OffsetTimeProxy::class.java, factory) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(LocalTimeSerializer(factory), ZoneIdSerializer(factory))
|
||||
class OffsetTimeSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<OffsetTime, OffsetTimeSerializer.OffsetTimeProxy>(
|
||||
OffsetTime::class.java,
|
||||
OffsetTimeProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(
|
||||
LocalTimeSerializer(factory),
|
||||
ZoneIdSerializer(factory)
|
||||
)
|
||||
|
||||
override fun toProxy(obj: OffsetTime): OffsetTimeProxy = OffsetTimeProxy(obj.toLocalTime(), obj.offset)
|
||||
|
||||
|
@ -10,8 +10,13 @@ import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
* to save on network bandwidth
|
||||
* Uses [OpaqueBytes] as a proxy
|
||||
*/
|
||||
class OpaqueBytesSubSequenceSerializer(factory: SerializerFactory) :
|
||||
CustomSerializer.Proxy<OpaqueBytesSubSequence, OpaqueBytes>(OpaqueBytesSubSequence::class.java, OpaqueBytes::class.java, factory) {
|
||||
class OpaqueBytesSubSequenceSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<OpaqueBytesSubSequence, OpaqueBytes>(
|
||||
OpaqueBytesSubSequence::class.java,
|
||||
OpaqueBytes::class.java,
|
||||
factory
|
||||
) {
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = emptyList()
|
||||
override fun toProxy(obj: OpaqueBytesSubSequence): OpaqueBytes = OpaqueBytes(obj.copyBytes())
|
||||
override fun fromProxy(proxy: OpaqueBytes): OpaqueBytesSubSequence = OpaqueBytesSubSequence(proxy.bytes, proxy.offset, proxy.size)
|
||||
|
@ -3,13 +3,18 @@ package net.corda.serialization.internal.amqp.custom
|
||||
import net.corda.core.KeepForDJVM
|
||||
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||
import java.time.OffsetTime
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* A serializer for [Optional] that uses a proxy object to write out the value stored in the optional or [Optional.EMPTY].
|
||||
*/
|
||||
class OptionalSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Optional<*>, OptionalSerializer.OptionalProxy>(Optional::class.java, OptionalProxy::class.java, factory) {
|
||||
class OptionalSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<Optional<*>, OptionalSerializer.OptionalProxy>(
|
||||
Optional::class.java,
|
||||
OptionalProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
|
||||
public override fun toProxy(obj: java.util.Optional<*>): OptionalProxy {
|
||||
return OptionalProxy(obj.orElse(null))
|
||||
|
@ -8,7 +8,13 @@ import java.time.Period
|
||||
/**
|
||||
* A serializer for [Period] that uses a proxy object to write out the integer form.
|
||||
*/
|
||||
class PeriodSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Period, PeriodSerializer.PeriodProxy>(Period::class.java, PeriodProxy::class.java, factory) {
|
||||
class PeriodSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<Period, PeriodSerializer.PeriodProxy>(
|
||||
Period::class.java,
|
||||
PeriodProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: Period): PeriodProxy = PeriodProxy(obj.years, obj.months, obj.days)
|
||||
|
||||
override fun fromProxy(proxy: PeriodProxy): Period = Period.of(proxy.years, proxy.months, proxy.days)
|
||||
|
@ -9,9 +9,19 @@ import org.apache.qpid.proton.codec.Data
|
||||
import java.lang.reflect.Type
|
||||
import java.security.PrivateKey
|
||||
|
||||
object PrivateKeySerializer : CustomSerializer.Implements<PrivateKey>(PrivateKey::class.java) {
|
||||
object PrivateKeySerializer
|
||||
: CustomSerializer.Implements<PrivateKey>(
|
||||
PrivateKey::class.java
|
||||
) {
|
||||
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), AMQPTypeIdentifiers.primitiveTypeName(ByteArray::class.java), descriptor, emptyList())))
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(
|
||||
type.toString(),
|
||||
"",
|
||||
listOf(type.toString()),
|
||||
AMQPTypeIdentifiers.primitiveTypeName(ByteArray::class.java),
|
||||
descriptor,
|
||||
emptyList()
|
||||
)))
|
||||
|
||||
override fun writeDescribedObject(obj: PrivateKey, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext
|
||||
|
@ -10,8 +10,18 @@ import java.security.PublicKey
|
||||
/**
|
||||
* A serializer that writes out a public key in X.509 format.
|
||||
*/
|
||||
object PublicKeySerializer : CustomSerializer.Implements<PublicKey>(PublicKey::class.java) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), AMQPTypeIdentifiers.primitiveTypeName(ByteArray::class.java), descriptor, emptyList())))
|
||||
object PublicKeySerializer
|
||||
: CustomSerializer.Implements<PublicKey>(
|
||||
PublicKey::class.java
|
||||
) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(
|
||||
type.toString(),
|
||||
"",
|
||||
listOf(type.toString()),
|
||||
AMQPTypeIdentifiers.primitiveTypeName(ByteArray::class.java),
|
||||
descriptor,
|
||||
emptyList()
|
||||
)))
|
||||
|
||||
override fun writeDescribedObject(obj: PublicKey, data: Data, type: Type, output: SerializationOutput,
|
||||
context: SerializationContext
|
||||
|
@ -11,7 +11,13 @@ import net.corda.serialization.internal.model.LocalTypeInformation
|
||||
import java.io.NotSerializableException
|
||||
|
||||
@KeepForDJVM
|
||||
class ThrowableSerializer(factory: LocalSerializerFactory) : CustomSerializer.Proxy<Throwable, ThrowableSerializer.ThrowableProxy>(Throwable::class.java, ThrowableProxy::class.java, factory) {
|
||||
class ThrowableSerializer(
|
||||
factory: LocalSerializerFactory
|
||||
) : CustomSerializer.Proxy<Throwable, ThrowableSerializer.ThrowableProxy>(
|
||||
Throwable::class.java,
|
||||
ThrowableProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private val logger = contextLogger()
|
||||
|
@ -7,7 +7,10 @@ import java.lang.reflect.Type
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509CRL
|
||||
|
||||
object X509CRLSerializer : CustomSerializer.Implements<X509CRL>(X509CRL::class.java) {
|
||||
object X509CRLSerializer
|
||||
: CustomSerializer.Implements<X509CRL>(
|
||||
X509CRL::class.java
|
||||
) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(
|
||||
type.toString(),
|
||||
"",
|
||||
|
@ -7,7 +7,10 @@ import java.lang.reflect.Type
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
object X509CertificateSerializer : CustomSerializer.Implements<X509Certificate>(X509Certificate::class.java) {
|
||||
object X509CertificateSerializer
|
||||
: CustomSerializer.Implements<X509Certificate>(
|
||||
X509Certificate::class.java
|
||||
) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(
|
||||
type.toString(),
|
||||
"",
|
||||
|
@ -8,7 +8,13 @@ import java.time.YearMonth
|
||||
/**
|
||||
* A serializer for [YearMonth] that uses a proxy object to write out the integer form.
|
||||
*/
|
||||
class YearMonthSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<YearMonth, YearMonthSerializer.YearMonthProxy>(YearMonth::class.java, YearMonthProxy::class.java, factory) {
|
||||
class YearMonthSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<YearMonth, YearMonthSerializer.YearMonthProxy>(
|
||||
YearMonth::class.java,
|
||||
YearMonthProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: YearMonth): YearMonthProxy = YearMonthProxy(obj.year, obj.monthValue.toByte())
|
||||
|
||||
override fun fromProxy(proxy: YearMonthProxy): YearMonth = YearMonth.of(proxy.year, proxy.month.toInt())
|
||||
|
@ -8,7 +8,13 @@ import java.time.Year
|
||||
/**
|
||||
* A serializer for [Year] that uses a proxy object to write out the integer form.
|
||||
*/
|
||||
class YearSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Year, YearSerializer.YearProxy>(Year::class.java, YearProxy::class.java, factory) {
|
||||
class YearSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<Year, YearSerializer.YearProxy>(
|
||||
Year::class.java,
|
||||
YearProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override fun toProxy(obj: Year): YearProxy = YearProxy(obj.value)
|
||||
|
||||
override fun fromProxy(proxy: YearProxy): Year = Year.of(proxy.year)
|
||||
|
@ -8,7 +8,13 @@ import java.time.ZoneId
|
||||
/**
|
||||
* A serializer for [ZoneId] that uses a proxy object to write out the string form.
|
||||
*/
|
||||
class ZoneIdSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<ZoneId, ZoneIdSerializer.ZoneIdProxy>(ZoneId::class.java, ZoneIdProxy::class.java, factory) {
|
||||
class ZoneIdSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<ZoneId, ZoneIdSerializer.ZoneIdProxy>(
|
||||
ZoneId::class.java,
|
||||
ZoneIdProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
override val revealSubclassesInSchema: Boolean = true
|
||||
|
||||
override fun toProxy(obj: ZoneId): ZoneIdProxy = ZoneIdProxy(obj.id)
|
||||
|
@ -12,22 +12,41 @@ import java.time.ZonedDateTime
|
||||
/**
|
||||
* A serializer for [ZonedDateTime] that uses a proxy object to write out the date, time, offset and zone.
|
||||
*/
|
||||
class ZonedDateTimeSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<ZonedDateTime, ZonedDateTimeSerializer.ZonedDateTimeProxy>(ZonedDateTime::class.java, ZonedDateTimeProxy::class.java, factory) {
|
||||
class ZonedDateTimeSerializer(
|
||||
factory: SerializerFactory
|
||||
) : CustomSerializer.Proxy<ZonedDateTime, ZonedDateTimeSerializer.ZonedDateTimeProxy>(
|
||||
ZonedDateTime::class.java,
|
||||
ZonedDateTimeProxy::class.java,
|
||||
factory
|
||||
) {
|
||||
// Java deserialization of `ZonedDateTime` uses a private method. We will resolve this somewhat statically
|
||||
// so that any change to internals of `ZonedDateTime` is detected early.
|
||||
companion object {
|
||||
val ofLenient: Method = ZonedDateTime::class.java.getDeclaredMethod("ofLenient", LocalDateTime::class.java, ZoneOffset::class.java, ZoneId::class.java)
|
||||
val ofLenient: Method = ZonedDateTime::class.java.getDeclaredMethod(
|
||||
"ofLenient",
|
||||
LocalDateTime::class.java,
|
||||
ZoneOffset::class.java,
|
||||
ZoneId::class.java
|
||||
)
|
||||
|
||||
init {
|
||||
ofLenient.isAccessible = true
|
||||
}
|
||||
}
|
||||
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(LocalDateTimeSerializer(factory), ZoneIdSerializer(factory))
|
||||
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = listOf(
|
||||
LocalDateTimeSerializer(factory),
|
||||
ZoneIdSerializer(factory)
|
||||
)
|
||||
|
||||
override fun toProxy(obj: ZonedDateTime): ZonedDateTimeProxy = ZonedDateTimeProxy(obj.toLocalDateTime(), obj.offset, obj.zone)
|
||||
|
||||
override fun fromProxy(proxy: ZonedDateTimeProxy): ZonedDateTime = ofLenient.invoke(null, proxy.dateTime, proxy.offset, proxy.zone) as ZonedDateTime
|
||||
override fun fromProxy(proxy: ZonedDateTimeProxy): ZonedDateTime = ofLenient.invoke(
|
||||
null,
|
||||
proxy.dateTime,
|
||||
proxy.offset,
|
||||
proxy.zone
|
||||
) as ZonedDateTime
|
||||
|
||||
@KeepForDJVM
|
||||
data class ZonedDateTimeProxy(val dateTime: LocalDateTime, val offset: ZoneOffset, val zone: ZoneId)
|
||||
|
Loading…
Reference in New Issue
Block a user