mirror of
https://github.com/corda/corda.git
synced 2025-02-06 11:09:18 +00:00
CORDA-1140 - FOR RPC Client P2P context use AMQP (#2716)
* CORDA-1140 - FOR RPC Client P2P context use AMQP * Review comments * Review comments * review comments * review comments
This commit is contained in:
parent
29ccd4dbb8
commit
d116b5e9f4
@ -6,7 +6,7 @@ import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
|||||||
import net.corda.core.serialization.internal.SerializationEnvironment
|
import net.corda.core.serialization.internal.SerializationEnvironment
|
||||||
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
||||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||||
import net.corda.nodeapi.internal.serialization.KRYO_P2P_CONTEXT
|
import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT
|
||||||
import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
|
import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
||||||
import net.corda.nodeapi.internal.serialization.amqp.AMQPClientSerializationScheme
|
import net.corda.nodeapi.internal.serialization.amqp.AMQPClientSerializationScheme
|
||||||
@ -43,7 +43,7 @@ class KryoClientSerializationScheme : AbstractKryoSerializationScheme() {
|
|||||||
registerScheme(KryoClientSerializationScheme())
|
registerScheme(KryoClientSerializationScheme())
|
||||||
registerScheme(AMQPClientSerializationScheme(emptyList()))
|
registerScheme(AMQPClientSerializationScheme(emptyList()))
|
||||||
},
|
},
|
||||||
KRYO_P2P_CONTEXT,
|
AMQP_P2P_CONTEXT,
|
||||||
rpcClientContext = KRYO_RPC_CLIENT_CONTEXT)
|
rpcClientContext = KRYO_RPC_CLIENT_CONTEXT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.nodeapi.internal.serialization.KRYO_CHECKPOINT_CONTEXT
|
import net.corda.nodeapi.internal.serialization.KRYO_CHECKPOINT_CONTEXT
|
||||||
import net.corda.nodeapi.internal.serialization.KRYO_P2P_CONTEXT
|
|
||||||
import net.corda.testing.core.SerializationEnvironmentRule
|
import net.corda.testing.core.SerializationEnvironmentRule
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
@ -39,14 +38,6 @@ class KotlinUtilsTest {
|
|||||||
assertThat(copy.transientVal).isEqualTo(copyVal)
|
assertThat(copy.transientVal).isEqualTo(copyVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `serialise transient property with non-capturing lambda`() {
|
|
||||||
expectedEx.expect(KryoException::class.java)
|
|
||||||
expectedEx.expectMessage("is not annotated or on the whitelist, so cannot be used in serialization")
|
|
||||||
val original = NonCapturingTransientProperty()
|
|
||||||
original.serialize(context = KRYO_P2P_CONTEXT)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `deserialise transient property with non-capturing lambda`() {
|
fun `deserialise transient property with non-capturing lambda`() {
|
||||||
expectedEx.expect(KryoException::class.java)
|
expectedEx.expect(KryoException::class.java)
|
||||||
@ -66,14 +57,6 @@ class KotlinUtilsTest {
|
|||||||
assertThat(copy.transientVal).startsWith("Hello")
|
assertThat(copy.transientVal).startsWith("Hello")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `serialise transient property with capturing lambda`() {
|
|
||||||
expectedEx.expect(KryoException::class.java)
|
|
||||||
expectedEx.expectMessage("is not annotated or on the whitelist, so cannot be used in serialization")
|
|
||||||
val original = CapturingTransientProperty("Hello")
|
|
||||||
original.serialize(context = KRYO_P2P_CONTEXT)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `deserialise transient property with capturing lambda`() {
|
fun `deserialise transient property with capturing lambda`() {
|
||||||
expectedEx.expect(KryoException::class.java)
|
expectedEx.expect(KryoException::class.java)
|
||||||
|
@ -29,14 +29,7 @@ val KRYO_RPC_SERVER_CONTEXT = SerializationContextImpl(kryoMagic,
|
|||||||
true,
|
true,
|
||||||
SerializationContext.UseCase.RPCServer,
|
SerializationContext.UseCase.RPCServer,
|
||||||
null)
|
null)
|
||||||
val KRYO_STORAGE_CONTEXT = SerializationContextImpl(kryoMagic,
|
|
||||||
SerializationDefaults.javaClass.classLoader,
|
|
||||||
AllButBlacklisted,
|
|
||||||
emptyMap(),
|
|
||||||
true,
|
|
||||||
SerializationContext.UseCase.Storage,
|
|
||||||
null,
|
|
||||||
AlwaysAcceptEncodingWhitelist)
|
|
||||||
val AMQP_STORAGE_CONTEXT = SerializationContextImpl(amqpMagic,
|
val AMQP_STORAGE_CONTEXT = SerializationContextImpl(amqpMagic,
|
||||||
SerializationDefaults.javaClass.classLoader,
|
SerializationDefaults.javaClass.classLoader,
|
||||||
AllButBlacklisted,
|
AllButBlacklisted,
|
||||||
@ -45,6 +38,7 @@ val AMQP_STORAGE_CONTEXT = SerializationContextImpl(amqpMagic,
|
|||||||
SerializationContext.UseCase.Storage,
|
SerializationContext.UseCase.Storage,
|
||||||
null,
|
null,
|
||||||
AlwaysAcceptEncodingWhitelist)
|
AlwaysAcceptEncodingWhitelist)
|
||||||
|
|
||||||
val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(amqpMagic,
|
val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(amqpMagic,
|
||||||
SerializationDefaults.javaClass.classLoader,
|
SerializationDefaults.javaClass.classLoader,
|
||||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
||||||
|
@ -16,14 +16,6 @@ import net.corda.nodeapi.internal.serialization.kryo.kryoMagic
|
|||||||
* CANNOT always be instantiated outside of the server and so
|
* CANNOT always be instantiated outside of the server and so
|
||||||
* MUST be kept separate from these ones!
|
* MUST be kept separate from these ones!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val KRYO_P2P_CONTEXT = SerializationContextImpl(kryoMagic,
|
|
||||||
SerializationDefaults.javaClass.classLoader,
|
|
||||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
|
||||||
emptyMap(),
|
|
||||||
true,
|
|
||||||
SerializationContext.UseCase.P2P,
|
|
||||||
null)
|
|
||||||
val KRYO_CHECKPOINT_CONTEXT = SerializationContextImpl(kryoMagic,
|
val KRYO_CHECKPOINT_CONTEXT = SerializationContextImpl(kryoMagic,
|
||||||
SerializationDefaults.javaClass.classLoader,
|
SerializationDefaults.javaClass.classLoader,
|
||||||
QuasarWhitelist,
|
QuasarWhitelist,
|
||||||
@ -32,6 +24,7 @@ val KRYO_CHECKPOINT_CONTEXT = SerializationContextImpl(kryoMagic,
|
|||||||
SerializationContext.UseCase.Checkpoint,
|
SerializationContext.UseCase.Checkpoint,
|
||||||
null,
|
null,
|
||||||
AlwaysAcceptEncodingWhitelist)
|
AlwaysAcceptEncodingWhitelist)
|
||||||
|
|
||||||
val AMQP_P2P_CONTEXT = SerializationContextImpl(amqpMagic,
|
val AMQP_P2P_CONTEXT = SerializationContextImpl(amqpMagic,
|
||||||
SerializationDefaults.javaClass.classLoader,
|
SerializationDefaults.javaClass.classLoader,
|
||||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
|
|
||||||
package net.corda.nodeapi.internal.serialization.amqp
|
package net.corda.nodeapi.internal.serialization.amqp
|
||||||
|
|
||||||
|
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
|
import net.corda.core.internal.objectOrNewInstance
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.*
|
||||||
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
import net.corda.nodeapi.internal.serialization.CordaSerializationMagic
|
||||||
import net.corda.core.utilities.ByteSequence
|
import net.corda.core.utilities.ByteSequence
|
||||||
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
||||||
import net.corda.nodeapi.internal.serialization.MutableClassWhitelist
|
import net.corda.nodeapi.internal.serialization.MutableClassWhitelist
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationScheme
|
import net.corda.nodeapi.internal.serialization.SerializationScheme
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@ -28,10 +31,20 @@ fun SerializerFactory.addToWhitelist(vararg types: Class<*>) {
|
|||||||
|
|
||||||
abstract class AbstractAMQPSerializationScheme(val cordappLoader: List<Cordapp>) : SerializationScheme {
|
abstract class AbstractAMQPSerializationScheme(val cordappLoader: List<Cordapp>) : SerializationScheme {
|
||||||
|
|
||||||
|
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
|
||||||
|
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
|
||||||
companion object {
|
companion object {
|
||||||
private val serializationWhitelists: List<SerializationWhitelist> by lazy {
|
private val serializationWhitelists: List<SerializationWhitelist> by lazy {
|
||||||
ServiceLoader.load(SerializationWhitelist::class.java, this::class.java.classLoader).toList() + DefaultWhitelist
|
ServiceLoader.load(SerializationWhitelist::class.java, this::class.java.classLoader).toList() + DefaultWhitelist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val customSerializers: List<SerializationCustomSerializer<*, *>> by lazy {
|
||||||
|
FastClasspathScanner().addClassLoader(this::class.java.classLoader).scan()
|
||||||
|
.getNamesOfClassesImplementing(SerializationCustomSerializer::class.java)
|
||||||
|
.mapNotNull { this::class.java.classLoader.loadClass(it).asSubclass(SerializationCustomSerializer::class.java) }
|
||||||
|
.filterNot { Modifier.isAbstract(it.modifiers) }
|
||||||
|
.map { it.kotlin.objectOrNewInstance() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerCustomSerializers(factory: SerializerFactory) {
|
private fun registerCustomSerializers(factory: SerializerFactory) {
|
||||||
@ -69,11 +82,20 @@ abstract class AbstractAMQPSerializationScheme(val cordappLoader: List<Cordapp>)
|
|||||||
factory.addToWhitelist(*whitelistProvider.whitelist.toTypedArray())
|
factory.addToWhitelist(*whitelistProvider.whitelist.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
for (loader in cordappLoader) {
|
// If we're passed in an external list we trust that, otherwise revert to looking at the scan of the
|
||||||
for (schema in loader.serializationCustomSerializers) {
|
// classpath to find custom serializers.
|
||||||
factory.registerExternal(CorDappCustomSerializer(schema, factory))
|
if (cordappLoader.isEmpty()) {
|
||||||
|
for (customSerializer in customSerializers) {
|
||||||
|
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cordappLoader.forEach { loader ->
|
||||||
|
for (customSerializer in loader.serializationCustomSerializers) {
|
||||||
|
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val serializerFactoriesForContexts = ConcurrentHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>()
|
private val serializerFactoriesForContexts = ConcurrentHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user