Move AMQP serializer toward the new common abstract itnerface

Allow unique serializer factories to be created per unique set of
WhiteList / Class Loader pair. Remove default consruction of the
SerializerFactory to force use of the FactoryFactory to get the generic
factory and thus access to it's ClassLoader
This commit is contained in:
Katelyn Baker 2017-08-08 15:35:55 +01:00
parent 9149900938
commit 139eef2ccb
21 changed files with 241 additions and 219 deletions

View File

@ -41,11 +41,17 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
rpcClientSerializerFactory(context)
SerializationContext.UseCase.RPCServer ->
rpcServerSerializerFactory(context)
else -> SerializerFactory(context.whitelist) // TODO pass class loader also
else -> SerializerFactory(context.whitelist, context.deserializationClassLoader)
}
}.also { registerCustomSerializers(it) }
}
fun getSerializerFactory(): SerializerFactory {
return serializerFactoriesForContexts.computeIfAbsent(Pair(AllWhitelist, deserializationClassLoader)) {
SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
}
}
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T {
val serializerFactory = getSerializerFactory(context)
return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz)

View File

@ -12,6 +12,7 @@ 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`
@ -34,4 +35,4 @@ class KryoAMQPSerializer(val serializationFactory: SerializationFactory, val ser
input.readBytes(allBytes, peekedBytes.size, size - peekedBytes.size)
return serializationFactory.deserialize(allBytes.sequence(), type, serializationContext)
}
}
}

View File

@ -151,8 +151,10 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* @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,
private val maker: (String) -> T = clazz.getConstructor(String::class.java).let { `constructor` -> { string -> `constructor`.newInstance(string) } },
private val unmaker: (T) -> String = { obj -> obj.toString() }) : Proxy<T, String>(clazz, String::class.java, /* Unused */ SerializerFactory(), withInheritance) {
private val maker: (String) -> T = clazz.getConstructor(String::class.java).let {
`constructor` -> { string -> `constructor`.newInstance(string) }
},
private val unmaker: (T) -> String = { obj -> obj.toString() }) : Proxy<T, String>(clazz, String::class.java, /* Unused */ SerializerFactoryFactory.get(), withInheritance) {
override val additionalSerializers: Iterable<CustomSerializer<out Any>> = emptyList()

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 = SerializerFactory()) {
class DeserializationInput(internal val serializerFactory: SerializerFactory = SerializerFactoryFactory.get()) {
// 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 = SerializerFactory()) {
open class SerializationOutput(internal val serializerFactory: SerializerFactory = SerializerFactoryFactory.get()) {
// TODO: we're not supporting object refs yet
private val objectHistory: MutableMap<Any, Int> = IdentityHashMap()
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()

View File

@ -44,11 +44,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 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
class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
class SerializerFactory(val whitelist: ClassWhitelist, cl : ClassLoader) {
private val serializersByType = ConcurrentHashMap<Type, AMQPSerializer<Any>>()
private val serializersByDescriptor = ConcurrentHashMap<Any, AMQPSerializer<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.
@ -176,15 +178,18 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
}
}
/**
* 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, sentinal: Boolean = false) {
val carpenterSchemas = CarpenterSchemas.newInstance()
for (typeNotation in schema.types) {
try {
processSchemaEntry(typeNotation, classCarpenter.classloader)
} catch (e: ClassNotFoundException) {
}
catch (e: ClassNotFoundException) {
if (sentinal || (typeNotation !is CompositeType)) throw e
typeNotation.carpenterSchema(
classLoaders = listOf(classCarpenter.classloader), carpenterSchemas = carpenterSchemas)
typeNotation.carpenterSchema(classloader, carpenterSchemas = carpenterSchemas)
}
}
@ -195,10 +200,9 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
}
}
private fun processSchemaEntry(typeNotation: TypeNotation,
cl: ClassLoader = DeserializedParameterizedType::class.java.classLoader) {
private fun processSchemaEntry(typeNotation: 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
}
}
@ -210,7 +214,6 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
}
private fun processCompositeType(typeNotation: CompositeType,
cl: ClassLoader = DeserializedParameterizedType::class.java.classLoader) {
// TODO: class loader logic, and compare the schema.
val type = typeForName(typeNotation.name, cl)
get(type.asClass() ?: throw NotSerializableException("Unable to build composite type for $type"), type)
@ -322,11 +325,9 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
else -> throw NotSerializableException("Unable to render type $type to a string.")
}
private fun typeForName(
name: String,
cl: ClassLoader = DeserializedParameterizedType::class.java.classLoader): Type {
private fun typeForName(name: String, classloader: ClassLoader): Type {
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) {
DeserializedGenericArrayType(elementType)
} else if (elementType is Class<*>) {
@ -349,7 +350,7 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
else -> throw NotSerializableException("Not able to deserialize array type: $name")
}
} else {
DeserializedParameterizedType.make(name, cl)
DeserializedParameterizedType.make(name, classloader)
}
}
}

View File

@ -0,0 +1,22 @@
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

@ -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.Schema as AMQPSchema
fun AMQPSchema.carpenterSchema(
loaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()))
: CarpenterSchemas {
fun AMQPSchema.carpenterSchema(classloader: ClassLoader) : CarpenterSchemas {
val rtn = CarpenterSchemas.newInstance()
types.filterIsInstance<CompositeType>().forEach {
it.carpenterSchema(classLoaders = loaders, carpenterSchemas = rtn)
it.carpenterSchema(classloader, carpenterSchemas = 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
*/
private fun CompositeType.validatePropertyTypes(
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())) {
private fun CompositeType.validatePropertyTypes(classloader: ClassLoader) {
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
* at this time
*
* @param classLoaders list of classLoaders, defaulting toe the system class loader, that might
* be used to load objects
* @param classloader the class loader provided dby the [SerializationContext]
* @param carpenterSchemas structure that holds the dependency tree and list of classes that
* need constructing
* @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
*/
fun CompositeType.carpenterSchema(
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()),
carpenterSchemas: CarpenterSchemas,
force: Boolean = false) {
if (classLoaders.exists(name)) {
validatePropertyTypes(classLoaders)
fun CompositeType.carpenterSchema(classloader: ClassLoader,
carpenterSchemas: CarpenterSchemas,
force: Boolean = false) {
if (classloader.exists(name)) {
validatePropertyTypes(classloader)
if (!force) return
}
val providesList = mutableListOf<Class<*>>()
var isInterface = false
var isCreatable = true
@ -62,7 +56,7 @@ fun CompositeType.carpenterSchema(
}
try {
providesList.add(classLoaders.loadIfExists(it))
providesList.add(classloader.loadClass(it))
} catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it)
isCreatable = false
@ -73,7 +67,7 @@ fun CompositeType.carpenterSchema(
fields.forEach {
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) {
carpenterSchemas.addDepPair(this, name, it.typeAsString())
isCreatable = false
@ -110,33 +104,18 @@ val typeStrToType: Map<Pair<String, Boolean>, Class<out Any?>> = mapOf(
Pair("byte", false) to Byte::class.javaObjectType
)
fun AMQPField.getTypeAsClass(
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())
) = typeStrToType[Pair(type, mandatory)] ?: when (type) {
fun AMQPField.getTypeAsClass(classloader: ClassLoader) = typeStrToType[Pair(type, mandatory)] ?: when (type) {
"string" -> String::class.java
"*" -> classLoaders.loadIfExists(requires[0])
else -> classLoaders.loadIfExists(type)
"*" -> classloader.loadClass(requires[0])
else -> classloader.loadClass(type)
}
fun AMQPField.validateType(
classLoaders: List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader())
) = when (type) {
fun AMQPField.validateType(classloader: ClassLoader) = when (type) {
"byte", "int", "string", "short", "long", "char", "boolean", "double", "float" -> true
"*" -> classLoaders.exists(requires[0])
else -> classLoaders.exists(type)
"*" -> classloader.exists(requires[0])
else -> classloader.exists(type)
}
private fun List<ClassLoader>.exists(clazz: String) = this.find {
try { it.loadClass(clazz); true } catch (e: ClassNotFoundException) { false }
} != null
private fun ClassLoader.exists(clazz: String) = run {
try { this.loadClass(clazz); true } catch (e: ClassNotFoundException) { false } }
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?
}
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)
}
@ -66,14 +67,14 @@ class CarpenterClassLoader : ClassLoader(Thread.currentThread().contextClassLoad
*
* Equals/hashCode methods are not yet supported.
*/
class ClassCarpenter {
class ClassCarpenter(cl: ClassLoader = Thread.currentThread().contextClassLoader) {
// TODO: Generics.
// TODO: Sandbox the generated code when a security manager is in use.
// TODO: Generate equals/hashCode.
// TODO: Support annotations.
// 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 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
if (schemas.dependencies[dependent]?.second?.isEmpty() ?: false) {
(schemas.dependencies.remove (dependent)?.first as CompositeType).carpenterSchema (
classLoaders = listOf<ClassLoader> (
ClassLoader.getSystemClassLoader(),
cc.classloader),
classloader = cc.classloader,
carpenterSchemas = schemas)
}
}

View File

@ -4,7 +4,7 @@ import org.apache.qpid.proton.codec.Data
class TestSerializationOutput(
private val verbose: Boolean,
serializerFactory: SerializerFactory = SerializerFactory()) : SerializationOutput(serializerFactory) {
serializerFactory: SerializerFactory = SerializerFactoryFactory.get()) : 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 = SerializerFactory()
val factory = SerializerFactoryFactory.get()
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 = SerializerFactory()
val factory = SerializerFactoryFactory.get()
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
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
// 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
class DeserializeNeedingCarpentrySimpleTypesTest {
class DeserializeNeedingCarpentrySimpleTypesTest : AmqpCarpenterBase() {
companion object {
/**
* If you want to see the schema encoded into the envelope after serialisation change this to true
@ -21,7 +21,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleInt() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"int" to NonNullableField(Integer::class.javaPrimitiveType!!)
)))
@ -41,7 +41,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleIntNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"int" to NullableField(Integer::class.java)
)))
@ -57,7 +57,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleIntNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"int" to NullableField(Integer::class.java)
)))
@ -73,7 +73,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleChar() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"char" to NonNullableField(Character::class.javaPrimitiveType!!)
)))
@ -86,7 +86,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleCharNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"char" to NullableField(Character::class.javaObjectType)
)))
@ -99,7 +99,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleCharNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"char" to NullableField(java.lang.Character::class.java)
)))
@ -112,7 +112,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleLong() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"long" to NonNullableField(Long::class.javaPrimitiveType!!)
)))
@ -126,7 +126,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleLongNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"long" to NullableField(Long::class.javaObjectType)
)))
@ -140,7 +140,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleLongNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"long" to NullableField(Long::class.javaObjectType)
)))
@ -153,7 +153,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleBoolean() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"boolean" to NonNullableField(Boolean::class.javaPrimitiveType!!)
)))
@ -166,7 +166,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleBooleanNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"boolean" to NullableField(Boolean::class.javaObjectType)
)))
@ -179,7 +179,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleBooleanNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"boolean" to NullableField(Boolean::class.javaObjectType)
)))
@ -192,7 +192,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleDouble() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"double" to NonNullableField(Double::class.javaPrimitiveType!!)
)))
@ -205,7 +205,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleDoubleNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"double" to NullableField(Double::class.javaObjectType)
)))
@ -218,7 +218,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleDoubleNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"double" to NullableField(Double::class.javaObjectType)
)))
@ -231,7 +231,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleShort() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"short" to NonNullableField(Short::class.javaPrimitiveType!!)
)))
@ -244,7 +244,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleShortNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"short" to NullableField(Short::class.javaObjectType)
)))
@ -257,7 +257,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleShortNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"short" to NullableField(Short::class.javaObjectType)
)))
@ -270,7 +270,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleFloat() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"float" to NonNullableField(Float::class.javaPrimitiveType!!)
)))
@ -283,7 +283,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleFloatNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"float" to NullableField(Float::class.javaObjectType)
)))
@ -296,7 +296,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleFloatNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"float" to NullableField(Float::class.javaObjectType)
)))
@ -309,7 +309,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleByte() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"byte" to NonNullableField(Byte::class.javaPrimitiveType!!)
)))
@ -324,7 +324,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleByteNullable() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"byte" to NullableField(Byte::class.javaObjectType)
)))
@ -339,7 +339,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun singleByteNullableNull() {
val clazz = ClassCarpenter().build(ClassSchema("single", mapOf(
val clazz = ClassCarpenter().build(ClassSchema(testName(), mapOf(
"byte" to NullableField(Byte::class.javaObjectType)
)))
@ -353,11 +353,10 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun simpleTypeKnownInterface() {
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)))
val testVal = "Some Person"
val classInstance = clazz.constructors[0].newInstance(testVal)
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(classInstance)
val deserializedObj = DeserializationInput(sf2).deserialize(serialisedBytes)
@ -368,7 +367,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
@Test
fun manyTypes() {
val manyClass = ClassCarpenter().build (ClassSchema("many", mapOf(
val manyClass = ClassCarpenter().build (ClassSchema(testName(), mapOf(
"intA" to NonNullableField (Int::class.java),
"intB" to NullableField (Integer::class.java),
"intC" to NullableField (Integer::class.java),
@ -397,7 +396,7 @@ class DeserializeNeedingCarpentrySimpleTypesTest {
"byteB" 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(
1, 2, null,
"a", "b", null,

View File

@ -3,22 +3,21 @@ package net.corda.nodeapi.internal.serialization.amqp
import org.junit.Test
import kotlin.test.*
import net.corda.nodeapi.internal.serialization.carpenter.*
import net.corda.nodeapi.internal.serialization.AllWhitelist
interface I {
fun getName() : String
}
/**
* 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
* 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.
*
* 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
* replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath
*/
class DeserializeNeedingCarpentryTests {
// 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
// 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.
//
// 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
// replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath
class DeserializeNeedingCarpentryTests : AmqpCarpenterBase() {
companion object {
/**
* If you want to see the schema encoded into the envelope after serialisation change this to true
@ -32,7 +31,7 @@ class DeserializeNeedingCarpentryTests {
@Test
fun verySimpleType() {
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 serialisedBytes = TestSerializationOutput(VERBOSE, sf1).serialize(classInstance)
@ -66,16 +65,20 @@ class DeserializeNeedingCarpentryTests {
val testValA = 10
val testValB = 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 concreteB = clazz.constructors[0].newInstance(testValB)
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))
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 (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
// same underlying class that we didn't create a second instance of the class with the
// second deserialisation
val lsf = SerializerFactory()
val deserialisedC = DeserializationInput(lsf).deserialize(TestSerializationOutput(VERBOSE, lsf).serialize(concreteC))
val lfactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
val deserialisedC = DeserializationInput(lfactory).deserialize(
TestSerializationOutput(VERBOSE, lfactory).serialize(concreteC))
assertEquals (testValC, deserialisedC::class.java.getMethod("getA").invoke(deserialisedC))
assertNotEquals (deserialisedA::class.java, deserialisedC::class.java)
assertNotEquals (deserialisedB::class.java, deserialisedC::class.java)
@ -94,7 +99,7 @@ class DeserializeNeedingCarpentryTests {
@Test
fun simpleTypeKnownInterface() {
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)))
val testVal = "Some Person"
val classInstance = clazz.constructors[0].newInstance(testVal)
@ -108,7 +113,7 @@ class DeserializeNeedingCarpentryTests {
@Test
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>)
@ -142,8 +147,8 @@ class DeserializeNeedingCarpentryTests {
fun reusedClasses() {
val cc = ClassCarpenter()
val innerType = cc.build(ClassSchema("inner", mapOf("a" to NonNullableField(Int::class.java))))
val outerType = cc.build(ClassSchema("outer", mapOf("a" to NonNullableField(innerType))))
val innerType = cc.build(ClassSchema("${testName()}.inner", mapOf("a" to NonNullableField(Int::class.java))))
val outerType = cc.build(ClassSchema("${testName()}.outer", mapOf("a" to NonNullableField(innerType))))
val inner = innerType.constructors[0].newInstance(1)
val outer = outerType.constructors[0].newInstance(innerType.constructors[0].newInstance(2))
@ -160,7 +165,7 @@ class DeserializeNeedingCarpentryTests {
@Test
fun nestedTypes() {
val cc = ClassCarpenter()
val nestedClass = cc.build (ClassSchema("nestedType",
val nestedClass = cc.build (ClassSchema(testName(),
mapOf("name" to NonNullableField(String::class.java))))
val outerClass = cc.build (ClassSchema("outerType",
@ -169,23 +174,6 @@ class DeserializeNeedingCarpentryTests {
val classInstance = outerClass.constructors.first().newInstance(nestedClass.constructors.first().newInstance("name"))
val serialisedBytes = TestSerializationOutput(VERBOSE, sf1).serialize(classInstance)
val deserializedObj = DeserializationInput(sf2).deserialize(serialisedBytes)
val inner = deserializedObj::class.java.getMethod("getInner").invoke(deserializedObj)
assertEquals("name", inner::class.java.getMethod("getName").invoke(inner))
}
@Test
fun repeatedNestedTypes() {
val cc = ClassCarpenter()
val nestedClass = cc.build (ClassSchema("nestedType",
mapOf("name" to NonNullableField(String::class.java))))
data class outer(val a: Any, val b: Any)
val classInstance = outer (
nestedClass.constructors.first().newInstance("foo"),
nestedClass.constructors.first().newInstance("bar"))
val serialisedBytes = TestSerializationOutput(VERBOSE, sf1).serialize(classInstance)
val deserializedObj = DeserializationInput(sf2).deserialize(serialisedBytes)
@ -195,7 +183,7 @@ class DeserializeNeedingCarpentryTests {
@Test
fun listOfType() {
val unknownClass = ClassCarpenter().build (ClassSchema("unknownClass", mapOf(
val unknownClass = ClassCarpenter().build (ClassSchema(testName(), mapOf(
"v1" to NonNullableField(Int::class.java),
"v2" to NonNullableField(Int::class.java))))
@ -223,7 +211,7 @@ class DeserializeNeedingCarpentryTests {
"gen.Interface",
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),
"name" to NonNullableField(String::class.java)),
interfaces = listOf (I::class.java, interfaceClass)))

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assertEquals("b", amqpSchemaB.fields[1].name)
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
assert(metaSchema.carpenterSchemas.isEmpty())
@ -92,7 +92,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is B)
amqpSchema.carpenterSchema()
amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
}
@Test
@ -112,7 +112,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is B)
val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("B")))
val carpenterSchema = amqpSchema.carpenterSchema()
val carpenterSchema = amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(1, carpenterSchema.size)
@ -140,7 +140,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is 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
// 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")))
amqpSchema.carpenterSchema()
amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
}
@Test(expected = UncarpentableException::class)
@ -226,7 +226,7 @@ class CompositeMembers : AmqpCarpenterBase() {
val amqpSchema = obj.envelope.schema.mangleNames(listOf(classTestName("A"), classTestName("B")))
amqpSchema.carpenterSchema()
amqpSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
}
@Suppress("UNUSED")
@ -251,7 +251,7 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(obj.obj is C)
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)
val serSchema = obj.envelope.schema
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
// it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema()
val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(1, l2.size)
val aSchema = l2.carpenterSchemas.find { it.name == mangleName(classTestName("A")) }
@ -88,13 +88,13 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(2, serSchema.types.size)
val l1 = serSchema.carpenterSchema()
val l1 = serSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(0, l1.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val aName = mangleName(classTestName("A"))
val l2 = mangleSchema.carpenterSchema()
val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
assertEquals(1, l2.size)
@ -132,7 +132,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
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
// 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
// needs some carpentry
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema()
val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
val aName = mangleName(classTestName("A"))
assertEquals(1, l2.size)
@ -180,14 +180,14 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
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
// it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size)
val mangleSchema = serSchema.mangleNames(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema()
val l2 = mangleSchema.carpenterSchema(ClassLoader.getSystemClassLoader())
val aName = mangleName(classTestName("A"))
assertEquals(1, l2.size)
@ -235,7 +235,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(4, serSchema.types.size)
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 bName = mangleName(classTestName("B"))
@ -292,7 +292,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
// ignore the return as we expect this to throw
serSchema.mangleNames(listOf(
classTestName("A"), "${this.javaClass.`package`.name}.I")).carpenterSchema()
classTestName("A"), "${this.javaClass.`package`.name}.I")).carpenterSchema(ClassLoader.getSystemClassLoader())
}
@Test
@ -315,7 +315,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val amqpSchema = serSchema.mangleNames(listOf(classTestName("A"), "${this.javaClass.`package`.name}.I"))
val aName = mangleName(classTestName("A"))
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
// schema for A until we have for I
@ -362,7 +362,7 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val aName = mangleName(classTestName("A"))
val iName = mangleName("${this.javaClass.`package`.name}.I")
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
// 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 iName = mangleName("${this.javaClass.`package`.name}.I")
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
// in that reverse order (I -> III -> A)

View File

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

View File

@ -30,7 +30,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("int", amqpSchema.fields[0].type)
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 aBuilder = ClassCarpenter().build(aSchema)
@ -58,7 +61,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val amqpSchema = obj.envelope.schema.types[0] as CompositeType
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 aBuilder = ClassCarpenter().build(aSchema)
@ -90,7 +96,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("long", amqpSchema.fields[0].type)
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 aBuilder = ClassCarpenter().build(aSchema)
@ -122,7 +131,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("short", amqpSchema.fields[0].type)
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 aBuilder = ClassCarpenter().build(aSchema)
@ -154,7 +166,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("double", amqpSchema.fields[0].type)
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 aBuilder = ClassCarpenter().build(aSchema)
@ -186,7 +201,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals("float", amqpSchema.fields[0].type)
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 aBuilder = ClassCarpenter().build(aSchema)