Refactoring changes to work with interface changes

Specifically we don't need the factory factory as that functionality
lives in the global defaults
This commit is contained in:
Katelyn Baker 2017-08-15 14:14:21 +01:00
parent 139eef2ccb
commit 825908cf15
11 changed files with 55 additions and 78 deletions

View File

@ -47,8 +47,9 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
}
fun getSerializerFactory(): SerializerFactory {
return serializerFactoriesForContexts.computeIfAbsent(Pair(AllWhitelist, deserializationClassLoader)) {
SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
return serializerFactoriesForContexts.computeIfAbsent(Pair(
AllWhitelist, SerializationDefaults.javaClass.classLoader)) {
SerializerFactory(AllWhitelist, SerializationDefaults.javaClass.classLoader)
}
}

View File

@ -6,13 +6,9 @@ import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationFactory
import net.corda.core.serialization.SerializedBytes
import net.corda.core.utilities.sequence
import net.corda.nodeapi.internal.serialization.amqp.AmqpHeaderV1_0
import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import net.corda.nodeapi.internal.serialization.amqp.SerializationOutput
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactoryFactory
/**
* This [Kryo] custom [Serializer] switches the object graph of anything annotated with `@CordaSerializable`

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.SerializationDefaults
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type
@ -68,26 +69,26 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
}
/**
* Additional base features for a custom serializer for a particular class, that excludes subclasses.
* Additional base features for a custom serializer for a particular class [withInheritance] is false
* or super class / interfaces [withInheritance] is true
*/
abstract class Is<T>(protected val clazz: Class<T>) : CustomSerializer<T>() {
override fun isSerializerFor(clazz: Class<*>): Boolean = clazz == this.clazz
abstract class CustomSerializerImp<T>(protected val clazz: Class<T>, protected val withInheritance: Boolean) : CustomSerializer<T>() {
override val type: Type get() = clazz
override val typeDescriptor: String = "$DESCRIPTOR_DOMAIN:${nameForType(clazz)}"
override fun writeClassInfo(output: SerializationOutput) {}
override val descriptor: Descriptor = Descriptor(typeDescriptor)
override fun isSerializerFor(clazz: Class<*>): Boolean = if (withInheritance) this.clazz.isAssignableFrom(clazz) else this.clazz == clazz
}
/**
* Additional base features for a custom serializer for a particular class, that excludes subclasses.
*/
abstract class Is<T>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, false)
/**
* Additional base features for a custom serializer for all implementations of a particular interface or super class.
*/
abstract class Implements<T>(protected val clazz: Class<T>) : CustomSerializer<T>() {
override fun isSerializerFor(clazz: Class<*>): Boolean = this.clazz.isAssignableFrom(clazz)
override val type: Type get() = clazz
override val typeDescriptor: String = "$DESCRIPTOR_DOMAIN:${nameForType(clazz)}"
override fun writeClassInfo(output: SerializationOutput) {}
override val descriptor: Descriptor = Descriptor(typeDescriptor)
}
abstract class Implements<T>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, true)
/**
* Additional base features over and above [Implements] or [Is] custom serializer for when the serialized form should be
@ -96,15 +97,11 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* The proxy class must use only types which are either native AMQP or other types for which there are pre-registered
* custom serializers.
*/
abstract class Proxy<T, P>(protected val clazz: Class<T>,
abstract class Proxy<T, P>(clazz: Class<T>,
protected val proxyClass: Class<P>,
protected val factory: SerializerFactory,
val withInheritance: Boolean = true) : CustomSerializer<T>() {
withInheritance: Boolean = true) : CustomSerializerImp<T>(clazz, withInheritance) {
override fun isSerializerFor(clazz: Class<*>): Boolean = if (withInheritance) this.clazz.isAssignableFrom(clazz) else this.clazz == clazz
override val type: Type get() = clazz
override val typeDescriptor: String = "$DESCRIPTOR_DOMAIN:${nameForType(clazz)}"
override fun writeClassInfo(output: SerializationOutput) {}
override val descriptor: Descriptor = Descriptor(typeDescriptor)
private val proxySerializer: ObjectSerializer by lazy { ObjectSerializer(proxyClass, factory) }
@ -152,26 +149,26 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
*/
abstract class ToString<T>(clazz: Class<T>, withInheritance: Boolean = false,
private val maker: (String) -> T = clazz.getConstructor(String::class.java).let {
`constructor` -> { string -> `constructor`.newInstance(string) }
`constructor` ->
{ string -> `constructor`.newInstance(string) }
},
private val unmaker: (T) -> String = { obj -> obj.toString() }) : Proxy<T, String>(clazz, String::class.java, /* Unused */ SerializerFactoryFactory.get(), withInheritance) {
private val unmaker: (T) -> String = { obj -> obj.toString() })
: CustomSerializerImp<T>(clazz, withInheritance) {
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = emptyList()
override val schemaForDocumentation = Schema(listOf(RestrictedType(nameForType(type), "", listOf(nameForType(type)), SerializerFactory.primitiveTypeName(String::class.java)!!, descriptor, emptyList())))
override fun toProxy(obj: T): String = unmaker(obj)
override fun fromProxy(proxy: String): T = maker(proxy)
override val schemaForDocumentation = Schema(
listOf(RestrictedType(nameForType(type), "", listOf(nameForType(type)),
SerializerFactory.primitiveTypeName(String::class.java)!!,
descriptor, emptyList())))
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
val proxy = toProxy(obj)
data.putObject(proxy)
data.putObject(unmaker(obj))
}
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): T {
val proxy = input.readObject(obj, schema, String::class.java) as String
return fromProxy(proxy)
return maker(proxy)
}
}
}

