Use LocalTypeIdentifier information where available to lookup CustomSerializer.

This commit is contained in:
Chris Rankin 2019-08-18 19:45:00 +01:00
parent be64c89515
commit aa2f1029a6
4 changed files with 36 additions and 6 deletions

View File

@ -44,7 +44,7 @@ interface CustomSerializerRegistry {
* *
* @param clazz The actual class to look for a custom serializer for. * @param clazz The actual class to look for a custom serializer for.
* @param declaredType The declared type to look for a custom serializer for. * @param declaredType The declared type to look for a custom serializer for.
* @return The custom serializer handing the class, if found, or `null`. * @return The custom serializer handling the class, if found, or `null`.
* *
* @throws IllegalCustomSerializerException If a custom serializer identifies itself as the serializer for * @throws IllegalCustomSerializerException If a custom serializer identifies itself as the serializer for
* a class annotated with [CordaSerializable], since all such classes should be serializable via standard object * a class annotated with [CordaSerializable], since all such classes should be serializable via standard object

View File

@ -6,6 +6,8 @@ import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug import net.corda.core.utilities.debug
import net.corda.core.utilities.trace import net.corda.core.utilities.trace
import net.corda.serialization.internal.model.* import net.corda.serialization.internal.model.*
import net.corda.serialization.internal.model.TypeIdentifier.*
import net.corda.serialization.internal.model.TypeIdentifier.Companion.classLoaderFor
import org.apache.qpid.proton.amqp.Symbol import org.apache.qpid.proton.amqp.Symbol
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type import java.lang.reflect.Type
@ -137,9 +139,18 @@ class DefaultLocalSerializerFactory(
serializersByTypeId.getOrPut(localTypeInformation.typeIdentifier) { serializersByTypeId.getOrPut(localTypeInformation.typeIdentifier) {
val declaredClass = declaredType.asClass() val declaredClass = declaredType.asClass()
// Any Custom Serializer cached for a ParameterizedType can only be
// found by searching for that exact same type. Searching for its raw
// class will not work!
val declaredGenericType = if (declaredType !is ParameterizedType && localTypeInformation.typeIdentifier is Parameterised) {
localTypeInformation.typeIdentifier.getLocalType(classLoaderFor(declaredClass))
} else {
declaredType
}
// can be useful to enable but will be *extremely* chatty if you do // can be useful to enable but will be *extremely* chatty if you do
logger.trace { "Get Serializer for $declaredClass ${declaredType.typeName}" } logger.trace { "Get Serializer for $declaredClass ${declaredGenericType.typeName}" }
customSerializerRegistry.findCustomSerializer(declaredClass, declaredType)?.apply { return@get this } customSerializerRegistry.findCustomSerializer(declaredClass, declaredGenericType)?.apply { return@get this }
return when (localTypeInformation) { return when (localTypeInformation) {
is LocalTypeInformation.ACollection -> makeDeclaredCollection(localTypeInformation) is LocalTypeInformation.ACollection -> makeDeclaredCollection(localTypeInformation)

View File

@ -63,6 +63,8 @@ sealed class TypeIdentifier {
// This method has locking. So we memo the value here. // This method has locking. So we memo the value here.
private val systemClassLoader: ClassLoader = ClassLoader.getSystemClassLoader() private val systemClassLoader: ClassLoader = ClassLoader.getSystemClassLoader()
fun classLoaderFor(clazz: Class<*>): ClassLoader = clazz.classLoader ?: systemClassLoader
/** /**
* Obtain the [TypeIdentifier] for an erased Java class. * Obtain the [TypeIdentifier] for an erased Java class.
* *

View File

@ -4,7 +4,9 @@ import com.google.common.hash.Hashing
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.toBase64 import net.corda.core.utilities.toBase64
import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.*
import java.io.NotSerializableException import net.corda.serialization.internal.model.TypeIdentifier.*
import net.corda.serialization.internal.model.TypeIdentifier.Companion.classLoaderFor
import java.lang.reflect.ParameterizedType
/** /**
* A fingerprinter that fingerprints [LocalTypeInformation]. * A fingerprinter that fingerprints [LocalTypeInformation].
@ -224,7 +226,22 @@ private class FingerPrintingState(
// Give any custom serializers loaded into the factory the chance to supply their own type-descriptors // Give any custom serializers loaded into the factory the chance to supply their own type-descriptors
private fun fingerprintWithCustomSerializerOrElse(type: LocalTypeInformation, defaultAction: () -> Unit) { private fun fingerprintWithCustomSerializerOrElse(type: LocalTypeInformation, defaultAction: () -> Unit) {
val customTypeDescriptor = customSerializerRegistry.findCustomSerializer(type.observedType.asClass(), type.observedType)?.typeDescriptor?.toString() val observedType = type.observedType
val observedClass = observedType.asClass()
// Any Custom Serializer cached for a ParameterizedType can only be
// found by searching for that exact same type. Searching for its raw
// class will not work!
val observedGenericType = if (observedType !is ParameterizedType && type.typeIdentifier is Parameterised) {
type.typeIdentifier.getLocalType(classLoaderFor(observedClass))
} else {
observedType
}
val customTypeDescriptor = customSerializerRegistry.findCustomSerializer(
clazz = observedClass,
declaredType = observedGenericType
)?.typeDescriptor?.toString()
if (customTypeDescriptor != null) writer.write(customTypeDescriptor) if (customTypeDescriptor != null) writer.write(customTypeDescriptor)
else defaultAction() else defaultAction()
} }