Merge pull request #1252 from corda/feature/kat/moveAMQPSerialiserTowardCommonInterface

Move AMQP serialiser toward common interface
This commit is contained in:
Katelyn Baker
2017-08-17 09:43:30 +01:00
committed by GitHub
21 changed files with 261 additions and 253 deletions

View File

@ -41,7 +41,7 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
rpcClientSerializerFactory(context) rpcClientSerializerFactory(context)
SerializationContext.UseCase.RPCServer -> SerializationContext.UseCase.RPCServer ->
rpcServerSerializerFactory(context) rpcServerSerializerFactory(context)
else -> SerializerFactory(context.whitelist) // TODO pass class loader also else -> SerializerFactory(context.whitelist, context.deserializationClassLoader)
} }
}.also { registerCustomSerializers(it) } }.also { registerCustomSerializers(it) }
} }

View File

@ -6,12 +6,9 @@ import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationFactory import net.corda.core.serialization.SerializationFactory
import net.corda.core.serialization.SerializedBytes
import net.corda.core.utilities.sequence import net.corda.core.utilities.sequence
import net.corda.nodeapi.internal.serialization.amqp.AmqpHeaderV1_0 import net.corda.nodeapi.internal.serialization.amqp.AmqpHeaderV1_0
import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput import net.corda.nodeapi.internal.serialization.amqp.DeserializationInput
import net.corda.nodeapi.internal.serialization.amqp.SerializationOutput
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
/** /**
* This [Kryo] custom [Serializer] switches the object graph of anything annotated with `@CordaSerializable` * This [Kryo] custom [Serializer] switches the object graph of anything annotated with `@CordaSerializable`
@ -34,4 +31,4 @@ class KryoAMQPSerializer(val serializationFactory: SerializationFactory, val ser
input.readBytes(allBytes, peekedBytes.size, size - peekedBytes.size) input.readBytes(allBytes, peekedBytes.size, size - peekedBytes.size)
return serializationFactory.deserialize(allBytes.sequence(), type, serializationContext) return serializationFactory.deserialize(allBytes.sequence(), type, serializationContext)
} }
} }

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.amqp package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.serialization.SerializationDefaults
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type 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>() { abstract class CustomSerializerImp<T>(protected val clazz: Class<T>, protected val withInheritance: Boolean) : CustomSerializer<T>() {
override fun isSerializerFor(clazz: Class<*>): Boolean = clazz == this.clazz
override val type: Type get() = clazz override val type: Type get() = clazz
override val typeDescriptor: String = "$DESCRIPTOR_DOMAIN:${nameForType(clazz)}" override val typeDescriptor: String = "$DESCRIPTOR_DOMAIN:${nameForType(clazz)}"
override fun writeClassInfo(output: SerializationOutput) {} override fun writeClassInfo(output: SerializationOutput) {}
override val descriptor: Descriptor = Descriptor(typeDescriptor) 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. * 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>() { abstract class Implements<T>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, true)
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)
}
/** /**
* Additional base features over and above [Implements] or [Is] custom serializer for when the serialized form should be * 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 * The proxy class must use only types which are either native AMQP or other types for which there are pre-registered
* custom serializers. * 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 proxyClass: Class<P>,
protected val factory: SerializerFactory, 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 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) } private val proxySerializer: ObjectSerializer by lazy { ObjectSerializer(proxyClass, factory) }
@ -151,25 +148,27 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* @param unmake A lambda that extracts the string value for an instance, that defaults to the [toString] method. * @param unmake A lambda that extracts the string value for an instance, that defaults to the [toString] method.
*/ */
abstract class ToString<T>(clazz: Class<T>, withInheritance: Boolean = false, 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) } }, private val maker: (String) -> T = clazz.getConstructor(String::class.java).let {
private val unmaker: (T) -> String = { obj -> obj.toString() }) : Proxy<T, String>(clazz, String::class.java, /* Unused */ SerializerFactory(), withInheritance) { `constructor` ->
{ string -> `constructor`.newInstance(string) }
},
private val unmaker: (T) -> String = { obj -> obj.toString() })
: CustomSerializerImp<T>(clazz, withInheritance) {
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = emptyList() 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 val schemaForDocumentation = Schema(
listOf(RestrictedType(nameForType(type), "", listOf(nameForType(type)),
override fun toProxy(obj: T): String = unmaker(obj) SerializerFactory.primitiveTypeName(String::class.java)!!,
descriptor, emptyList())))
override fun fromProxy(proxy: String): T = maker(proxy)
override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) { override fun writeDescribedObject(obj: T, data: Data, type: Type, output: SerializationOutput) {
val proxy = toProxy(obj) data.putObject(unmaker(obj))
data.putObject(proxy)
} }
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): T { override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): T {
val proxy = input.readObject(obj, schema, String::class.java) as String 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 * @param serializerFactory This is the factory for [AMQPSerializer] instances and can be shared across multiple
* instances and threads. * instances and threads.
*/ */
class DeserializationInput(internal val serializerFactory: SerializerFactory = SerializerFactory()) { class DeserializationInput(internal val serializerFactory: SerializerFactory) {
// TODO: we're not supporting object refs yet // TODO: we're not supporting object refs yet
private val objectHistory: MutableList<Any> = ArrayList() 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 * @param serializerFactory This is the factory for [AMQPSerializer] instances and can be shared across multiple
* instances and threads. * instances and threads.
*/ */
open class SerializationOutput(internal val serializerFactory: SerializerFactory = SerializerFactory()) { open class SerializationOutput(internal val serializerFactory: SerializerFactory) {
// TODO: we're not supporting object refs yet // TODO: we're not supporting object refs yet
private val objectHistory: MutableMap<Any, Int> = IdentityHashMap() private val objectHistory: MutableMap<Any, Int> = IdentityHashMap()
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet() private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()

View File

@ -4,7 +4,6 @@ import com.google.common.primitives.Primitives
import com.google.common.reflect.TypeResolver import com.google.common.reflect.TypeResolver
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.nodeapi.internal.serialization.AllWhitelist
import net.corda.nodeapi.internal.serialization.carpenter.CarpenterSchemas import net.corda.nodeapi.internal.serialization.carpenter.CarpenterSchemas
import net.corda.nodeapi.internal.serialization.carpenter.ClassCarpenter import net.corda.nodeapi.internal.serialization.carpenter.ClassCarpenter
import net.corda.nodeapi.internal.serialization.carpenter.MetaCarpenter import net.corda.nodeapi.internal.serialization.carpenter.MetaCarpenter
@ -44,11 +43,13 @@ import javax.annotation.concurrent.ThreadSafe
// TODO: need to rethink matching of constructor to properties in relation to implementing interfaces and needing those properties etc. // TODO: need to rethink matching of constructor to properties in relation to implementing interfaces and needing those properties etc.
// TODO: need to support super classes as well as interfaces with our current code base... what's involved? If we continue to ban, what is the impact? // TODO: need to support super classes as well as interfaces with our current code base... what's involved? If we continue to ban, what is the impact?
@ThreadSafe @ThreadSafe
class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) { class SerializerFactory(val whitelist: ClassWhitelist, cl : ClassLoader) {
private val serializersByType = ConcurrentHashMap<Type, AMQPSerializer<Any>>() private val serializersByType = ConcurrentHashMap<Type, AMQPSerializer<Any>>()
private val serializersByDescriptor = ConcurrentHashMap<Any, AMQPSerializer<Any>>() private val serializersByDescriptor = ConcurrentHashMap<Any, AMQPSerializer<Any>>()
private val customSerializers = CopyOnWriteArrayList<CustomSerializer<out Any>>() private val customSerializers = CopyOnWriteArrayList<CustomSerializer<out Any>>()
private val classCarpenter = ClassCarpenter() private val classCarpenter = ClassCarpenter(cl)
val classloader : ClassLoader
get() = classCarpenter.classloader
/** /**
* Look up, and manufacture if necessary, a serializer for the given type. * Look up, and manufacture if necessary, a serializer for the given type.
@ -176,15 +177,18 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
} }
} }
private fun processSchema(schema: Schema, sentinal: Boolean = false) { /**
* Iterate over an AMQP schema, for each type ascertain weather it's on ClassPath of [classloader] amd
* if not use the [ClassCarpenter] to generate a class to use in it's place
*/
private fun processSchema(schema: Schema, sentinel: Boolean = false) {
val carpenterSchemas = CarpenterSchemas.newInstance() val carpenterSchemas = CarpenterSchemas.newInstance()
for (typeNotation in schema.types) { for (typeNotation in schema.types) {
try { try {
processSchemaEntry(typeNotation, classCarpenter.classloader) processSchemaEntry(typeNotation)
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
if (sentinal || (typeNotation !is CompositeType)) throw e if (sentinel || (typeNotation !is CompositeType)) throw e
typeNotation.carpenterSchema( typeNotation.carpenterSchema(classloader, carpenterSchemas = carpenterSchemas)
classLoaders = listOf(classCarpenter.classloader), carpenterSchemas = carpenterSchemas)
} }
} }
@ -195,24 +199,22 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
} }
} }
private fun processSchemaEntry(typeNotation: TypeNotation, private fun processSchemaEntry(typeNotation: TypeNotation) {
cl: ClassLoader = DeserializedParameterizedType::class.java.classLoader) {
when (typeNotation) { when (typeNotation) {
is CompositeType -> processCompositeType(typeNotation, cl) // java.lang.Class (whether a class or interface) is CompositeType -> processCompositeType(typeNotation) // java.lang.Class (whether a class or interface)
is RestrictedType -> processRestrictedType(typeNotation) // Collection / Map, possibly with generics is RestrictedType -> processRestrictedType(typeNotation) // Collection / Map, possibly with generics
} }
} }
private fun processRestrictedType(typeNotation: RestrictedType) { private fun processRestrictedType(typeNotation: RestrictedType) {
// TODO: class loader logic, and compare the schema. // TODO: class loader logic, and compare the schema.
val type = typeForName(typeNotation.name) val type = typeForName(typeNotation.name, classloader)
get(null, type) get(null, type)
} }
private fun processCompositeType(typeNotation: CompositeType, private fun processCompositeType(typeNotation: CompositeType) {
cl: ClassLoader = DeserializedParameterizedType::class.java.classLoader) {
// TODO: class loader logic, and compare the schema. // TODO: class loader logic, and compare the schema.
val type = typeForName(typeNotation.name, cl) val type = typeForName(typeNotation.name, classloader)
get(type.asClass() ?: throw NotSerializableException("Unable to build composite type for $type"), type) get(type.asClass() ?: throw NotSerializableException("Unable to build composite type for $type"), type)
} }
@ -322,11 +324,9 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
else -> throw NotSerializableException("Unable to render type $type to a string.") else -> throw NotSerializableException("Unable to render type $type to a string.")
} }
private fun typeForName( private fun typeForName(name: String, classloader: ClassLoader): Type {
name: String,
cl: ClassLoader = DeserializedParameterizedType::class.java.classLoader): Type {
return if (name.endsWith("[]")) { return if (name.endsWith("[]")) {
val elementType = typeForName(name.substring(0, name.lastIndex - 1)) val elementType = typeForName(name.substring(0, name.lastIndex - 1), classloader)
if (elementType is ParameterizedType || elementType is GenericArrayType) { if (elementType is ParameterizedType || elementType is GenericArrayType) {
DeserializedGenericArrayType(elementType) DeserializedGenericArrayType(elementType)
} else if (elementType is Class<*>) { } else if (elementType is Class<*>) {
@ -349,7 +349,7 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
else -> throw NotSerializableException("Not able to deserialize array type: $name") else -> throw NotSerializableException("Not able to deserialize array type: $name")
} }
} else { } else {
DeserializedParameterizedType.make(name, cl) DeserializedParameterizedType.make(name, classloader)
} }
} }
} }