View File

@ -20,7 +20,7 @@ data class ObjectAndEnvelope<out T>(val obj: T, val envelope: Envelope)
* @param serializerFactory This is the factory for [AMQPSerializer] instances and can be shared across multiple
* instances and threads.
*/
class DeserializationInput(internal val serializerFactory: SerializerFactory = SerializerFactoryFactory.get()) {
class DeserializationInput(internal val serializerFactory: SerializerFactory) {
// TODO: we're not supporting object refs yet
private val objectHistory: MutableList<Any> = ArrayList()

View File

@ -14,7 +14,7 @@ import kotlin.collections.LinkedHashSet
* @param serializerFactory This is the factory for [AMQPSerializer] instances and can be shared across multiple
* instances and threads.
*/
open class SerializationOutput(internal val serializerFactory: SerializerFactory = SerializerFactoryFactory.get()) {
open class SerializationOutput(internal val serializerFactory: SerializerFactory) {
// TODO: we're not supporting object refs yet
private val objectHistory: MutableMap<Any, Int> = IdentityHashMap()
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()

View File

@ -1,22 +0,0 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.ClassWhitelist
import net.corda.nodeapi.internal.serialization.AllWhitelist
/**
* Factory singleton that maps unique Serializer Factories from a pair of WhitleList and ClassLoader
*/
object SerializerFactoryFactory {
val factories : MutableMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory> = mutableMapOf()
fun get(context: SerializationContext) : SerializerFactory =
factories.computeIfAbsent(Pair(context.whitelist, context.deserializationClassLoader)) {
SerializerFactory(context.whitelist, context.deserializationClassLoader)
}
fun get() : SerializerFactory =
factories.computeIfAbsent(Pair(AllWhitelist, ClassLoader.getSystemClassLoader())) {
SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
}
}

View File

@ -1,10 +1,14 @@
package net.corda.nodeapi.internal.serialization.amqp
import org.apache.qpid.proton.codec.Data
import net.corda.nodeapi.internal.serialization.AllWhitelist
fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
class TestSerializationOutput(
private val verbose: Boolean,
serializerFactory: SerializerFactory = SerializerFactoryFactory.get()) : SerializationOutput(serializerFactory) {
serializerFactory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()))
: SerializationOutput(serializerFactory) {
override fun writeSchema(schema: Schema, data: Data) {
if (verbose) println(schema)

View File

@ -18,7 +18,7 @@ class DeserializeAndReturnEnvelopeTests {
val a = A(10, "20")
val factory = SerializerFactoryFactory.get()
val factory = testDefaultFactory()
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
@ -34,7 +34,7 @@ class DeserializeAndReturnEnvelopeTests {
val b = B(A(10, "20"), 30.0F)
val factory = SerializerFactoryFactory.get()
val factory = testDefaultFactory()
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))

View File

@ -16,30 +16,30 @@ class DeserializeSimpleTypesTests {
private const val VERBOSE = false
}
val sf1 = SerializerFactory()
val sf2 = SerializerFactory()
val sf1 = testDefaultFactory()
val sf2 = testDefaultFactory()
@Test
fun testChar() {
data class C(val c: Char)
var deserializedC = DeserializationInput().deserialize(SerializationOutput().serialize(C('c')))
var deserializedC = DeserializationInput(sf).deserialize(SerializationOutput(sf).serialize(C('c')))
assertEquals('c', deserializedC.c)
// CYRILLIC CAPITAL LETTER YU (U+042E)
deserializedC = DeserializationInput().deserialize(SerializationOutput().serialize(C('Ю')))
deserializedC = DeserializationInput(sf).deserialize(SerializationOutput(sf).serialize(C('Ю')))
assertEquals('Ю', deserializedC.c)
// ARABIC LETTER FEH WITH DOT BELOW (U+06A3)
deserializedC = DeserializationInput().deserialize(SerializationOutput().serialize(C('ڣ')))
deserializedC = DeserializationInput(sf).deserialize(SerializationOutput(sf).serialize(C('ڣ')))
assertEquals('ڣ', deserializedC.c)
// ARABIC LETTER DAD WITH DOT BELOW (U+06FB)
deserializedC = DeserializationInput().deserialize(SerializationOutput().serialize(C('ۻ')))
deserializedC = DeserializationInput(sf).deserialize(SerializationOutput(sf).serialize(C('ۻ')))
assertEquals('ۻ', deserializedC.c)
// BENGALI LETTER AA (U+0986)
deserializedC = DeserializationInput().deserialize(SerializationOutput().serialize(C('আ')))
deserializedC = DeserializationInput(sf).deserialize(SerializationOutput(sf).serialize(C('আ')))
assertEquals('আ', deserializedC.c)
}
@ -49,8 +49,8 @@ class DeserializeSimpleTypesTests {
data class C(val c: Character)
val c = C(Character('c'))
val serialisedC = SerializationOutput().serialize(c)
val deserializedC = DeserializationInput().deserialize(serialisedC)
val serialisedC = SerializationOutput(sf).serialize(c)
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
assertEquals(c.c, deserializedC.c)
}
@ -60,8 +60,8 @@ class DeserializeSimpleTypesTests {
data class C(val c: Char?)
val c = C(null)
val serialisedC = SerializationOutput().serialize(c)
val deserializedC = DeserializationInput().deserialize(serialisedC)
val serialisedC = SerializationOutput(sf).serialize(c)
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
assertEquals(c.c, deserializedC.c)
}

View File

@ -14,6 +14,9 @@ import net.corda.nodeapi.RPCException
import net.corda.nodeapi.internal.serialization.AbstractAMQPSerializationScheme
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import net.corda.nodeapi.internal.serialization.AMQPServerSerializationScheme
import net.corda.nodeapi.internal.serialization.AllWhitelist
import net.corda.testing.MEGA_CORP
import net.corda.testing.MEGA_CORP_PUBKEY
import org.apache.qpid.proton.amqp.*
@ -135,7 +138,8 @@ class SerializationOutputTests {
data class PolymorphicProperty(val foo: FooInterface?)
private fun serdes(obj: Any,
factory: SerializerFactory = SerializerFactoryFactory.get(),
factory: SerializerFactory = SerializerFactory (
AllWhitelist, ClassLoader.getSystemClassLoader()),
freshDeserializationFactory: SerializerFactory = SerializerFactory(
AllWhitelist, ClassLoader.getSystemClassLoader()),
expectedEqual: Boolean = true,
@ -527,10 +531,10 @@ class SerializationOutputTests {
fun `test transaction state`() {
val state = TransactionState(FooState(), MEGA_CORP)
val factory = SerializerFactory()
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
AbstractAMQPSerializationScheme.registerCustomSerializers(factory)
val factory2 = SerializerFactory()
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
AbstractAMQPSerializationScheme.registerCustomSerializers(factory2)
val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false)

View File

@ -1,11 +1,8 @@
package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.nodeapi.internal.serialization.amqp.*
import net.corda.nodeapi.internal.serialization.amqp.Field
import net.corda.nodeapi.internal.serialization.amqp.Schema
import net.corda.nodeapi.internal.serialization.amqp.TypeNotation
import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.nodeapi.internal.serialization.amqp.SerializationOutput
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactoryFactory
fun mangleName(name: String) = "${name}__carpenter"
@ -37,7 +34,7 @@ fun Schema.mangleNames(names: List<String>): Schema {
}
open class AmqpCarpenterBase {
var factory = SerializerFactoryFactory.get()
var factory = testDefaultFactory()
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
fun testName(): String = Thread.currentThread().stackTrace[2].methodName