Provide a map of Java primitive types as a configuration value.

This commit is contained in:
Chris Rankin 2019-08-19 11:51:49 +01:00
parent aa2f1029a6
commit bdd5d13655
4 changed files with 44 additions and 5 deletions

View File

@ -13,11 +13,16 @@ import net.corda.serialization.internal.carpenter.Schema
@Suppress("UNUSED")
fun createSerializerFactoryFactory(): SerializerFactoryFactory = DeterministicSerializerFactoryFactory()
/**
* Creates a [ClassCarpenter] suitable for the DJVM, i.e. one that doesn't work.
*/
fun createClassCarpenter(context: SerializationContext): ClassCarpenter = DummyClassCarpenter(context.whitelist, context.deserializationClassLoader)
private class DeterministicSerializerFactoryFactory : SerializerFactoryFactory {
override fun make(context: SerializationContext) =
SerializerFactoryBuilder.build(
whitelist = context.whitelist,
classCarpenter = DummyClassCarpenter(context.whitelist, context.deserializationClassLoader))
classCarpenter = createClassCarpenter(context))
}
private class DummyClassCarpenter(

View File

@ -3,14 +3,21 @@
package net.corda.serialization.internal.amqp
import net.corda.core.serialization.SerializationContext
import net.corda.serialization.internal.carpenter.ClassCarpenter
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
fun createSerializerFactoryFactory(): SerializerFactoryFactory = SerializerFactoryFactoryImpl()
fun createClassCarpenter(context: SerializationContext): ClassCarpenter = ClassCarpenterImpl(
whitelist = context.whitelist,
cl = context.deserializationClassLoader,
lenient = context.lenientCarpenterEnabled
)
open class SerializerFactoryFactoryImpl : SerializerFactoryFactory {
override fun make(context: SerializationContext): SerializerFactory {
return SerializerFactoryBuilder.build(context.whitelist,
ClassCarpenterImpl(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled),
createClassCarpenter(context),
mustPreserveDataWhenEvolving = context.preventDataLoss
)
}

View File

@ -17,6 +17,13 @@ interface EvolutionSerializerFactory {
fun getEvolutionSerializer(
remote: RemoteTypeInformation,
local: LocalTypeInformation): AMQPSerializer<Any>?
/**
* A mapping between Java object types and their equivalent Java primitive types.
* Predominantly for the sake of the DJVM sandbox where e.g. `char` will map to
* sandbox.java.lang.Character instead of java.lang.Character.
*/
val primitiveTypes: Map<Class<*>, Class<*>>
}
class EvolutionSerializationException(remoteTypeInformation: RemoteTypeInformation, reason: String)
@ -32,7 +39,9 @@ class EvolutionSerializationException(remoteTypeInformation: RemoteTypeInformati
class DefaultEvolutionSerializerFactory(
private val localSerializerFactory: LocalSerializerFactory,
private val classLoader: ClassLoader,
private val mustPreserveDataWhenEvolving: Boolean): EvolutionSerializerFactory {
private val mustPreserveDataWhenEvolving: Boolean,
override val primitiveTypes: Map<Class<*>, Class<*>>
): EvolutionSerializerFactory {
override fun getEvolutionSerializer(remote: RemoteTypeInformation,
local: LocalTypeInformation): AMQPSerializer<Any>? =
@ -77,7 +86,7 @@ class DefaultEvolutionSerializerFactory(
val localClass = localProperty.type.observedType.asClass()
val remoteClass = remoteProperty.type.typeIdentifier.getLocalType(classLoader).asClass()
if (!localClass.isAssignableFrom(remoteClass) && remoteClass != localClass.kotlin.javaPrimitiveType) {
if (!localClass.isAssignableFrom(remoteClass) && remoteClass != primitiveTypes[localClass]) {
throw EvolutionSerializationException(this,
"Local type $localClass of property $name is not assignable from remote type $remoteClass")
}

View File

@ -7,9 +7,24 @@ import net.corda.serialization.internal.carpenter.ClassCarpenter
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import net.corda.serialization.internal.model.*
import java.io.NotSerializableException
import java.util.Collections.unmodifiableMap
@KeepForDJVM
object SerializerFactoryBuilder {
/**
* The standard mapping of Java object types to Java primitive types.
* The DJVM will need to override these, but probably not anyone else.
*/
private val javaPrimitiveTypes: Map<Class<*>, Class<*>> = unmodifiableMap(mapOf<Class<out Any>?, Class<out Any>?>(
Boolean::class.javaObjectType to Boolean::class.javaPrimitiveType,
Byte::class.javaObjectType to Byte::class.javaPrimitiveType,
Char::class.javaObjectType to Char::class.javaPrimitiveType,
Double::class.javaObjectType to Double::class.javaPrimitiveType,
Float::class.javaObjectType to Float::class.javaPrimitiveType,
Int::class.javaObjectType to Int::class.javaPrimitiveType,
Long::class.javaObjectType to Long::class.javaPrimitiveType,
Short::class.javaObjectType to Short::class.javaPrimitiveType
)) as Map<Class<*>, Class<*>>
@JvmStatic
fun build(whitelist: ClassWhitelist, classCarpenter: ClassCarpenter): SerializerFactory {
@ -99,7 +114,8 @@ object SerializerFactoryBuilder {
val evolutionSerializerFactory = if (allowEvolution) DefaultEvolutionSerializerFactory(
localSerializerFactory,
classCarpenter.classloader,
mustPreserveDataWhenEvolving
mustPreserveDataWhenEvolving,
javaPrimitiveTypes
) else NoEvolutionSerializerFactory
val remoteSerializerFactory = DefaultRemoteSerializerFactory(
@ -127,4 +143,6 @@ Local:
${localTypeInformation.prettyPrint(false)}
""")
}
override val primitiveTypes: Map<Class<*>, Class<*>> = emptyMap()
}