View File

@ -4,13 +4,11 @@ import net.corda.nodeapi.internal.serialization.amqp.CompositeType
import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField
import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema
fun AMQPSchema.carpenterSchema( fun AMQPSchema.carpenterSchema(classloader: ClassLoader) : CarpenterSchemas {
loaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()))
: CarpenterSchemas {
val rtn = CarpenterSchemas.newInstance() val rtn = CarpenterSchemas.newInstance()
types.filterIsInstance<CompositeType>().forEach { types.filterIsInstance<CompositeType>().forEach {
it.carpenterSchema(classLoaders = loaders, carpenterSchemas = rtn) it.carpenterSchema(classloader, carpenterSchemas = rtn)
} }
return rtn return rtn
@ -19,10 +17,9 @@ fun AMQPSchema.carpenterSchema(
/** /**
* if we can load the class then we MUST know about all of it's composite elements * if we can load the class then we MUST know about all of it's composite elements
*/ */
private fun CompositeType.validatePropertyTypes( private fun CompositeType.validatePropertyTypes(classloader: ClassLoader) {
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())) {
fields.forEach { fields.forEach {
if (!it.validateType(classLoaders)) throw UncarpentableException(name, it.name, it.type) if (!it.validateType(classloader)) throw UncarpentableException(name, it.name, it.type)
} }
} }
@ -34,24 +31,21 @@ fun AMQPField.typeAsString() = if (type == "*") requires[0] else type
* b) add the class to the dependency tree in [carpenterSchemas] if it cannot be instantiated * b) add the class to the dependency tree in [carpenterSchemas] if it cannot be instantiated
* at this time * at this time
* *
* @param classLoaders list of classLoaders, defaulting toe the system class loader, that might * @param classloader the class loader provided dby the [SerializationContext]
* be used to load objects
* @param carpenterSchemas structure that holds the dependency tree and list of classes that * @param carpenterSchemas structure that holds the dependency tree and list of classes that
* need constructing * need constructing
* @param force by default a schema is not added to [carpenterSchemas] if it already exists * @param force by default a schema is not added to [carpenterSchemas] if it already exists
* on the class path. For testing purposes schema generation can be forced * on the class path. For testing purposes schema generation can be forced
*/ */
fun CompositeType.carpenterSchema( fun CompositeType.carpenterSchema(classloader: ClassLoader,
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()), carpenterSchemas: CarpenterSchemas,
carpenterSchemas: CarpenterSchemas, force: Boolean = false) {
force: Boolean = false) { if (classloader.exists(name)) {
if (classLoaders.exists(name)) { validatePropertyTypes(classloader)
validatePropertyTypes(classLoaders)
if (!force) return if (!force) return
} }
val providesList = mutableListOf<Class<*>>() val providesList = mutableListOf<Class<*>>()
var isInterface = false var isInterface = false
var isCreatable = true var isCreatable = true
@ -62,7 +56,7 @@ fun CompositeType.carpenterSchema(
} }
try { try {
providesList.add(classLoaders.loadIfExists(it)) providesList.add(classloader.loadClass(it))
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it) carpenterSchemas.addDepPair(this, name, it)
isCreatable = false isCreatable = false
@ -73,7 +67,7 @@ fun CompositeType.carpenterSchema(
fields.forEach { fields.forEach {
try { try {
m[it.name] = FieldFactory.newInstance(it.mandatory, it.name, it.getTypeAsClass(classLoaders)) m[it.name] = FieldFactory.newInstance(it.mandatory, it.name, it.getTypeAsClass(classloader))
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it.typeAsString()) carpenterSchemas.addDepPair(this, name, it.typeAsString())
isCreatable = false isCreatable = false
@ -110,33 +104,18 @@ val typeStrToType: Map<Pair<String, Boolean>, Class<out Any?>> = mapOf(
Pair("byte", false) to Byte::class.javaObjectType Pair("byte", false) to Byte::class.javaObjectType
) )
fun AMQPField.getTypeAsClass( fun AMQPField.getTypeAsClass(classloader: ClassLoader) = typeStrToType[Pair(type, mandatory)] ?: when (type) {
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())
) = typeStrToType[Pair(type, mandatory)] ?: when (type) {
"string" -> String::class.java "string" -> String::class.java
"*" -> classLoaders.loadIfExists(requires[0]) "*" -> classloader.loadClass(requires[0])
else -> classLoaders.loadIfExists(type) else -> classloader.loadClass(type)
} }
fun AMQPField.validateType( fun AMQPField.validateType(classloader: ClassLoader) = when (type) {
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())
) = when (type) {
"byte", "int", "string", "short", "long", "char", "boolean", "double", "float" -> true "byte", "int", "string", "short", "long", "char", "boolean", "double", "float" -> true
"*" -> classLoaders.exists(requires[0]) "*" -> classloader.exists(requires[0])
else -> classLoaders.exists(type) else -> classloader.exists(type)
} }
private fun List<ClassLoader>.exists(clazz: String) = this.find { private fun ClassLoader.exists(clazz: String) = run {
try { it.loadClass(clazz); true } catch (e: ClassNotFoundException) { false } try { this.loadClass(clazz); true } catch (e: ClassNotFoundException) { false } }
} != null
private fun List<ClassLoader>.loadIfExists(clazz: String): Class<*> {
this.forEach {
try {
return it.loadClass(clazz)
} catch (e: ClassNotFoundException) {
return@forEach
}
}
throw ClassNotFoundException(clazz)
}

View File

@ -18,7 +18,8 @@ interface SimpleFieldAccess {
operator fun get(name: String): Any? operator fun get(name: String): Any?
} }
class CarpenterClassLoader : ClassLoader(Thread.currentThread().contextClassLoader) { class CarpenterClassLoader (parentClassLoader: ClassLoader = Thread.currentThread().contextClassLoader) :
ClassLoader(parentClassLoader) {
fun load(name: String, bytes: ByteArray) = defineClass(name, bytes, 0, bytes.size) fun load(name: String, bytes: ByteArray) = defineClass(name, bytes, 0, bytes.size)
} }
@ -66,14 +67,14 @@ class CarpenterClassLoader : ClassLoader(Thread.currentThread().contextClassLoad
* *
* Equals/hashCode methods are not yet supported. * Equals/hashCode methods are not yet supported.
*/ */
class ClassCarpenter { class ClassCarpenter(cl: ClassLoader = Thread.currentThread().contextClassLoader) {
// TODO: Generics. // TODO: Generics.
// TODO: Sandbox the generated code when a security manager is in use. // TODO: Sandbox the generated code when a security manager is in use.
// TODO: Generate equals/hashCode. // TODO: Generate equals/hashCode.
// TODO: Support annotations. // TODO: Support annotations.
// TODO: isFoo getter patterns for booleans (this is what Kotlin generates) // TODO: isFoo getter patterns for booleans (this is what Kotlin generates)
val classloader = CarpenterClassLoader() val classloader = CarpenterClassLoader(cl)
private val _loaded = HashMap<String, Class<*>>() private val _loaded = HashMap<String, Class<*>>()
private val String.jvm: String get() = replace(".", "/") private val String.jvm: String get() = replace(".", "/")

View File

@ -73,9 +73,7 @@ abstract class MetaCarpenterBase (val schemas : CarpenterSchemas, val cc : Class
// we're out of blockers so we can now create the type // we're out of blockers so we can now create the type
if (schemas.dependencies[dependent]?.second?.isEmpty() ?: false) { if (schemas.dependencies[dependent]?.second?.isEmpty() ?: false) {
(schemas.dependencies.remove (dependent)?.first as CompositeType).carpenterSchema ( (schemas.dependencies.remove (dependent)?.first as CompositeType).carpenterSchema (
classLoaders = listOf<ClassLoader> ( classloader = cc.classloader,
ClassLoader.getSystemClassLoader(),
cc.classloader),
carpenterSchemas = schemas) carpenterSchemas = schemas)
} }
} }

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import net.corda.nodeapi.internal.serialization.carpenter.*
// those classes don't exist within the system's Class Loader the deserialiser will be forced to carpent // those classes don't exist within the system's Class Loader the deserialiser will be forced to carpent
// versions of them up using its own internal class carpenter (each carpenter houses it's own loader). This // versions of them up using its own internal class carpenter (each carpenter houses it's own loader). This
// replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath // replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath
class DeserializeNeedingCarpentrySimpleTypesTest { class DeserializeNeedingCarpentrySimpleTypesTest : AmqpCarpenterBase() {
companion object { companion object {
/** /**
* If you want to see the schema encoded into the envelope after serialisation change this to true * If you want to see the schema encoded into the envelope after serialisation change this to true
@ -16,12 +16,12 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
private const val VERBOSE = false private const val VERBOSE = false
} }
val sf = SerializerFactory() val sf = testDefaultFactory()
val sf2 = SerializerFactory() val sf2 = testDefaultFactory()
@Test @Test
fun singleInt() { fun singleInt() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"int" to NonNullableField(Integer::class.javaPrimitiveType!!) "int" to NonNullableField(Integer::class.javaPrimitiveType!!)
))) )))
@ -41,7 +41,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleIntNullable() { fun singleIntNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"int" to NullableField(Integer::class.java) "int" to NullableField(Integer::class.java)
))) )))
@ -57,7 +57,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleIntNullableNull() { fun singleIntNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"int" to NullableField(Integer::class.java) "int" to NullableField(Integer::class.java)
))) )))
@ -73,7 +73,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleChar() { fun singleChar() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"char" to NonNullableField(Character::class.javaPrimitiveType!!) "char" to NonNullableField(Character::class.javaPrimitiveType!!)
))) )))
@ -86,7 +86,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleCharNullable() { fun singleCharNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"char" to NullableField(Character::class.javaObjectType) "char" to NullableField(Character::class.javaObjectType)
))) )))
@ -99,7 +99,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleCharNullableNull() { fun singleCharNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"char" to NullableField(java.lang.Character::class.java) "char" to NullableField(java.lang.Character::class.java)
))) )))
@ -112,7 +112,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleLong() { fun singleLong() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"long" to NonNullableField(Long::class.javaPrimitiveType!!) "long" to NonNullableField(Long::class.javaPrimitiveType!!)
))) )))
@ -126,7 +126,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleLongNullable() { fun singleLongNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"long" to NullableField(Long::class.javaObjectType) "long" to NullableField(Long::class.javaObjectType)
))) )))
@ -140,7 +140,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleLongNullableNull() { fun singleLongNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"long" to NullableField(Long::class.javaObjectType) "long" to NullableField(Long::class.javaObjectType)
))) )))
@ -153,7 +153,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleBoolean() { fun singleBoolean() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"boolean" to NonNullableField(Boolean::class.javaPrimitiveType!!) "boolean" to NonNullableField(Boolean::class.javaPrimitiveType!!)
))) )))
@ -166,7 +166,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleBooleanNullable() { fun singleBooleanNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"boolean" to NullableField(Boolean::class.javaObjectType) "boolean" to NullableField(Boolean::class.javaObjectType)
))) )))
@ -179,7 +179,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleBooleanNullableNull() { fun singleBooleanNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"boolean" to NullableField(Boolean::class.javaObjectType) "boolean" to NullableField(Boolean::class.javaObjectType)
))) )))
@ -192,7 +192,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleDouble() { fun singleDouble() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"double" to NonNullableField(Double::class.javaPrimitiveType!!) "double" to NonNullableField(Double::class.javaPrimitiveType!!)
))) )))
@ -205,7 +205,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleDoubleNullable() { fun singleDoubleNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"double" to NullableField(Double::class.javaObjectType) "double" to NullableField(Double::class.javaObjectType)
))) )))
@ -218,7 +218,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleDoubleNullableNull() { fun singleDoubleNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"double" to NullableField(Double::class.javaObjectType) "double" to NullableField(Double::class.javaObjectType)
))) )))
@ -231,7 +231,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleShort() { fun singleShort() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"short" to NonNullableField(Short::class.javaPrimitiveType!!) "short" to NonNullableField(Short::class.javaPrimitiveType!!)
))) )))
@ -244,7 +244,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleShortNullable() { fun singleShortNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"short" to NullableField(Short::class.javaObjectType) "short" to NullableField(Short::class.javaObjectType)
))) )))
@ -257,7 +257,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleShortNullableNull() { fun singleShortNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"short" to NullableField(Short::class.javaObjectType) "short" to NullableField(Short::class.javaObjectType)
))) )))
@ -270,7 +270,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleFloat() { fun singleFloat() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"float" to NonNullableField(Float::class.javaPrimitiveType!!) "float" to NonNullableField(Float::class.javaPrimitiveType!!)
))) )))
@ -283,7 +283,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleFloatNullable() { fun singleFloatNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"float" to NullableField(Float::class.javaObjectType) "float" to NullableField(Float::class.javaObjectType)
))) )))
@ -296,7 +296,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleFloatNullableNull() { fun singleFloatNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"float" to NullableField(Float::class.javaObjectType) "float" to NullableField(Float::class.javaObjectType)
))) )))
@ -309,7 +309,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleByte() { fun singleByte() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"byte" to NonNullableField(Byte::class.javaPrimitiveType!!) "byte" to NonNullableField(Byte::class.javaPrimitiveType!!)
))) )))
@ -324,7 +324,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleByteNullable() { fun singleByteNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"byte" to NullableField(Byte::class.javaObjectType) "byte" to NullableField(Byte::class.javaObjectType)
))) )))
@ -339,7 +339,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun singleByteNullableNull() { fun singleByteNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf( val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"byte" to NullableField(Byte::class.javaObjectType) "byte" to NullableField(Byte::class.javaObjectType)
))) )))
@ -353,11 +353,10 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun simpleTypeKnownInterface() { fun simpleTypeKnownInterface() {
val clazz = ClassCarpenter().build (ClassSchema( val clazz = ClassCarpenter().build (ClassSchema(
"oneType", mapOf("name" to NonNullableField(String::class.java)), testName(), mapOf("name" to NonNullableField(String::class.java)),
interfaces = listOf (I::class.java))) interfaces = listOf (I::class.java)))
val testVal = "Some Person" val testVal = "Some Person"
val classInstance = clazz.constructors[0].newInstance(testVal) val classInstance = clazz.constructors[0].newInstance(testVal)
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(classInstance) val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(classInstance)
val deserializedObj = DeserializationInput(sf2).deserialize(serialisedBytes) val deserializedObj = DeserializationInput(sf2).deserialize(serialisedBytes)
@ -368,7 +367,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test @Test
fun manyTypes() { fun manyTypes() {
val manyClass = ClassCarpenter().build (ClassSchema("many", mapOf( val manyClass = ClassCarpenter().build (ClassSchema(testName(), mapOf(
"intA" to NonNullableField (Int::class.java), "intA" to NonNullableField (Int::class.java),
"intB" to NullableField (Integer::class.java), "intB" to NullableField (Integer::class.java),
"intC" to NullableField (Integer::class.java), "intC" to NullableField (Integer::class.java),
@ -397,7 +396,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
"byteB" to NullableField (Byte::class.javaObjectType), "byteB" to NullableField (Byte::class.javaObjectType),
"byteC" to NullableField (Byte::class.javaObjectType)))) "byteC" to NullableField (Byte::class.javaObjectType))))
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize( val serialisedBytes = TestSerializationOutput(VERBOSE, factory).serialize(
manyClass.constructors.first().newInstance( manyClass.constructors.first().newInstance(
1, 2, null, 1, 2, null,
"a", "b", null, "a", "b", null,

View File

@ -3,22 +3,21 @@ package net.corda.nodeapi.internal.serialization.amqp
import org.junit.Test import org.junit.Test
import kotlin.test.* import kotlin.test.*
import net.corda.nodeapi.internal.serialization.carpenter.* import net.corda.nodeapi.internal.serialization.carpenter.*
import net.corda.nodeapi.internal.serialization.AllWhitelist
interface I { interface I {
fun getName() : String fun getName() : String
} }
/** // These tests work by having the class carpenter build the classes we serialise and then deserialise them
* These tests work by having the class carpenter build the classes we serialise and then deserialise them // within the context of a second serialiser factory. The second factory is required as the first, having
* within the context of a second serialiser factory. The second factory is required as the first, having // been used to serialise the class, will have cached a copy of the class and will thus bypass the need
* been used to serialise the class, will have cached a copy of the class and will thus bypass the need // to pull it out of the class loader.
* to pull it out of the class loader. //
* // However, those classes don't exist within the system's Class Loader and thus the deserialiser will be forced
* However, those classes don't exist within the system's Class Loader and thus the deserialiser will be forced // to carpent versions of them up using its own internal class carpenter (each carpenter houses it's own loader). This
* to carpent versions of them up using its own internal class carpenter (each carpenter houses it's own loader). This // replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath
* replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath class DeserializeNeedingCarpentryTests : AmqpCarpenterBase() {
*/
class DeserializeNeedingCarpentryTests {
companion object { companion object {
/** /**
* If you want to see the schema encoded into the envelope after serialisation change this to true * If you want to see the schema encoded into the envelope after serialisation change this to true
@ -26,13 +25,13 @@ class DeserializeNeedingCarpentryTests {
private const val VERBOSE = false private const val VERBOSE = false
} }
val sf1 = SerializerFactory() val sf1 = testDefaultFactory()
val sf2 = SerializerFactory() val sf2 = testDefaultFactory()
@Test @Test
fun verySimpleType() { fun verySimpleType() {
val testVal = 10 val testVal = 10
val clazz = ClassCarpenter().build(ClassSchema("oneType", mapOf("a" to NonNullableField(Int::class.java)))) val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf("a" to NonNullableField(Int::class.java))))
val classInstance = clazz.constructors[0].newInstance(testVal) val classInstance = clazz.constructors[0].newInstance(testVal)
val serialisedBytes = TestSerializationOutput(VERBOSE, sf1).serialize(classInstance) val serialisedBytes = TestSerializationOutput(VERBOSE, sf1).serialize(classInstance)
@ -66,16 +65,20 @@ class DeserializeNeedingCarpentryTests {
val testValA = 10 val testValA = 10
val testValB = 20 val testValB = 20
val testValC = 20 val testValC = 20
val clazz = ClassCarpenter().build(ClassSchema("oneType", mapOf("a" to NonNullableField(Int::class.java)))) val clazz = ClassCarpenter().build(ClassSchema("${testName()}_clazz",
mapOf("a" to NonNullableField(Int::class.java))))
val concreteA = clazz.constructors[0].newInstance(testValA) val concreteA = clazz.constructors[0].newInstance(testValA)
val concreteB = clazz.constructors[0].newInstance(testValB) val concreteB = clazz.constructors[0].newInstance(testValB)
val concreteC = clazz.constructors[0].newInstance(testValC) val concreteC = clazz.constructors[0].newInstance(testValC)
val deserialisedA = DeserializationInput(sf2).deserialize(TestSerializationOutput(VERBOSE, sf1).serialize(concreteA)) val deserialisedA = DeserializationInput(sf2).deserialize(
TestSerializationOutput(VERBOSE, sf1).serialize(concreteA))
assertEquals (testValA, deserialisedA::class.java.getMethod("getA").invoke(deserialisedA)) assertEquals (testValA, deserialisedA::class.java.getMethod("getA").invoke(deserialisedA))
val deserialisedB = DeserializationInput(sf2).deserialize(TestSerializationOutput(VERBOSE, sf1).serialize(concreteB)) val deserialisedB = DeserializationInput(sf2).deserialize(
TestSerializationOutput(VERBOSE, sf1).serialize(concreteB))
assertEquals (testValB, deserialisedA::class.java.getMethod("getA").invoke(deserialisedB)) assertEquals (testValB, deserialisedA::class.java.getMethod("getA").invoke(deserialisedB))
assertEquals (deserialisedA::class.java, deserialisedB::class.java) assertEquals (deserialisedA::class.java, deserialisedB::class.java)
@ -84,8 +87,10 @@ class DeserializeNeedingCarpentryTests {
// won't already exist and it will be carpented a second time showing that when A and B are the // won't already exist and it will be carpented a second time showing that when A and B are the
// same underlying class that we didn't create a second instance of the class with the // same underlying class that we didn't create a second instance of the class with the
// second deserialisation // second deserialisation
val lsf = SerializerFactory() val lfactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
val deserialisedC = DeserializationInput(lsf).deserialize(TestSerializationOutput(VERBOSE, lsf).serialize(concreteC)) val deserialisedC = DeserializationInput(lfactory).deserialize(
TestSerializationOutput(VERBOSE, lfactory).serialize(concreteC))
assertEquals (testValC, deserialisedC::class.java.getMethod("getA").invoke(deserialisedC)) assertEquals (testValC, deserialisedC::class.java.getMethod("getA").invoke(deserialisedC))
assertNotEquals (deserialisedA::class.java, deserialisedC::class.java) assertNotEquals (deserialisedA::class.java, deserialisedC::class.java)
assertNotEquals (deserialisedB::class.java, deserialisedC::class.java) assertNotEquals (deserialisedB::class.java, deserialisedC::class.java)
@ -94,7 +99,7 @@ class DeserializeNeedingCarpentryTests {
@Test @Test
fun simpleTypeKnownInterface() { fun simpleTypeKnownInterface() {
val clazz = ClassCarpenter().build (ClassSchema( val clazz = ClassCarpenter().build (ClassSchema(
"oneType", mapOf("name" to NonNullableField(String::class.java)), testName(), mapOf("name" to NonNullableField(String::class.java)),
interfaces = listOf (I::class.java))) interfaces = listOf (I::class.java)))
val testVal = "Some Person" val testVal = "Some Person"
val classInstance = clazz.constructors[0].newInstance(testVal) val classInstance = clazz.constructors[0].newInstance(testVal)
@ -108,7 +113,7 @@ class DeserializeNeedingCarpentryTests {
@Test @Test
fun arrayOfTypes() { fun arrayOfTypes() {
val clazz = ClassCarpenter().build(ClassSchema("oneType", mapOf("a" to NonNullableField(Int::class.java)))) val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf("a" to NonNullableField(Int::class.java))))
data class Outer (val a : Array<Any>) data class Outer (val a : Array<Any>)
@ -142,8 +147,8 @@ class DeserializeNeedingCarpentryTests {
fun reusedClasses() { fun reusedClasses() {
val cc = ClassCarpenter() val cc = ClassCarpenter()
val innerType = cc.build(ClassSchema("inner", mapOf("a" to NonNullableField(Int::class.java)))) val innerType = cc.build(ClassSchema("${testName()}.inner", mapOf("a" to NonNullableField(Int::class.java))))
val outerType = cc.build(ClassSchema("outer", mapOf("a" to NonNullableField(innerType)))) val outerType = cc.build(ClassSchema("${testName()}.outer", mapOf("a" to NonNullableField(innerType))))
val inner = innerType.constructors[0].newInstance(1) val inner = innerType.constructors[0].newInstance(1)
val outer = outerType.constructors[0].newInstance(innerType.constructors[0].newInstance(2)) val outer = outerType.constructors[0].newInstance(innerType.constructors[0].newInstance(2))
@ -195,7 +200,7 @@ class DeserializeNeedingCarpentryTests {
@Test @Test
fun listOfType() { fun listOfType() {
val unknownClass = ClassCarpenter().build (ClassSchema("unknownClass", mapOf( val unknownClass = ClassCarpenter().build (ClassSchema(testName(), mapOf(
"v1" to NonNullableField(Int::class.java), "v1" to NonNullableField(Int::class.java),
"v2" to NonNullableField(Int::class.java)))) "v2" to NonNullableField(Int::class.java))))
@ -223,7 +228,7 @@ class DeserializeNeedingCarpentryTests {
"gen.Interface", "gen.Interface",
mapOf("age" to NonNullableField (Int::class.java)))) mapOf("age" to NonNullableField (Int::class.java))))
val concreteClass = cc.build (ClassSchema ("gen.Class", mapOf( val concreteClass = cc.build (ClassSchema (testName(), mapOf(
"age" to NonNullableField (Int::class.java), "age" to NonNullableField (Int::class.java),
"name" to NonNullableField(String::class.java)), "name" to NonNullableField(String::class.java)),
interfaces = listOf (I::class.java, interfaceClass))) interfaces = listOf (I::class.java, interfaceClass)))

View File

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

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.amqp; package net.corda.nodeapi.internal.serialization.amqp;
import net.corda.nodeapi.internal.serialization.AllWhitelist;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.DecoderImpl;
import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.codec.EncoderImpl;
@ -167,7 +168,7 @@ public class JavaSerializationOutputTests {
} }
private Object serdes(Object obj) throws NotSerializableException { private Object serdes(Object obj) throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(); SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
SerializedBytes<Object> bytes = ser.serialize(obj); SerializedBytes<Object> bytes = ser.serialize(obj);

View File

@ -14,7 +14,9 @@ import net.corda.nodeapi.RPCException
import net.corda.nodeapi.internal.serialization.AbstractAMQPSerializationScheme import net.corda.nodeapi.internal.serialization.AbstractAMQPSerializationScheme
import net.corda.nodeapi.internal.serialization.EmptyWhitelist import net.corda.nodeapi.internal.serialization.EmptyWhitelist
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive
import net.corda.nodeapi.internal.serialization.amqp.custom.* 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
import net.corda.testing.MEGA_CORP_PUBKEY import net.corda.testing.MEGA_CORP_PUBKEY
import org.apache.qpid.proton.amqp.* import org.apache.qpid.proton.amqp.*
@ -136,8 +138,10 @@ class SerializationOutputTests {
data class PolymorphicProperty(val foo: FooInterface?) data class PolymorphicProperty(val foo: FooInterface?)
private fun serdes(obj: Any, private fun serdes(obj: Any,
factory: SerializerFactory = SerializerFactory(), factory: SerializerFactory = SerializerFactory (
freshDeserializationFactory: SerializerFactory = SerializerFactory(), AllWhitelist, ClassLoader.getSystemClassLoader()),
freshDeserializationFactory: SerializerFactory = SerializerFactory(
AllWhitelist, ClassLoader.getSystemClassLoader()),
expectedEqual: Boolean = true, expectedEqual: Boolean = true,
expectDeserializedEqual: Boolean = true): Any { expectDeserializedEqual: Boolean = true): Any {
val ser = SerializationOutput(factory) val ser = SerializationOutput(factory)
@ -285,13 +289,13 @@ class SerializationOutputTests {
@Test(expected = NotSerializableException::class) @Test(expected = NotSerializableException::class)
fun `test whitelist`() { fun `test whitelist`() {
val obj = Woo2(4) val obj = Woo2(4)
serdes(obj, SerializerFactory(EmptyWhitelist)) serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()))
} }
@Test @Test
fun `test annotation whitelisting`() { fun `test annotation whitelisting`() {
val obj = AnnotatedWoo(5) val obj = AnnotatedWoo(5)
serdes(obj, SerializerFactory(EmptyWhitelist)) serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()))
} }
@Test(expected = NotSerializableException::class) @Test(expected = NotSerializableException::class)
@ -387,10 +391,10 @@ class SerializationOutputTests {
@Test @Test
fun `test custom serializers on public key`() { fun `test custom serializers on public key`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(PublicKeySerializer) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer)
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(PublicKeySerializer) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.PublicKeySerializer)
val obj = MEGA_CORP_PUBKEY val obj = MEGA_CORP_PUBKEY
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
} }
@ -398,16 +402,16 @@ class SerializationOutputTests {
@Test @Test
fun `test annotation is inherited`() { fun `test annotation is inherited`() {
val obj = InheritAnnotation("blah") val obj = InheritAnnotation("blah")
serdes(obj, SerializerFactory(EmptyWhitelist)) serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()))
} }
@Test @Test
fun `test throwables serialize`() { fun `test throwables serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(ThrowableSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(ThrowableSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
val t = IllegalAccessException("message").fillInStackTrace() val t = IllegalAccessException("message").fillInStackTrace()
val desThrowable = serdes(t, factory, factory2, false) as Throwable val desThrowable = serdes(t, factory, factory2, false) as Throwable
@ -416,11 +420,11 @@ class SerializationOutputTests {
@Test @Test
fun `test complex throwables serialize`() { fun `test complex throwables serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(ThrowableSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(ThrowableSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
try { try {
try { try {
@ -447,11 +451,11 @@ class SerializationOutputTests {
@Test @Test
fun `test suppressed throwables serialize`() { fun `test suppressed throwables serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(ThrowableSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(ThrowableSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
try { try {
try { try {
@ -469,11 +473,11 @@ class SerializationOutputTests {
@Test @Test
fun `test flow corda exception subclasses serialize`() { fun `test flow corda exception subclasses serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(ThrowableSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(ThrowableSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
val obj = FlowException("message").fillInStackTrace() val obj = FlowException("message").fillInStackTrace()
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -481,11 +485,11 @@ class SerializationOutputTests {
@Test @Test
fun `test RPC corda exception subclasses serialize`() { fun `test RPC corda exception subclasses serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(ThrowableSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(ThrowableSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.ThrowableSerializer(factory2))
val obj = RPCException("message").fillInStackTrace() val obj = RPCException("message").fillInStackTrace()
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -525,12 +529,12 @@ class SerializationOutputTests {
@Test @Test
fun `test transaction state`() { fun `test transaction state`() {
val state = TransactionState<FooState>(FooState(), MEGA_CORP) val state = TransactionState(FooState(), MEGA_CORP)
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
AbstractAMQPSerializationScheme.registerCustomSerializers(factory) AbstractAMQPSerializationScheme.registerCustomSerializers(factory)
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
AbstractAMQPSerializationScheme.registerCustomSerializers(factory2) AbstractAMQPSerializationScheme.registerCustomSerializers(factory2)
val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false) val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false)
@ -542,11 +546,11 @@ class SerializationOutputTests {
@Test @Test
fun `test currencies serialize`() { fun `test currencies serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(CurrencySerializer) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.CurrencySerializer)
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(CurrencySerializer) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.CurrencySerializer)
val obj = Currency.getInstance("USD") val obj = Currency.getInstance("USD")
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -554,11 +558,11 @@ class SerializationOutputTests {
@Test @Test
fun `test big decimals serialize`() { fun `test big decimals serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(BigDecimalSerializer) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.BigDecimalSerializer)
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(BigDecimalSerializer) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.BigDecimalSerializer)
val obj = BigDecimal("100000000000000000000000000000.00") val obj = BigDecimal("100000000000000000000000000000.00")
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -566,11 +570,11 @@ class SerializationOutputTests {
@Test @Test
fun `test instants serialize`() { fun `test instants serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(InstantSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.InstantSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(InstantSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.InstantSerializer(factory2))
val obj = Instant.now() val obj = Instant.now()
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -578,11 +582,11 @@ class SerializationOutputTests {
@Test @Test
fun `test StateRef serialize`() { fun `test StateRef serialize`() {
val factory = SerializerFactory() val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory.register(InstantSerializer(factory)) factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.InstantSerializer(factory))
val factory2 = SerializerFactory() val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
factory2.register(InstantSerializer(factory2)) factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.InstantSerializer(factory2))
val obj = StateRef(SecureHash.randomSHA256(), 0) val obj = StateRef(SecureHash.randomSHA256(), 0)
serdes(obj, factory, factory2) serdes(obj, factory, factory2)

View File

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

View File

@ -63,7 +63,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assertEquals("b", amqpSchemaB.fields[1].name) assertEquals("b", amqpSchemaB.fields[1].name)
assertEquals("int", amqpSchemaB.fields[1].type) assertEquals("int", amqpSchemaB.fields[1].type)
val metaSchema = obj.envelope.schema.carpenterSchema() val metaSchema = obj.envelope.schema.carpenterSchema(ClassLoader.getSystemClassLoader())
// if we know all the classes there is nothing to really achieve here // if we know all the classes there is nothing to really achieve here
assert(metaSchema.carpenterSchemas.isEmpty()) assert(metaSchema.carpenterSchemas.isEmpty())
@ -92,7 +92,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is B) assert(obj.obj is B)
amqpSchema.carpenterSchema() amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
} }
@Test @Test
@ -112,7 +112,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is B) assert(obj.obj is B)
val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("B")))
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(1, carpenterSchema.size) assertEquals(1, carpenterSchema.size)
@ -140,7 +140,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is B) assert(obj.obj is B)
val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B")))
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// just verify we're in the expected initial state, A is carpentable, B is not because // just verify we're in the expected initial state, A is carpentable, B is not because
// it depends on A and the dependency chains are in place // it depends on A and the dependency chains are in place
@ -200,7 +200,7 @@ class CompositeMembers : AmqpCarpenterBase() {
val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B")))
amqpSchema.carpenterSchema() amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
} }
@Test(expected = UncarpentableException::class) @Test(expected = UncarpentableException::class)
@ -226,7 +226,7 @@ class CompositeMembers : AmqpCarpenterBase() {
val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B")))
amqpSchema.carpenterSchema() amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
} }
@Suppress("UNUSED") @Suppress("UNUSED")
@ -251,7 +251,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is C) assert(obj.obj is C)
val carpenterSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B"))) val carpenterSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B")))
TestMetaCarpenter(carpenterSchema.carpenterSchema()) TestMetaCarpenter(carpenterSchema.carpenterSchema(ClassLoader.getSystemClassLoader()))
} }
/* /*

View File

@ -45,14 +45,14 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertTrue(obj.obj is A) assertTrue(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
assertEquals(2, serSchema.types.size) assertEquals(2, serSchema.types.size)
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// since we're using an envelope generated by seilaising classes defined locally // since we're using an envelope generated by seilaising classes defined locally
// it's extremely unlikely we'd need to carpent any classes // it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size) assertEquals(0, l1.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema() val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(1, l2.size) assertEquals(1, l2.size)
val aSchema = l2.carpenterSchemas.find { it.name == mangleName(classTestName("A")) } val aSchema = l2.carpenterSchemas.find { it.name == mangleName(classTestName("A")) }
@ -88,13 +88,13 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(2, serSchema.types.size) assertEquals(2, serSchema.types.size)
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(0, l1.size) assertEquals(0, l1.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
val l2 = mangleSchema.carpenterSchema() val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(1, l2.size) assertEquals(1, l2.size)
@ -132,7 +132,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(3, serSchema.types.size) assertEquals(3, serSchema.types.size)
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// since we're using an envelope generated by serialising classes defined locally // since we're using an envelope generated by serialising classes defined locally
// it's extremely unlikely we'd need to carpent any classes // it's extremely unlikely we'd need to carpent any classes
@ -141,7 +141,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
// pretend we don't know the class we've been sent, i.e. it's unknown to the class loader, and thus // pretend we don't know the class we've been sent, i.e. it's unknown to the class loader, and thus
// needs some carpentry // needs some carpentry
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema() val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
assertEquals(1, l2.size) assertEquals(1, l2.size)
@ -180,14 +180,14 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(3, serSchema.types.size) assertEquals(3, serSchema.types.size)
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// since we're using an envelope generated by serialising classes defined locally // since we're using an envelope generated by serialising classes defined locally
// it's extremely unlikely we'd need to carpent any classes // it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size) assertEquals(0, l1.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema() val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
assertEquals(1, l2.size) assertEquals(1, l2.size)
@ -235,7 +235,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(4, serSchema.types.size) assertEquals(4, serSchema.types.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A"), classTestName("B"))) val mangleSchema = serSchema.mangleNames(listOf(classTestName("A"), classTestName("B")))
val cSchema = mangleSchema.carpenterSchema() val cSchema = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
val bName = mangleName(classTestName("B")) val bName = mangleName(classTestName("B"))
@ -292,7 +292,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
// ignore the return as we expect this to throw // ignore the return as we expect this to throw
serSchema.mangleNames(listOf( serSchema.mangleNames(listOf(
classTestName("A"), "${this.javaClass.`package`.name}.I")).carpenterSchema() classTestName("A"), "${this.javaClass.`package`.name}.I")).carpenterSchema(ClassLoader.getSystemClassLoader())
} }
@Test @Test
@ -315,7 +315,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val amqpSchema = serSchema.mangleNames(listOf(classTestName("A"), "${this.javaClass.`package`.name}.I")) val amqpSchema = serSchema.mangleNames(listOf(classTestName("A"), "${this.javaClass.`package`.name}.I"))
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
val iName = mangleName("${this.javaClass.`package`.name}.I") val iName = mangleName("${this.javaClass.`package`.name}.I")
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// whilst there are two unknown classes within the envelope A depends on I so we can't construct a // whilst there are two unknown classes within the envelope A depends on I so we can't construct a
// schema for A until we have for I // schema for A until we have for I
@ -362,7 +362,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
val iName = mangleName("${this.javaClass.`package`.name}.I") val iName = mangleName("${this.javaClass.`package`.name}.I")
val iiName = mangleName("${this.javaClass.`package`.name}.II") val iiName = mangleName("${this.javaClass.`package`.name}.II")
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// there is nothing preventing us from carpenting up the two interfaces so // there is nothing preventing us from carpenting up the two interfaces so
// our initial list should contain both interface with A being dependent on both // our initial list should contain both interface with A being dependent on both
@ -414,7 +414,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val aName = mangleName(classTestName("A")) val aName = mangleName(classTestName("A"))
val iName = mangleName("${this.javaClass.`package`.name}.I") val iName = mangleName("${this.javaClass.`package`.name}.I")
val iiiName = mangleName("${this.javaClass.`package`.name}.III") val iiiName = mangleName("${this.javaClass.`package`.name}.III")
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
// Since A depends on III and III extends I we will have to construct them // Since A depends on III and III extends I we will have to construct them
// in that reverse order (I -> III -> A) // in that reverse order (I -> III -> A)

View File

@ -36,7 +36,10 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("int", amqpSchema.fields[1].type) assertEquals("int", amqpSchema.fields[1].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
assertEquals(1, carpenterSchema.size) assertEquals(1, carpenterSchema.size)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") } val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }
@ -77,7 +80,10 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("string", amqpSchema.fields[1].type) assertEquals("string", amqpSchema.fields[1].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
assertEquals(1, carpenterSchema.size) assertEquals(1, carpenterSchema.size)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") } val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }

View File

@ -30,7 +30,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("int", amqpSchema.fields[0].type) assertEquals("int", amqpSchema.fields[0].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
@ -58,7 +61,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val amqpSchema = obj.envelope.schema.types[0] as CompositeType val amqpSchema = obj.envelope.schema.types[0] as CompositeType
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
@ -90,7 +96,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("long", amqpSchema.fields[0].type) assertEquals("long", amqpSchema.fields[0].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
@ -122,7 +131,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("short", amqpSchema.fields[0].type) assertEquals("short", amqpSchema.fields[0].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
@ -154,7 +166,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("double", amqpSchema.fields[0].type) assertEquals("double", amqpSchema.fields[0].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
@ -186,7 +201,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("float", amqpSchema.fields[0].type) assertEquals("float", amqpSchema.fields[0].type)
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(
classloader = ClassLoader.getSystemClassLoader(),
carpenterSchemas = carpenterSchema,
force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)