Merge remote-tracking branch 'remotes/open/master' into merges/os-merge-to-ecbf23a

This commit is contained in:
szymonsztuka 2018-11-07 18:17:29 +00:00
commit 44dfa23ad5
40 changed files with 730 additions and 355 deletions

4
.idea/compiler.xml generated
View File

@ -106,10 +106,6 @@
<module name="core_main" target="1.8" /> <module name="core_main" target="1.8" />
<module name="core_smokeTest" target="1.8" /> <module name="core_smokeTest" target="1.8" />
<module name="core_test" target="1.8" /> <module name="core_test" target="1.8" />
<module name="crypto-service_main" target="1.8" />
<module name="crypto-service_test" target="1.8" />
<module name="crypto-services_main" target="1.8" />
<module name="crypto-services_test" target="1.8" />
<module name="data_main" target="1.8" /> <module name="data_main" target="1.8" />
<module name="data_test" target="1.8" /> <module name="data_test" target="1.8" />
<module name="dbmigration_main" target="1.8" /> <module name="dbmigration_main" target="1.8" />

View File

@ -38,10 +38,7 @@ import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.parseAsHex import net.corda.core.utilities.parseAsHex
import net.corda.core.utilities.toHexString import net.corda.core.utilities.toHexString
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.*
import net.corda.serialization.internal.amqp.constructorForDeserialization
import net.corda.serialization.internal.amqp.hasCordaSerializable
import net.corda.serialization.internal.amqp.propertiesForSerialization
import java.math.BigDecimal import java.math.BigDecimal
import java.security.PublicKey import java.security.PublicKey
import java.security.cert.CertPath import java.security.cert.CertPath
@ -88,7 +85,7 @@ class CordaModule : SimpleModule("corda-core") {
*/ */
private class CordaSerializableBeanSerializerModifier : BeanSerializerModifier() { private class CordaSerializableBeanSerializerModifier : BeanSerializerModifier() {
// We need to pass in a SerializerFactory when scanning for properties, but don't actually do any serialisation so any will do. // We need to pass in a SerializerFactory when scanning for properties, but don't actually do any serialisation so any will do.
private val serializerFactory = SerializerFactory(AllWhitelist, javaClass.classLoader) private val serializerFactory = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader)
override fun changeProperties(config: SerializationConfig, override fun changeProperties(config: SerializationConfig,
beanDesc: BeanDescription, beanDesc: BeanDescription,

View File

@ -8,10 +8,7 @@ import net.corda.core.serialization.SerializationCustomSerializer
import net.corda.core.serialization.internal.SerializationEnvironment import net.corda.core.serialization.internal.SerializationEnvironment
import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.serialization.internal.nodeSerializationEnv
import net.corda.serialization.internal.* import net.corda.serialization.internal.*
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.*
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.amqp.amqpMagic
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
/** /**
@ -52,7 +49,7 @@ class AMQPClientSerializationScheme(
} }
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory { override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply { return SerializerFactoryBuilder.build(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply {
register(RpcClientObservableDeSerializer) register(RpcClientObservableDeSerializer)
register(RpcClientCordaFutureSerializer(this)) register(RpcClientCordaFutureSerializer(this))
register(RxNotificationSerializer(this)) register(RxNotificationSerializer(this))

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=4.0.33 gradlePluginsVersion=4.0.34
kotlinVersion=1.2.71 kotlinVersion=1.2.71
# ***************************************************************# # ***************************************************************#
# When incrementing platformVersion make sure to update # # When incrementing platformVersion make sure to update #

View File

@ -1,18 +1,23 @@
package net.corda.core package net.corda.core
import net.corda.core.crypto.internal.AliasPrivateKey
/** /**
* OIDs used for the Corda platform. Entries MUST NOT be removed from this file; if an OID is incorrectly assigned it * OIDs used for the Corda platform. All entries MUST be defined in this file only and they MUST NOT be removed.
* should be marked deprecated. * If an OID is incorrectly assigned, it should be marked deprecated and NEVER be reused again.
*/ */
@KeepForDJVM @KeepForDJVM
object CordaOID { object CordaOID {
/** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */ /** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */
const val R3_ROOT = "1.3.6.1.4.1.50530" const val R3_ROOT = "1.3.6.1.4.1.50530"
/** OIDs issued for the Corda platform */ /** OIDs issued for the Corda platform. */
const val CORDA_PLATFORM = "$R3_ROOT.1" const val CORDA_PLATFORM = "$R3_ROOT.1"
/** /**
* Identifier for the X.509 certificate extension specifying the Corda role. See * Identifier for the X.509 certificate extension specifying the Corda role. See
* https://r3-cev.atlassian.net/wiki/spaces/AWG/pages/156860572/Certificate+identity+type+extension for details. * https://r3-cev.atlassian.net/wiki/spaces/AWG/pages/156860572/Certificate+identity+type+extension for details.
*/ */
const val X509_EXTENSION_CORDA_ROLE = "$CORDA_PLATFORM.1" const val X509_EXTENSION_CORDA_ROLE = "$CORDA_PLATFORM.1"
/** OID for [AliasPrivateKey]. */
const val ALIAS_PRIVATE_KEY = "$CORDA_PLATFORM.2"
} }

View File

@ -42,7 +42,9 @@ private fun provideNonDeterministic(provider: Provider) {
@KeepForDJVM @KeepForDJVM
object CordaObjectIdentifier { object CordaObjectIdentifier {
// UUID-based OID // UUID-based OID
// TODO: Register for an OID space and issue our own shorter OID. // TODO define and use an official Corda OID in [CordaOID]. We didn't do yet for backwards compatibility purposes,
// because key.encoded (serialised version of keys) and [PublicKey.hash] for already stored [CompositeKey]s
// will not match.
@JvmField @JvmField
val COMPOSITE_KEY = ASN1ObjectIdentifier("2.25.30086077608615255153862931087626791002") val COMPOSITE_KEY = ASN1ObjectIdentifier("2.25.30086077608615255153862931087626791002")
@JvmField @JvmField

View File

@ -1,5 +1,6 @@
package net.corda.core.crypto.internal package net.corda.core.crypto.internal
import net.corda.core.CordaOID
import org.bouncycastle.asn1.* import org.bouncycastle.asn1.*
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
import org.bouncycastle.asn1.x509.AlgorithmIdentifier import org.bouncycastle.asn1.x509.AlgorithmIdentifier
@ -17,12 +18,7 @@ import java.security.spec.PKCS8EncodedKeySpec
data class AliasPrivateKey(val alias: String): PrivateKey { data class AliasPrivateKey(val alias: String): PrivateKey {
companion object { companion object {
// UUID-based OID const val ALIAS_KEY_ALGORITHM = "AliasPrivateKey"
// TODO: Register for an OID space and issue our own shorter OID.
@JvmField
val ALIAS_PRIVATE_KEY = ASN1ObjectIdentifier("2.26.40086077608615255153862931087626791001")
const val ALIAS_KEY_ALGORITHM = "ALIAS"
} }
override fun getAlgorithm() = ALIAS_KEY_ALGORITHM override fun getAlgorithm() = ALIAS_KEY_ALGORITHM
@ -30,7 +26,10 @@ data class AliasPrivateKey(val alias: String): PrivateKey {
override fun getEncoded(): ByteArray { override fun getEncoded(): ByteArray {
val keyVector = ASN1EncodableVector() val keyVector = ASN1EncodableVector()
keyVector.add(DERUTF8String(alias)) keyVector.add(DERUTF8String(alias))
val privateKeyInfoBytes = PrivateKeyInfo(AlgorithmIdentifier(ALIAS_PRIVATE_KEY), DERSequence(keyVector)).getEncoded(ASN1Encoding.DER) val privateKeyInfoBytes = PrivateKeyInfo(
AlgorithmIdentifier(ASN1ObjectIdentifier(CordaOID.ALIAS_PRIVATE_KEY)),
DERSequence(keyVector)
).getEncoded(ASN1Encoding.DER)
val keySpec = PKCS8EncodedKeySpec(privateKeyInfoBytes) val keySpec = PKCS8EncodedKeySpec(privateKeyInfoBytes)
return keySpec.encoded return keySpec.encoded
} }

View File

@ -6,7 +6,7 @@ import net.corda.serialization.internal.AMQP_RPC_CLIENT_CONTEXT
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.DeserializationInput import net.corda.serialization.internal.amqp.DeserializationInput
import net.corda.serialization.internal.amqp.SerializationOutput import net.corda.serialization.internal.amqp.SerializationOutput
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactoryBuilder
import net.corda.serialization.internal.amqp.custom.PublicKeySerializer import net.corda.serialization.internal.amqp.custom.PublicKeySerializer
import net.corda.testing.core.DUMMY_BANK_A_NAME import net.corda.testing.core.DUMMY_BANK_A_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME import net.corda.testing.core.DUMMY_NOTARY_NAME
@ -15,7 +15,7 @@ import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class TransactionVerificationExceptionSerialisationTests { class TransactionVerificationExceptionSerialisationTests {
private fun defaultFactory() = SerializerFactory( private fun defaultFactory() = SerializerFactoryBuilder.build(
AllWhitelist, AllWhitelist,
ClassLoader.getSystemClassLoader() ClassLoader.getSystemClassLoader()
) )

View File

@ -320,6 +320,8 @@ absolute path to the node's base directory.
Valid values for this property are between 4 (that is the number used for the single threaded state machine in Valid values for this property are between 4 (that is the number used for the single threaded state machine in
open source) and the number of flow threads. open source) and the number of flow threads.
.. _corda_configuration_file_signer_blacklist:
:cordappSignerKeyFingerprintBlacklist: List of public keys fingerprints (SHA-256 of public key hash) not allowed as Cordapp JARs signers. :cordappSignerKeyFingerprintBlacklist: List of public keys fingerprints (SHA-256 of public key hash) not allowed as Cordapp JARs signers.
Node will not load Cordapps signed by those keys. Node will not load Cordapps signed by those keys.
The option takes effect only in production mode and defaults to Corda development keys (``["56CA54E803CB87C8472EBD3FBC6A2F1876E814CEEBF74860BD46997F40729367", The option takes effect only in production mode and defaults to Corda development keys (``["56CA54E803CB87C8472EBD3FBC6A2F1876E814CEEBF74860BD46997F40729367",

View File

@ -162,6 +162,9 @@ without need to create a keystore and configure the ``cordapp`` plugin.
For production deployment ensure to sign the CorDapp using your own certificate e.g. by setting system properties to point to an external keystore For production deployment ensure to sign the CorDapp using your own certificate e.g. by setting system properties to point to an external keystore
or by disabling signing in ``cordapp`` plugin and signing the CordDapp JAR downstream in your build pipeline. or by disabling signing in ``cordapp`` plugin and signing the CordDapp JAR downstream in your build pipeline.
CorDapp signed by Corda development certificate is accepted by Corda node only when running in the development mode. CorDapp signed by Corda development certificate is accepted by Corda node only when running in the development mode.
In case CordDapp signed by the (default) development key is run on node in the production mode (e.g. for testing),
the node may be set to accept the development key by adding the ``cordappSignerKeyFingerprintBlacklist = []`` property set to empty list
(see :ref:`Configuring a node <corda_configuration_file_signer_blacklist>`).
Signing options can be contextually overwritten by the relevant system properties as described above. Signing options can be contextually overwritten by the relevant system properties as described above.
This allows the single ``build.gradle`` file to be used for a development build (defaulting to the Corda development keystore) This allows the single ``build.gradle`` file to be used for a development build (defaulting to the Corda development keystore)

View File

@ -139,3 +139,62 @@ the ``SubResponder`` with ``BaseResponder``
} }
This will generate the corresponding ``flowOverrides`` section and place it in the configuration for that node. This will generate the corresponding ``flowOverrides`` section and place it in the configuration for that node.
Modifying the behaviour of @InitiatingFlow(s)
---------------------------------------------
It is likely that initiating flows will also require changes to reflect the different systems that are likely to be encountered.
At the moment, corda provides the ability to subclass an Initiator, and ensures that the correct responder will be invoked.
In the below example, we will change the behaviour of an Initiator from filtering Notaries out from comms, to only communicating with Notaries
.. code-block:: kotlin
@InitiatingFlow
@StartableByRPC
@StartableByService
open class BaseInitiator : FlowLogic<String>() {
@Suspendable
override fun call(): String {
val partiesToTalkTo = serviceHub.networkMapCache.allNodes
.filterNot { it.legalIdentities.first() in serviceHub.networkMapCache.notaryIdentities }
.filterNot { it.legalIdentities.first().name == ourIdentity.name }.map { it.legalIdentities.first() }
val responses = ArrayList<String>()
for (party in partiesToTalkTo) {
val session = initiateFlow(party)
val received = session.receive<String>().unwrap { it }
responses.add(party.name.toString() + " responded with backend: " + received)
}
return "${getFLowName()} received the following \n" + responses.joinToString("\n") { it }
}
open fun getFLowName(): String {
return "Normal Computer"
}
}
@StartableByRPC
@StartableByService
class NotaryOnlyInitiator : BaseInitiator() {
@Suspendable
override fun call(): String {
return "Notary Communicator received:\n" + serviceHub.networkMapCache.notaryIdentities.map {
"Notary: ${it.name.organisation} is using a " + initiateFlow(it).receive<String>().unwrap { it }
}.joinToString("\n") { it }
}
.. warning:: The subclass must not have the @InitiatingFlow annotation.
Corda will use the first annotation detected in the class hierarchy to determine which responder should be invoked. So for a Responder similar to
.. code-block:: kotlin
@InitiatedBy(BaseInitiator::class)
class BobbyResponder(othersideSession: FlowSession) : BaseResponder(othersideSession) {
override fun getMessageFromBackend(): String {
return "Robert'); DROP TABLE STATES;"
}
}
it would be possible to invoke either ``BaseInitiator`` or ``NotaryOnlyInitiator`` and ``BobbyResponder`` would be used to reply.
.. warning:: You must ensure the sequence of sends/receives/subFlows in a subclass are compatible with the parent.

View File

@ -1,6 +1,7 @@
package net.corda.nodeapi.internal.network package net.corda.nodeapi.internal.network
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import net.corda.core.crypto.toStringShort import net.corda.core.crypto.toStringShort
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
@ -30,6 +31,7 @@ import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.SerializationFactoryImpl import net.corda.serialization.internal.SerializationFactoryImpl
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
import net.corda.serialization.internal.amqp.amqpMagic import net.corda.serialization.internal.amqp.amqpMagic
import java.io.File
import java.io.InputStream import java.io.InputStream
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.StandardCopyOption.REPLACE_EXISTING import java.nio.file.StandardCopyOption.REPLACE_EXISTING
@ -96,21 +98,36 @@ internal constructor(private val initSerEnv: Boolean,
private fun generateNodeInfo(nodeDir: Path): Path { private fun generateNodeInfo(nodeDir: Path): Path {
val logsDir = (nodeDir / LOGS_DIR_NAME).createDirectories() val logsDir = (nodeDir / LOGS_DIR_NAME).createDirectories()
val nodeInfoGenFile = (logsDir / "node-info-gen.log").toFile()
val process = ProcessBuilder(nodeInfoGenCmd) val process = ProcessBuilder(nodeInfoGenCmd)
.directory(nodeDir.toFile()) .directory(nodeDir.toFile())
.redirectErrorStream(true) .redirectErrorStream(true)
.redirectOutput((logsDir / "node-info-gen.log").toFile()) .redirectOutput(nodeInfoGenFile)
.apply { environment()["CAPSULE_CACHE_DIR"] = "../.cache" } .apply { environment()["CAPSULE_CACHE_DIR"] = "../.cache" }
.start() .start()
if (!process.waitFor(3, TimeUnit.MINUTES)) { if (!process.waitFor(3, TimeUnit.MINUTES)) {
process.destroyForcibly() process.destroyForcibly()
throw IllegalStateException("Error while generating node info file. Please check the logs in $logsDir.") printNodeInfoGenLogToConsole(nodeInfoGenFile)
} }
check(process.exitValue() == 0) { "Error while generating node info file. Please check the logs in $logsDir." } printNodeInfoGenLogToConsole(nodeInfoGenFile) { process.exitValue() == 0 }
return nodeDir.list { paths -> return nodeDir.list { paths ->
paths.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get() paths.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get()
} }
} }
private fun printNodeInfoGenLogToConsole(nodeInfoGenFile: File, check: (() -> Boolean) = { true }) {
if (!check.invoke()) {
val nodeDir = nodeInfoGenFile.parent
val nodeIdentifier = try {
ConfigFactory.parseFile((nodeDir / "node.conf").toFile()).getString("myLegalName")
} catch (e: ConfigException) {
nodeDir
}
System.err.println("#### Error while generating node info file $nodeIdentifier ####")
nodeInfoGenFile.inputStream().copyTo(System.err)
throw IllegalStateException("Error while generating node info file. Please check the logs in $nodeDir.")
}
}
} }
sealed class NotaryCluster { sealed class NotaryCluster {
@ -142,7 +159,7 @@ internal constructor(private val initSerEnv: Boolean,
private fun isBFTNotary(config: Config): Boolean { private fun isBFTNotary(config: Config): Boolean {
// TODO: pass a commandline parameter to the bootstrapper instead. Better yet, a notary config map // TODO: pass a commandline parameter to the bootstrapper instead. Better yet, a notary config map
// specifying the notary identities and the type (single-node, CFT, BFT) of each notary to set up. // specifying the notary identities and the type (single-node, CFT, BFT) of each notary to set up.
return config.getString ("notary.className").contains("BFT", true) return config.getString("notary.className").contains("BFT", true)
} }
private fun generateServiceIdentitiesForNotaryClusters(configs: Map<Path, Config>) { private fun generateServiceIdentitiesForNotaryClusters(configs: Map<Path, Config>) {
@ -172,7 +189,7 @@ internal constructor(private val initSerEnv: Boolean,
} }
/** Entry point for the tool */ /** Entry point for the tool */
fun bootstrap(directory: Path, copyCordapps: Boolean, minimumPlatformVersion: Int, packageOwnership : Map<JavaPackageName, PublicKey?> = emptyMap()) { fun bootstrap(directory: Path, copyCordapps: Boolean, minimumPlatformVersion: Int, packageOwnership: Map<JavaPackageName, PublicKey?> = emptyMap()) {
require(minimumPlatformVersion <= PLATFORM_VERSION) { "Minimum platform version cannot be greater than $PLATFORM_VERSION" } require(minimumPlatformVersion <= PLATFORM_VERSION) { "Minimum platform version cannot be greater than $PLATFORM_VERSION" }
// Don't accidently include the bootstrapper jar as a CorDapp! // Don't accidently include the bootstrapper jar as a CorDapp!
val bootstrapperJar = javaClass.location.toPath() val bootstrapperJar = javaClass.location.toPath()
@ -188,7 +205,7 @@ internal constructor(private val initSerEnv: Boolean,
copyCordapps: Boolean, copyCordapps: Boolean,
fromCordform: Boolean, fromCordform: Boolean,
minimumPlatformVersion: Int = PLATFORM_VERSION, minimumPlatformVersion: Int = PLATFORM_VERSION,
packageOwnership : Map<JavaPackageName, PublicKey?> = emptyMap() packageOwnership: Map<JavaPackageName, PublicKey?> = emptyMap()
) { ) {
directory.createDirectories() directory.createDirectories()
println("Bootstrapping local test network in $directory") println("Bootstrapping local test network in $directory")
@ -361,7 +378,7 @@ internal constructor(private val initSerEnv: Boolean,
existingNetParams: NetworkParameters?, existingNetParams: NetworkParameters?,
nodeDirs: List<Path>, nodeDirs: List<Path>,
minimumPlatformVersion: Int, minimumPlatformVersion: Int,
packageOwnership : Map<JavaPackageName, PublicKey?> packageOwnership: Map<JavaPackageName, PublicKey?>
): NetworkParameters { ): NetworkParameters {
// TODO Add config for maxMessageSize and maxTransactionSize // TODO Add config for maxMessageSize and maxTransactionSize
val netParams = if (existingNetParams != null) { val netParams = if (existingNetParams != null) {
@ -369,13 +386,12 @@ internal constructor(private val initSerEnv: Boolean,
existingNetParams.packageOwnership.entries.containsAll(packageOwnership.entries)) { existingNetParams.packageOwnership.entries.containsAll(packageOwnership.entries)) {
existingNetParams existingNetParams
} else { } else {
var updatePackageOwnership = mutableMapOf(*existingNetParams.packageOwnership.map { Pair(it.key,it.value) }.toTypedArray()) var updatePackageOwnership = mutableMapOf(*existingNetParams.packageOwnership.map { Pair(it.key, it.value) }.toTypedArray())
packageOwnership.forEach { key, value -> packageOwnership.forEach { key, value ->
if (value == null) { if (value == null) {
if (updatePackageOwnership.remove(key) != null) if (updatePackageOwnership.remove(key) != null)
println("Unregistering package $key") println("Unregistering package $key")
} } else {
else {
if (updatePackageOwnership.put(key, value) == null) if (updatePackageOwnership.put(key, value) == null)
println("Registering package $key for owner ${value.toStringShort()}") println("Registering package $key for owner ${value.toStringShort()}")
} }

View File

@ -8,6 +8,7 @@ import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.amqp.SerializerFactoryBuilder
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
/** /**
@ -28,7 +29,7 @@ class AMQPServerSerializationScheme(
} }
override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory { override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply { return SerializerFactoryBuilder.build(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply {
register(RpcServerObservableSerializer()) register(RpcServerObservableSerializer())
register(RpcServerCordaFutureSerializer(this)) register(RpcServerCordaFutureSerializer(this))
register(RxNotificationSerializer(this)) register(RxNotificationSerializer(this))

View File

@ -10,7 +10,7 @@ import net.corda.node.serialization.amqp.RpcServerObservableSerializer
import net.corda.node.services.messaging.ObservableSubscription import net.corda.node.services.messaging.ObservableSubscription
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.SerializationOutput import net.corda.serialization.internal.amqp.SerializationOutput
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactoryBuilder
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.Test import org.junit.Test
import rx.Observable import rx.Observable
@ -34,7 +34,7 @@ class RpcServerObservableSerializerTests {
@Test @Test
fun canSerializerBeRegistered() { fun canSerializerBeRegistered() {
val sf = SerializerFactory(AllWhitelist, javaClass.classLoader) val sf = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader)
try { try {
sf.register(RpcServerObservableSerializer()) sf.register(RpcServerObservableSerializer())
@ -67,7 +67,7 @@ class RpcServerObservableSerializerTests {
deduplicationIdentity = "thisIsATest", deduplicationIdentity = "thisIsATest",
clientAddress = SimpleString(testClientAddress)) clientAddress = SimpleString(testClientAddress))
val sf = SerializerFactory(AllWhitelist, javaClass.classLoader).apply { val sf = SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).apply {
register(RpcServerObservableSerializer()) register(RpcServerObservableSerializer())
} }

View File

@ -12,6 +12,7 @@ import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
import net.corda.serialization.internal.amqp.SerializerFactoryBuilder
import net.corda.client.rpc.internal.ObservableContext as ClientObservableContext import net.corda.client.rpc.internal.ObservableContext as ClientObservableContext
/** /**
@ -28,13 +29,13 @@ class AMQPRoundTripRPCSerializationScheme(
cordappCustomSerializers, serializerFactoriesForContexts cordappCustomSerializers, serializerFactoriesForContexts
) { ) {
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory { override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
return SerializerFactory(AllWhitelist, javaClass.classLoader).apply { return SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).apply {
register(RpcClientObservableDeSerializer) register(RpcClientObservableDeSerializer)
} }
} }
override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory { override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
return SerializerFactory(AllWhitelist, javaClass.classLoader).apply { return SerializerFactoryBuilder.build(AllWhitelist, javaClass.classLoader).apply {
register(RpcServerObservableSerializer()) register(RpcServerObservableSerializer())
} }
} }

View File

@ -50,6 +50,7 @@ task patchSerialization(type: Zip, dependsOn: serializationJarTask) {
exclude 'net/corda/serialization/internal/amqp/AMQPSerializerFactories*' exclude 'net/corda/serialization/internal/amqp/AMQPSerializerFactories*'
exclude 'net/corda/serialization/internal/amqp/AMQPStreams*' exclude 'net/corda/serialization/internal/amqp/AMQPStreams*'
exclude 'net/corda/serialization/internal/amqp/AMQPSerializationThreadContext*' exclude 'net/corda/serialization/internal/amqp/AMQPSerializationThreadContext*'
exclude 'net/corda/serialization/internal/model/DefaultCacheProvider*'
} }
reproducibleFileOrder = true reproducibleFileOrder = true

View File

@ -15,15 +15,9 @@ fun createSerializerFactoryFactory(): SerializerFactoryFactory = DeterministicSe
private class DeterministicSerializerFactoryFactory : SerializerFactoryFactory { private class DeterministicSerializerFactoryFactory : SerializerFactoryFactory {
override fun make(context: SerializationContext) = override fun make(context: SerializationContext) =
SerializerFactory( SerializerFactoryBuilder.build(
whitelist = context.whitelist, whitelist = context.whitelist,
classCarpenter = DummyClassCarpenter(context.whitelist, context.deserializationClassLoader), classCarpenter = DummyClassCarpenter(context.whitelist, context.deserializationClassLoader))
serializersByType = mutableMapOf(),
serializersByDescriptor = mutableMapOf(),
customSerializers = ArrayList(),
customSerializersCache = mutableMapOf(),
transformsCache = mutableMapOf()
)
} }
private class DummyClassCarpenter( private class DummyClassCarpenter(

View File

@ -0,0 +1,9 @@
package net.corda.serialization.internal.model
/**
* We can't have [ConcurrentHashMap]s in the DJVM, so it must supply its own version of this object which returns
* plain old [MutableMap]s instead.
*/
object DefaultCacheProvider {
fun <K, V> createCache(): MutableMap<K, V> = mutableMapOf()
}

View File

@ -3,11 +3,14 @@
package net.corda.serialization.internal.amqp package net.corda.serialization.internal.amqp
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
fun createSerializerFactoryFactory(): SerializerFactoryFactory = SerializerFactoryFactoryImpl() fun createSerializerFactoryFactory(): SerializerFactoryFactory = SerializerFactoryFactoryImpl()
open class SerializerFactoryFactoryImpl : SerializerFactoryFactory { open class SerializerFactoryFactoryImpl : SerializerFactoryFactory {
override fun make(context: SerializationContext): SerializerFactory { override fun make(context: SerializationContext): SerializerFactory {
return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled) return SerializerFactoryBuilder.build(context.whitelist,
ClassCarpenterImpl(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled)
)
} }
} }

View File

@ -1,7 +1,6 @@
package net.corda.serialization.internal.amqp package net.corda.serialization.internal.amqp
import com.google.common.primitives.Primitives import com.google.common.primitives.Primitives
import net.corda.core.DeleteForDJVM
import net.corda.core.KeepForDJVM import net.corda.core.KeepForDJVM
import net.corda.core.StubOutForDJVM import net.corda.core.StubOutForDJVM
import net.corda.core.internal.kotlinObjectInstance import net.corda.core.internal.kotlinObjectInstance
@ -12,12 +11,11 @@ import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.trace import net.corda.core.utilities.trace
import net.corda.serialization.internal.carpenter.* import net.corda.serialization.internal.carpenter.*
import net.corda.serialization.internal.model.DefaultCacheProvider
import org.apache.qpid.proton.amqp.* import org.apache.qpid.proton.amqp.*
import java.io.NotSerializableException import java.io.NotSerializableException
import java.lang.reflect.* import java.lang.reflect.*
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
@KeepForDJVM @KeepForDJVM
@ -49,54 +47,122 @@ data class CustomSerializersCacheKey(val clazz: Class<*>, val declaredType: Type
// 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?
@KeepForDJVM @KeepForDJVM
@ThreadSafe @ThreadSafe
open class SerializerFactory( interface SerializerFactory {
val whitelist: ClassWhitelist, val whitelist: ClassWhitelist
val classCarpenter: ClassCarpenter, val classCarpenter: ClassCarpenter
private val evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, val fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter
val fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, // Caches
private val serializersByType: MutableMap<Type, AMQPSerializer<Any>>, val serializersByType: MutableMap<Type, AMQPSerializer<Any>>
val serializersByDescriptor: MutableMap<Any, AMQPSerializer<Any>>, val serializersByDescriptor: MutableMap<Any, AMQPSerializer<Any>>
private val customSerializers: MutableList<SerializerFor>, val transformsCache: MutableMap<String, EnumMap<TransformTypes, MutableList<Transform>>>
private val customSerializersCache: MutableMap<CustomSerializersCacheKey, AMQPSerializer<Any>?>, val fingerPrinter: FingerPrinter
val transformsCache: MutableMap<String, EnumMap<TransformTypes, MutableList<Transform>>>, val classloader: ClassLoader
/**
* Look up, and manufacture if necessary, a serializer for the given type.
*
* @param actualClass Will be null if there isn't an actual object instance available (e.g. for
* restricted type processing).
*/
@Throws(NotSerializableException::class)
fun get(actualClass: Class<*>?, declaredType: Type): AMQPSerializer<Any>
/**
* Lookup and manufacture a serializer for the given AMQP type descriptor, assuming we also have the necessary types
* contained in the [Schema].
*/
@Throws(NotSerializableException::class)
fun get(typeDescriptor: Any, schema: SerializationSchemas): AMQPSerializer<Any>
/**
* Register a custom serializer for any type that cannot be serialized or deserialized by the default serializer
* that expects to find getters and a constructor with a parameter for each property.
*/
fun register(customSerializer: CustomSerializer<out Any>)
fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer<Any>?
fun registerExternal(customSerializer: CorDappCustomSerializer)
fun registerByDescriptor(name: Symbol, serializerCreator: () -> AMQPSerializer<Any>): AMQPSerializer<Any>
object AnyType : WildcardType {
override fun getUpperBounds(): Array<Type> = arrayOf(Object::class.java)
override fun getLowerBounds(): Array<Type> = emptyArray()
override fun toString(): String = "?"
}
companion object {
fun isPrimitive(type: Type): Boolean = primitiveTypeName(type) != null
fun primitiveTypeName(type: Type): String? {
val clazz = type as? Class<*> ?: return null
return primitiveTypeNames[Primitives.unwrap(clazz)]
}
fun primitiveType(type: String): Class<*>? {
return namesOfPrimitiveTypes[type]
}
private val primitiveTypeNames: Map<Class<*>, String> = mapOf(
Character::class.java to "char",
Char::class.java to "char",
Boolean::class.java to "boolean",
Byte::class.java to "byte",
UnsignedByte::class.java to "ubyte",
Short::class.java to "short",
UnsignedShort::class.java to "ushort",
Int::class.java to "int",
UnsignedInteger::class.java to "uint",
Long::class.java to "long",
UnsignedLong::class.java to "ulong",
Float::class.java to "float",
Double::class.java to "double",
Decimal32::class.java to "decimal32",
Decimal64::class.java to "decimal62",
Decimal128::class.java to "decimal128",
Date::class.java to "timestamp",
UUID::class.java to "uuid",
ByteArray::class.java to "binary",
String::class.java to "string",
Symbol::class.java to "symbol")
private val namesOfPrimitiveTypes: Map<String, Class<*>> = primitiveTypeNames.map { it.value to it.key }.toMap()
fun nameForType(type: Type): String = when (type) {
is Class<*> -> {
primitiveTypeName(type) ?: if (type.isArray) {
"${nameForType(type.componentType)}${if (type.componentType.isPrimitive) "[p]" else "[]"}"
} else type.name
}
is ParameterizedType -> {
"${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>"
}
is GenericArrayType -> "${nameForType(type.genericComponentType)}[]"
is WildcardType -> "?"
is TypeVariable<*> -> "?"
else -> throw AMQPNotSerializableException(type, "Unable to render type $type to a string.")
}
}
}
open class DefaultSerializerFactory(
override val whitelist: ClassWhitelist,
override val classCarpenter: ClassCarpenter,
private val evolutionSerializerProvider: EvolutionSerializerProvider,
override val fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter,
private val onlyCustomSerializers: Boolean = false private val onlyCustomSerializers: Boolean = false
) { ) : SerializerFactory {
@DeleteForDJVM
constructor(whitelist: ClassWhitelist,
classCarpenter: ClassCarpenter,
evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider,
fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter,
onlyCustomSerializers: Boolean = false
) : this(
whitelist,
classCarpenter,
evolutionSerializerProvider,
fingerPrinterConstructor,
ConcurrentHashMap(),
ConcurrentHashMap(),
CopyOnWriteArrayList(),
ConcurrentHashMap(),
ConcurrentHashMap(),
onlyCustomSerializers
)
@DeleteForDJVM // Caches
constructor(whitelist: ClassWhitelist, override val serializersByType: MutableMap<Type, AMQPSerializer<Any>> = DefaultCacheProvider.createCache()
carpenterClassLoader: ClassLoader, override val serializersByDescriptor: MutableMap<Any, AMQPSerializer<Any>> = DefaultCacheProvider.createCache()
lenientCarpenter: Boolean = false, private var customSerializers: List<SerializerFor> = emptyList()
evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider, private val customSerializersCache: MutableMap<CustomSerializersCacheKey, AMQPSerializer<Any>?> = DefaultCacheProvider.createCache()
fingerPrinterConstructor: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter, override val transformsCache: MutableMap<String, EnumMap<TransformTypes, MutableList<Transform>>> = DefaultCacheProvider.createCache()
onlyCustomSerializers: Boolean = false
) : this(
whitelist,
ClassCarpenterImpl(whitelist, carpenterClassLoader, lenientCarpenter),
evolutionSerializerProvider,
fingerPrinterConstructor,
onlyCustomSerializers)
val fingerPrinter by lazy { fingerPrinterConstructor(this) } override val fingerPrinter by lazy { fingerPrinterConstructor(this) }
val classloader: ClassLoader get() = classCarpenter.classloader override val classloader: ClassLoader get() = classCarpenter.classloader
// Used to short circuit any computation for a given input, for performance. // Used to short circuit any computation for a given input, for performance.
private data class MemoType(val actualClass: Class<*>?, val declaredType: Type) : Type private data class MemoType(val actualClass: Class<*>?, val declaredType: Type) : Type
@ -108,7 +174,7 @@ open class SerializerFactory(
* restricted type processing). * restricted type processing).
*/ */
@Throws(NotSerializableException::class) @Throws(NotSerializableException::class)
fun get(actualClass: Class<*>?, declaredType: Type): AMQPSerializer<Any> { override fun get(actualClass: Class<*>?, declaredType: Type): AMQPSerializer<Any> {
// can be useful to enable but will be *extremely* chatty if you do // can be useful to enable but will be *extremely* chatty if you do
logger.trace { "Get Serializer for $actualClass ${declaredType.typeName}" } logger.trace { "Get Serializer for $actualClass ${declaredType.typeName}" }
@ -169,7 +235,7 @@ open class SerializerFactory(
* contained in the [Schema]. * contained in the [Schema].
*/ */
@Throws(NotSerializableException::class) @Throws(NotSerializableException::class)
fun get(typeDescriptor: Any, schema: SerializationSchemas): AMQPSerializer<Any> { override fun get(typeDescriptor: Any, schema: SerializationSchemas): AMQPSerializer<Any> {
return serializersByDescriptor[typeDescriptor] ?: { return serializersByDescriptor[typeDescriptor] ?: {
logger.trace("get Serializer descriptor=${typeDescriptor}") logger.trace("get Serializer descriptor=${typeDescriptor}")
processSchema(FactorySchemaAndDescriptor(schema, typeDescriptor)) processSchema(FactorySchemaAndDescriptor(schema, typeDescriptor))
@ -182,7 +248,7 @@ open class SerializerFactory(
* Register a custom serializer for any type that cannot be serialized or deserialized by the default serializer * Register a custom serializer for any type that cannot be serialized or deserialized by the default serializer
* that expects to find getters and a constructor with a parameter for each property. * that expects to find getters and a constructor with a parameter for each property.
*/ */
open fun register(customSerializer: CustomSerializer<out Any>) { override fun register(customSerializer: CustomSerializer<out Any>) {
logger.trace("action=\"Registering custom serializer\", class=\"${customSerializer.type}\"") logger.trace("action=\"Registering custom serializer\", class=\"${customSerializer.type}\"")
if (!serializersByDescriptor.containsKey(customSerializer.typeDescriptor)) { if (!serializersByDescriptor.containsKey(customSerializer.typeDescriptor)) {
customSerializers += customSerializer customSerializers += customSerializer
@ -193,7 +259,7 @@ open class SerializerFactory(
} }
} }
fun registerExternal(customSerializer: CorDappCustomSerializer) { override fun registerExternal(customSerializer: CorDappCustomSerializer) {
logger.trace("action=\"Registering external serializer\", class=\"${customSerializer.type}\"") logger.trace("action=\"Registering external serializer\", class=\"${customSerializer.type}\"")
if (!serializersByDescriptor.containsKey(customSerializer.typeDescriptor)) { if (!serializersByDescriptor.containsKey(customSerializer.typeDescriptor)) {
customSerializers += customSerializer customSerializers += customSerializer
@ -319,7 +385,7 @@ open class SerializerFactory(
throw AMQPNotSerializableException( throw AMQPNotSerializableException(
type, type,
"Serializer does not support synthetic classes") "Serializer does not support synthetic classes")
} else if (isPrimitive(clazz)) { } else if (SerializerFactory.isPrimitive(clazz)) {
AMQPPrimitiveSerializer(clazz) AMQPPrimitiveSerializer(clazz)
} else { } else {
findCustomSerializer(clazz, declaredType) ?: run { findCustomSerializer(clazz, declaredType) ?: run {
@ -344,7 +410,7 @@ open class SerializerFactory(
} }
} }
internal fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer<Any>? { override fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer<Any>? {
return customSerializersCache.computeIfAbsent(CustomSerializersCacheKey(clazz, declaredType), ::doFindCustomSerializer) return customSerializersCache.computeIfAbsent(CustomSerializersCacheKey(clazz, declaredType), ::doFindCustomSerializer)
} }
@ -383,69 +449,11 @@ open class SerializerFactory(
return MapSerializer(declaredType, this) return MapSerializer(declaredType, this)
} }
fun registerByDescriptor(name: Symbol, serializerCreator: () -> AMQPSerializer<Any>): AMQPSerializer<Any> = override fun registerByDescriptor(name: Symbol, serializerCreator: () -> AMQPSerializer<Any>): AMQPSerializer<Any> =
serializersByDescriptor.computeIfAbsent(name) { _ -> serializerCreator() } serializersByDescriptor.computeIfAbsent(name) { _ -> serializerCreator() }
companion object { companion object {
private val logger = contextLogger() private val logger = contextLogger()
fun isPrimitive(type: Type): Boolean = primitiveTypeName(type) != null
fun primitiveTypeName(type: Type): String? {
val clazz = type as? Class<*> ?: return null
return primitiveTypeNames[Primitives.unwrap(clazz)]
} }
fun primitiveType(type: String): Class<*>? {
return namesOfPrimitiveTypes[type]
}
private val primitiveTypeNames: Map<Class<*>, String> = mapOf(
Character::class.java to "char",
Char::class.java to "char",
Boolean::class.java to "boolean",
Byte::class.java to "byte",
UnsignedByte::class.java to "ubyte",
Short::class.java to "short",
UnsignedShort::class.java to "ushort",
Int::class.java to "int",
UnsignedInteger::class.java to "uint",
Long::class.java to "long",
UnsignedLong::class.java to "ulong",
Float::class.java to "float",
Double::class.java to "double",
Decimal32::class.java to "decimal32",
Decimal64::class.java to "decimal62",
Decimal128::class.java to "decimal128",
Date::class.java to "timestamp",
UUID::class.java to "uuid",
ByteArray::class.java to "binary",
String::class.java to "string",
Symbol::class.java to "symbol")
private val namesOfPrimitiveTypes: Map<String, Class<*>> = primitiveTypeNames.map { it.value to it.key }.toMap()
fun nameForType(type: Type): String = when (type) {
is Class<*> -> {
primitiveTypeName(type) ?: if (type.isArray) {
"${nameForType(type.componentType)}${if (type.componentType.isPrimitive) "[p]" else "[]"}"
} else type.name
}
is ParameterizedType -> {
"${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>"
}
is GenericArrayType -> "${nameForType(type.genericComponentType)}[]"
is WildcardType -> "?"
is TypeVariable<*> -> "?"
else -> throw AMQPNotSerializableException(type, "Unable to render type $type to a string.")
}
}
object AnyType : WildcardType {
override fun getUpperBounds(): Array<Type> = arrayOf(Object::class.java)
override fun getLowerBounds(): Array<Type> = emptyArray()
override fun toString(): String = "?"
}
} }

View File

@ -0,0 +1,53 @@
package net.corda.serialization.internal.amqp
import net.corda.core.DeleteForDJVM
import net.corda.core.KeepForDJVM
import net.corda.core.serialization.ClassWhitelist
import net.corda.serialization.internal.carpenter.ClassCarpenter
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
@KeepForDJVM
object SerializerFactoryBuilder {
@JvmStatic
@JvmOverloads
fun build(
whitelist: ClassWhitelist,
classCarpenter: ClassCarpenter,
evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider,
fingerPrinterProvider: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter,
onlyCustomSerializers: Boolean = false): SerializerFactory {
return makeFactory(
whitelist,
classCarpenter,
evolutionSerializerProvider,
fingerPrinterProvider,
onlyCustomSerializers)
}
@JvmStatic
@JvmOverloads
@DeleteForDJVM
fun build(
whitelist: ClassWhitelist,
carpenterClassLoader: ClassLoader,
lenientCarpenterEnabled: Boolean = false,
evolutionSerializerProvider: EvolutionSerializerProvider = DefaultEvolutionSerializerProvider,
fingerPrinterProvider: (SerializerFactory) -> FingerPrinter = ::SerializerFingerPrinter,
onlyCustomSerializers: Boolean = false): SerializerFactory {
return makeFactory(
whitelist,
ClassCarpenterImpl(whitelist, carpenterClassLoader, lenientCarpenterEnabled),
evolutionSerializerProvider,
fingerPrinterProvider,
onlyCustomSerializers)
}
private fun makeFactory(whitelist: ClassWhitelist,
classCarpenter: ClassCarpenter,
evolutionSerializerProvider: EvolutionSerializerProvider,
fingerPrinterProvider: (SerializerFactory) -> FingerPrinter,
onlyCustomSerializers: Boolean) =
DefaultSerializerFactory(whitelist, classCarpenter, evolutionSerializerProvider, fingerPrinterProvider,
onlyCustomSerializers)
}

View File

@ -0,0 +1,11 @@
package net.corda.serialization.internal.model
import java.util.concurrent.ConcurrentHashMap
/**
* We can't have [ConcurrentHashMap]s in the DJVM, so it must supply its own version of this object which returns
* plain old [MutableMap]s instead.
*/
object DefaultCacheProvider {
fun <K, V> createCache(): MutableMap<K, V> = ConcurrentHashMap()
}

View File

@ -147,10 +147,7 @@ public class JavaPrivatePropertyTests {
// //
// Now ensure we actually got a private property serializer // Now ensure we actually got a private property serializer
// //
Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor"); Map<Object, AMQPSerializer<Object>> serializersByDescriptor = factory.getSerializersByDescriptor();
f.setAccessible(true);
Map<?, AMQPSerializer<?>> serializersByDescriptor = uncheckedCast(f.get(factory));
assertEquals(1, serializersByDescriptor.size()); assertEquals(1, serializersByDescriptor.size());
ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]); ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]);
@ -175,9 +172,7 @@ public class JavaPrivatePropertyTests {
// //
// Now ensure we actually got a private property serializer // Now ensure we actually got a private property serializer
// //
Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor"); Map<Object, AMQPSerializer<Object>> serializersByDescriptor = factory.getSerializersByDescriptor();
f.setAccessible(true);
Map<?, AMQPSerializer<?>> serializersByDescriptor = uncheckedCast(f.get(factory));
assertEquals(1, serializersByDescriptor.size()); assertEquals(1, serializersByDescriptor.size());
ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]); ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]);

View File

@ -7,7 +7,7 @@ import net.corda.node.serialization.kryo.kryoMagic
import net.corda.node.services.statemachine.DataSessionMessage import net.corda.node.services.statemachine.DataSessionMessage
import net.corda.serialization.internal.amqp.DeserializationInput import net.corda.serialization.internal.amqp.DeserializationInput
import net.corda.serialization.internal.amqp.Envelope import net.corda.serialization.internal.amqp.Envelope
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactoryBuilder
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.internal.amqpSpecific import net.corda.testing.internal.amqpSpecific
import net.corda.testing.internal.kryoSpecific import net.corda.testing.internal.kryoSpecific
@ -28,7 +28,7 @@ class ListsSerializationTest {
fun <T : Any> verifyEnvelope(serBytes: SerializedBytes<T>, envVerBody: (Envelope) -> Unit) = fun <T : Any> verifyEnvelope(serBytes: SerializedBytes<T>, envVerBody: (Envelope) -> Unit) =
amqpSpecific("AMQP specific envelope verification") { amqpSpecific("AMQP specific envelope verification") {
val context = SerializationFactory.defaultFactory.defaultContext val context = SerializationFactory.defaultFactory.defaultContext
val envelope = DeserializationInput(SerializerFactory(context.whitelist, context.deserializationClassLoader)).getEnvelope(serBytes, context) val envelope = DeserializationInput(SerializerFactoryBuilder.build(context.whitelist, context.deserializationClassLoader)).getEnvelope(serBytes, context)
envVerBody(envelope) envVerBody(envelope)
} }
} }

View File

@ -4,6 +4,7 @@ import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.SerializationCustomSerializer import net.corda.core.serialization.SerializationCustomSerializer
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.testutils.* import net.corda.serialization.internal.amqp.testutils.*
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions
import org.junit.Test import org.junit.Test
import java.io.NotSerializableException import java.io.NotSerializableException
@ -12,16 +13,16 @@ import kotlin.test.assertEquals
class CorDappSerializerTests { class CorDappSerializerTests {
data class NeedsProxy(val a: String) data class NeedsProxy(val a: String)
private fun proxyFactory( private fun proxyFactory(serializers: List<SerializationCustomSerializer<*, *>>): SerializerFactory {
serializers: List<SerializationCustomSerializer<*, *>> val factory = SerializerFactoryBuilder.build(AllWhitelist,
) = SerializerFactory( ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()),
AllWhitelist, DefaultEvolutionSerializerProvider)
ClassLoader.getSystemClassLoader(),
onlyCustomSerializers = true
).apply {
serializers.forEach { serializers.forEach {
registerExternal(CorDappCustomSerializer(it, this)) factory.registerExternal(CorDappCustomSerializer(it, factory))
} }
return factory
} }
class NeedsProxyProxySerializer : SerializationCustomSerializer<NeedsProxy, NeedsProxyProxySerializer.Proxy> { class NeedsProxyProxySerializer : SerializationCustomSerializer<NeedsProxy, NeedsProxyProxySerializer.Proxy> {
@ -101,7 +102,10 @@ class CorDappSerializerTests {
override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses
} }
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) val whitelist = WL()
val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory)) factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory))
val tv1 = 100 val tv1 = 100
@ -123,7 +127,10 @@ class CorDappSerializerTests {
override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses
} }
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) val whitelist = WL()
val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory)) factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory))
val tv1 = 100 val tv1 = 100
@ -148,7 +155,10 @@ class CorDappSerializerTests {
override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses override fun hasListed(type: Class<*>): Boolean = type.name in allowedClasses
} }
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) val whitelist = WL()
val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory)) factory.registerExternal(CorDappCustomSerializer(NeedsProxyProxySerializer(), factory))
val tv1 = 100 val tv1 = 100

View File

@ -94,7 +94,9 @@ class DeserializeNeedingCarpentryTests : AmqpCarpenterBase(AllWhitelist) {
// 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 lfactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val lfactory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val deserialisedC = DeserializationInput(lfactory).deserialize( val deserialisedC = DeserializationInput(lfactory).deserialize(
TestSerializationOutput(VERBOSE, lfactory).serialize(concreteC)) TestSerializationOutput(VERBOSE, lfactory).serialize(concreteC))

View File

@ -9,6 +9,7 @@ import net.corda.serialization.internal.amqp.testutils.deserializeAndReturnEnvel
import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema
import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution
import net.corda.serialization.internal.amqp.testutils.testName import net.corda.serialization.internal.amqp.testutils.testName
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions
import org.junit.Test import org.junit.Test
import java.io.NotSerializableException import java.io.NotSerializableException
@ -205,7 +206,10 @@ class EnumTests {
} }
} }
val factory = SerializerFactory(WL(classTestName("C")), ClassLoader.getSystemClassLoader()) val whitelist = WL(classTestName("C"))
val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
Assertions.assertThatThrownBy { Assertions.assertThatThrownBy {
TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE)) TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE))
@ -223,7 +227,10 @@ class EnumTests {
} }
} }
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) val whitelist = WL()
val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
// if it all works, this won't explode // if it all works, this won't explode
TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE)) TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE))
@ -237,7 +244,10 @@ class EnumTests {
override fun hasListed(type: Class<*>) = false override fun hasListed(type: Class<*>) = false
} }
val factory = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) val whitelist = WL()
val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
// if it all works, this won't explode // if it all works, this won't explode
TestSerializationOutput(VERBOSE, factory).serialize(C(AnnotatedBras.UNDERWIRE)) TestSerializationOutput(VERBOSE, factory).serialize(C(AnnotatedBras.UNDERWIRE))
@ -252,14 +262,19 @@ class EnumTests {
} }
// first serialise the class using a context in which Bras are whitelisted // first serialise the class using a context in which Bras are whitelisted
val factory = SerializerFactory(WL(listOf(classTestName("C"), val whitelist = WL(listOf(classTestName("C"),
"net.corda.serialization.internal.amqp.EnumTests\$Bras")), "net.corda.serialization.internal.amqp.EnumTests\$Bras"))
ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
val bytes = TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE)) val bytes = TestSerializationOutput(VERBOSE, factory).serialize(C(Bras.UNDERWIRE))
// then take that serialised object and attempt to deserialize it in a context that // then take that serialised object and attempt to deserialize it in a context that
// disallows the Bras enum // disallows the Bras enum
val factory2 = SerializerFactory(WL(listOf(classTestName("C"))), ClassLoader.getSystemClassLoader()) val whitelist1 = WL(listOf(classTestName("C")))
val factory2 = SerializerFactoryBuilder.build(whitelist1,
ClassCarpenterImpl(whitelist1, ClassLoader.getSystemClassLoader())
)
Assertions.assertThatThrownBy { Assertions.assertThatThrownBy {
DeserializationInput(factory2).deserialize(bytes) DeserializationInput(factory2).deserialize(bytes)
}.isInstanceOf(NotSerializableException::class.java) }.isInstanceOf(NotSerializableException::class.java)

View File

@ -6,6 +6,7 @@ import kotlin.test.assertEquals
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
class FingerPrinterTesting : FingerPrinter { class FingerPrinterTesting : FingerPrinter {
private var index = 0 private var index = 0
@ -39,11 +40,9 @@ class FingerPrinterTestingTests {
fun worksAsReplacement() { fun worksAsReplacement() {
data class C(val a: Int, val b: Long) data class C(val a: Int, val b: Long)
val factory = SerializerFactory( val factory = SerializerFactoryBuilder.build(AllWhitelist,
AllWhitelist, ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()),
ClassLoader.getSystemClassLoader(), fingerPrinterProvider = { _ -> FingerPrinterTesting() })
evolutionSerializerProvider = FailIfEvolutionAttempted,
fingerPrinterConstructor = { _ -> FingerPrinterTesting() })
val blob = TestSerializationOutput(VERBOSE, factory).serializeAndReturnSchema(C(1, 2L)) val blob = TestSerializationOutput(VERBOSE, factory).serializeAndReturnSchema(C(1, 2L))

View File

@ -9,6 +9,7 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import net.corda.serialization.internal.amqp.testutils.* import net.corda.serialization.internal.amqp.testutils.*
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import net.corda.testing.common.internal.ProjectStructure.projectRootDir import net.corda.testing.common.internal.ProjectStructure.projectRootDir
import net.corda.testing.core.TestIdentity import net.corda.testing.core.TestIdentity
import org.junit.Test import org.junit.Test
@ -120,8 +121,12 @@ class GenericsTests {
data class G(val a: Int) data class G(val a: Int)
data class Wrapper<T : Any>(val a: Int, val b: SerializedBytes<T>) data class Wrapper<T : Any>(val a: Int, val b: SerializedBytes<T>)
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val ser = SerializationOutput(factory) val ser = SerializationOutput(factory)
val gBytes = ser.serialize(G(1)) val gBytes = ser.serialize(G(1))
@ -145,8 +150,12 @@ class GenericsTests {
data class Container<T>(val b: T) data class Container<T>(val b: T)
data class Wrapper<T : Any>(val c: Container<T>) data class Wrapper<T : Any>(val c: Container<T>)
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
val factories = listOf(factory, SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val factories = listOf(factory, SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
))
val ser = SerializationOutput(factory) val ser = SerializationOutput(factory)
ser.serialize(Wrapper(Container(InnerA(1)))).apply { ser.serialize(Wrapper(Container(InnerA(1)))).apply {
@ -178,8 +187,12 @@ class GenericsTests {
data class Wrapper<T : Any>(val c: Container<T>) data class Wrapper<T : Any>(val c: Container<T>)
val factorys = listOf( val factorys = listOf(
SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()), SerializerFactoryBuilder.build(AllWhitelist,
SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
),
SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
))
val ser = SerializationOutput(factorys[0]) val ser = SerializationOutput(factorys[0])
@ -200,7 +213,9 @@ class GenericsTests {
private fun forceWildcardSerialize( private fun forceWildcardSerialize(
a: ForceWildcard<*>, a: ForceWildcard<*>,
factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())): SerializedBytes<*> { factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)): SerializedBytes<*> {
val bytes = SerializationOutput(factory).serializeAndReturnSchema(a) val bytes = SerializationOutput(factory).serializeAndReturnSchema(a)
factory.serializersByDescriptor.printKeyToType() factory.serializersByDescriptor.printKeyToType()
bytes.printSchema() bytes.printSchema()
@ -210,21 +225,27 @@ class GenericsTests {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun forceWildcardDeserializeString( private fun forceWildcardDeserializeString(
bytes: SerializedBytes<*>, bytes: SerializedBytes<*>,
factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) { factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)) {
DeserializationInput(factory).deserialize(bytes as SerializedBytes<ForceWildcard<String>>) DeserializationInput(factory).deserialize(bytes as SerializedBytes<ForceWildcard<String>>)
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun forceWildcardDeserializeDouble( private fun forceWildcardDeserializeDouble(
bytes: SerializedBytes<*>, bytes: SerializedBytes<*>,
factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) { factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)) {
DeserializationInput(factory).deserialize(bytes as SerializedBytes<ForceWildcard<Double>>) DeserializationInput(factory).deserialize(bytes as SerializedBytes<ForceWildcard<Double>>)
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun forceWildcardDeserialize( private fun forceWildcardDeserialize(
bytes: SerializedBytes<*>, bytes: SerializedBytes<*>,
factory: SerializerFactory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) { factory: SerializerFactory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)) {
DeserializationInput(factory).deserialize(bytes as SerializedBytes<ForceWildcard<*>>) DeserializationInput(factory).deserialize(bytes as SerializedBytes<ForceWildcard<*>>)
} }
@ -236,7 +257,9 @@ class GenericsTests {
@Test @Test
fun forceWildcardSharedFactory() { fun forceWildcardSharedFactory() {
val f = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val f = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
forceWildcardDeserializeString(forceWildcardSerialize(ForceWildcard("hello"), f), f) forceWildcardDeserializeString(forceWildcardSerialize(ForceWildcard("hello"), f), f)
forceWildcardDeserializeDouble(forceWildcardSerialize(ForceWildcard(3.0), f), f) forceWildcardDeserializeDouble(forceWildcardSerialize(ForceWildcard(3.0), f), f)
} }
@ -250,7 +273,9 @@ class GenericsTests {
@Test @Test
fun forceWildcardDeserializeSharedFactory() { fun forceWildcardDeserializeSharedFactory() {
val f = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val f = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard("hello"), f), f) forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard("hello"), f), f)
forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard(10), f), f) forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard(10), f), f)
forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard(20.0), f), f) forceWildcardDeserialize(forceWildcardSerialize(ForceWildcard(20.0), f), f)
@ -288,7 +313,9 @@ class GenericsTests {
// possibly altering how we serialise things // possibly altering how we serialise things
val altClassLoader = cl() val altClassLoader = cl()
val factory2 = SerializerFactory(AllWhitelist, altClassLoader) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, altClassLoader)
)
factory2.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) factory2.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
val ser2 = TestSerializationOutput(VERBOSE, factory2).serializeAndReturnSchema(state) val ser2 = TestSerializationOutput(VERBOSE, factory2).serializeAndReturnSchema(state)
@ -297,7 +324,9 @@ class GenericsTests {
factory3.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) factory3.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
DeserializationInput(factory3).deserializeAndReturnEnvelope(ser1.obj) DeserializationInput(factory3).deserializeAndReturnEnvelope(ser1.obj)
val factory4 = SerializerFactory(AllWhitelist, cl()) val factory4 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, cl())
)
factory4.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) factory4.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
DeserializationInput(factory4).deserializeAndReturnEnvelope(ser2.obj) DeserializationInput(factory4).deserializeAndReturnEnvelope(ser2.obj)
} }

View File

@ -5,6 +5,7 @@ import net.corda.serialization.internal.amqp.custom.OptionalSerializer
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
import net.corda.serialization.internal.amqp.testutils.deserialize import net.corda.serialization.internal.amqp.testutils.deserialize
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import org.hamcrest.Matchers.`is` import org.hamcrest.Matchers.`is`
import org.hamcrest.Matchers.equalTo import org.hamcrest.Matchers.equalTo
import org.junit.Assert import org.junit.Assert
@ -17,7 +18,9 @@ class OptionalSerializationTests {
fun setupEnclosedSerializationTest() { fun setupEnclosedSerializationTest() {
@Test @Test
fun `java optionals should serialize`() { fun `java optionals should serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(OptionalSerializer(factory)) factory.register(OptionalSerializer(factory))
val obj = Optional.ofNullable("YES") val obj = Optional.ofNullable("YES")
val bytes = TestSerializationOutput(true, factory).serialize(obj) val bytes = TestSerializationOutput(true, factory).serialize(obj)

View File

@ -17,15 +17,6 @@ import java.util.*
class PrivatePropertyTests { class PrivatePropertyTests {
private val factory = testDefaultFactoryNoEvolution() private val factory = testDefaultFactoryNoEvolution()
companion object {
val fields : Map<String, java.lang.reflect.Field> = mapOf (
"serializersByDesc" to SerializerFactory::class.java.getDeclaredField("serializersByDescriptor")).apply {
this.values.forEach {
it.isAccessible = true
}
}
}
@Test @Test
fun testWithOnePrivateProperty() { fun testWithOnePrivateProperty() {
data class C(private val b: String) data class C(private val b: String)
@ -134,8 +125,7 @@ class PrivatePropertyTests {
val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1) val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1)
assertEquals(1, schemaAndBlob.schema.types.size) assertEquals(1, schemaAndBlob.schema.types.size)
@Suppress("UNCHECKED_CAST") val serializersByDescriptor = factory.serializersByDescriptor
val serializersByDescriptor = fields["serializersByDesc"]?.get(factory) as ConcurrentHashMap<Any, AMQPSerializer<Any>>
val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name
serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply {
@ -163,8 +153,7 @@ class PrivatePropertyTests {
val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1) val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1)
assertEquals(1, schemaAndBlob.schema.types.size) assertEquals(1, schemaAndBlob.schema.types.size)
@Suppress("UNCHECKED_CAST") val serializersByDescriptor = factory.serializersByDescriptor
val serializersByDescriptor = fields["serializersByDesc"]?.get(factory) as ConcurrentHashMap<Any, AMQPSerializer<Any>>
val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name
serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply {
@ -192,7 +181,7 @@ class PrivatePropertyTests {
val output = SerializationOutput(factory).serializeAndReturnSchema(c1) val output = SerializationOutput(factory).serializeAndReturnSchema(c1)
println (output.schema) println (output.schema)
val serializersByDescriptor = fields["serializersByDesc"]!!.get(factory) as ConcurrentHashMap<Any, AMQPSerializer<Any>> val serializersByDescriptor = factory.serializersByDescriptor
// Inner and Outer // Inner and Outer
assertEquals(2, serializersByDescriptor.size) assertEquals(2, serializersByDescriptor.size)
@ -212,7 +201,7 @@ class PrivatePropertyTests {
val output = SerializationOutput(factory).serializeAndReturnSchema(C("this is nice")) val output = SerializationOutput(factory).serializeAndReturnSchema(C("this is nice"))
val serializersByDescriptor = fields["serializersByDesc"]!!.get(factory) as ConcurrentHashMap<Any, AMQPSerializer<Any>> val serializersByDescriptor = factory.serializersByDescriptor
val schemaDescriptor = output.schema.types.first().descriptor.name val schemaDescriptor = output.schema.types.first().descriptor.name
serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply {

View File

@ -23,6 +23,7 @@ import net.corda.nodeapi.internal.crypto.ContentSignerBuilder
import net.corda.serialization.internal.* import net.corda.serialization.internal.*
import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive
import net.corda.serialization.internal.amqp.testutils.* import net.corda.serialization.internal.amqp.testutils.*
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.BOB_NAME import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
@ -207,9 +208,8 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
} }
private fun defaultFactory(): SerializerFactory { private fun defaultFactory(): SerializerFactory {
return SerializerFactory( return SerializerFactoryBuilder.build(AllWhitelist,
AllWhitelist, ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()),
ClassLoader.getSystemClassLoader(),
evolutionSerializerProvider = FailIfEvolutionAttempted evolutionSerializerProvider = FailIfEvolutionAttempted
) )
} }
@ -368,13 +368,17 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@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, ClassLoader.getSystemClassLoader())) serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist,
ClassCarpenterImpl(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, ClassLoader.getSystemClassLoader())) serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist,
ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader())
))
} }
@Test(expected = NotSerializableException::class) @Test(expected = NotSerializableException::class)
@ -471,7 +475,9 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `class constructor is invoked on deserialisation`() { fun `class constructor is invoked on deserialisation`() {
compression == null || return // Manipulation of serialized bytes is invalid if they're compressed. compression == null || return // Manipulation of serialized bytes is invalid if they're compressed.
val ser = SerializationOutput(SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) val ser = SerializationOutput(SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
))
val des = DeserializationInput(ser.serializerFactory) val des = DeserializationInput(ser.serializerFactory)
val serialisedOne = ser.serialize(NonZeroByte(1), compression).bytes val serialisedOne = ser.serialize(NonZeroByte(1), compression).bytes
val serialisedTwo = ser.serialize(NonZeroByte(2), compression).bytes val serialisedTwo = ser.serialize(NonZeroByte(2), compression).bytes
@ -496,9 +502,13 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test custom serializers on public key`() { fun `test custom serializers on public key`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) factory.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer) factory2.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
val obj = MEGA_CORP_PUBKEY val obj = MEGA_CORP_PUBKEY
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -507,21 +517,29 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test annotation is inherited`() { fun `test annotation is inherited`() {
val obj = InheritAnnotation("blah") val obj = InheritAnnotation("blah")
serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())) serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist,
ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader())
))
} }
@Test @Test
fun `generics from java are supported`() { fun `generics from java are supported`() {
val obj = DummyOptional<String>("YES") val obj = DummyOptional<String>("YES")
serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())) serdes(obj, SerializerFactoryBuilder.build(EmptyWhitelist,
ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader())
))
} }
@Test @Test
fun `test throwables serialize`() { fun `test throwables serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2))
val t = IllegalAccessException("message").fillInStackTrace() val t = IllegalAccessException("message").fillInStackTrace()
@ -537,10 +555,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test complex throwables serialize`() { fun `test complex throwables serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2))
try { try {
@ -567,10 +589,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test suppressed throwables serialize`() { fun `test suppressed throwables serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2))
try { try {
@ -589,10 +615,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test flow corda exception subclasses serialize`() { fun `test flow corda exception subclasses serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2))
val obj = FlowException("message").fillInStackTrace() val obj = FlowException("message").fillInStackTrace()
@ -601,10 +631,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test RPC corda exception subclasses serialize`() { fun `test RPC corda exception subclasses serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ThrowableSerializer(factory2))
val obj = RPCException("message").fillInStackTrace() val obj = RPCException("message").fillInStackTrace()
@ -666,10 +700,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
SerializerFactory::class.java) SerializerFactory::class.java)
func.isAccessible = true func.isAccessible = true
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
func.invoke(scheme, testSerializationContext, factory) func.invoke(scheme, testSerializationContext, factory)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
func.invoke(scheme, testSerializationContext, factory2) func.invoke(scheme, testSerializationContext, factory2)
val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false) val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false)
@ -680,10 +718,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test currencies serialize`() { fun `test currencies serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.CurrencySerializer) factory.register(net.corda.serialization.internal.amqp.custom.CurrencySerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.CurrencySerializer) factory2.register(net.corda.serialization.internal.amqp.custom.CurrencySerializer)
val obj = Currency.getInstance("USD") val obj = Currency.getInstance("USD")
@ -692,10 +734,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test big decimals serialize`() { fun `test big decimals serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
val obj = BigDecimal("100000000000000000000000000000.00") val obj = BigDecimal("100000000000000000000000000000.00")
@ -704,10 +750,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test instants serialize`() { fun `test instants serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(factory2))
val obj = Instant.now() val obj = Instant.now()
@ -716,10 +766,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test durations serialize`() { fun `test durations serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(factory2))
val obj = Duration.of(1000000L, ChronoUnit.MILLIS) val obj = Duration.of(1000000L, ChronoUnit.MILLIS)
@ -728,10 +782,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test local date serialize`() { fun `test local date serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.LocalDateSerializer(factory2))
val obj = LocalDate.now() val obj = LocalDate.now()
@ -740,10 +798,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test local time serialize`() { fun `test local time serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.LocalTimeSerializer(factory2))
val obj = LocalTime.now() val obj = LocalTime.now()
@ -752,10 +814,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test local date time serialize`() { fun `test local date time serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer(factory2))
val obj = LocalDateTime.now() val obj = LocalDateTime.now()
@ -764,10 +830,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test zoned date time serialize`() { fun `test zoned date time serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer(factory2))
val obj = ZonedDateTime.now() val obj = ZonedDateTime.now()
@ -776,10 +846,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test offset time serialize`() { fun `test offset time serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(factory2))
val obj = OffsetTime.now() val obj = OffsetTime.now()
@ -788,10 +862,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test offset date time serialize`() { fun `test offset date time serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(factory2))
val obj = OffsetDateTime.now() val obj = OffsetDateTime.now()
@ -800,10 +878,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test year serialize`() { fun `test year serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.YearSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.YearSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.YearSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.YearSerializer(factory2))
val obj = Year.now() val obj = Year.now()
@ -812,10 +894,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test year month serialize`() { fun `test year month serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(factory2))
val obj = YearMonth.now() val obj = YearMonth.now()
@ -824,10 +910,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test month day serialize`() { fun `test month day serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(factory2))
val obj = MonthDay.now() val obj = MonthDay.now()
@ -836,10 +926,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test period serialize`() { fun `test period serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.PeriodSerializer(factory2))
val obj = Period.of(99, 98, 97) val obj = Period.of(99, 98, 97)
@ -866,10 +960,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test X509 certificate serialize`() { fun `test X509 certificate serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer) factory.register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.X509CertificateSerializer)
val obj = BOB_IDENTITY.certificate val obj = BOB_IDENTITY.certificate
@ -878,10 +976,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test cert path serialize`() { fun `test cert path serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.CertPathSerializer(factory2))
val obj = BOB_IDENTITY.certPath val obj = BOB_IDENTITY.certPath
@ -905,9 +1007,13 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test StateRef serialize`() { fun `test StateRef serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val obj = StateRef(SecureHash.randomSHA256(), 0) val obj = StateRef(SecureHash.randomSHA256(), 0)
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
@ -953,8 +1059,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
val b = ByteArray(2) val b = ByteArray(2)
val obj = Bob(listOf(a, b, a)) val obj = Bob(listOf(a, b, a))
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val obj2 = serdes(obj, factory, factory2, false, false) val obj2 = serdes(obj, factory, factory2, false, false)
assertNotSame(obj2.byteArrays[0], obj2.byteArrays[2]) assertNotSame(obj2.byteArrays[0], obj2.byteArrays[2])
@ -967,8 +1077,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
val a = listOf("a", "b") val a = listOf("a", "b")
val obj = Vic(a, a) val obj = Vic(a, a)
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val objCopy = serdes(obj, factory, factory2) val objCopy = serdes(obj, factory, factory2)
assertSame(objCopy.a, objCopy.b) assertSame(objCopy.a, objCopy.b)
} }
@ -984,8 +1098,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
fun `test private constructor`() { fun `test private constructor`() {
val obj = Spike() val obj = Spike()
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
serdes(obj, factory, factory2) serdes(obj, factory, factory2)
} }
@ -993,10 +1111,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test toString custom serializer`() { fun `test toString custom serializer`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
val obj = BigDecimals(BigDecimal.TEN, BigDecimal.TEN) val obj = BigDecimals(BigDecimal.TEN, BigDecimal.TEN)
@ -1008,10 +1130,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test BigInteger custom serializer`() { fun `test BigInteger custom serializer`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer) factory.register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.BigIntegerSerializer)
val obj = BigIntegers(BigInteger.TEN, BigInteger.TEN) val obj = BigIntegers(BigInteger.TEN, BigInteger.TEN)
@ -1028,10 +1154,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test X509CRL custom serializer`() { fun `test X509CRL custom serializer`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer) factory.register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.X509CRLSerializer)
val obj = emptyCrl() val obj = emptyCrl()
@ -1042,10 +1172,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test byte arrays not reference counted`() { fun `test byte arrays not reference counted`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) factory.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.BigDecimalSerializer)
val bytes = ByteArray(1) val bytes = ByteArray(1)
@ -1056,10 +1190,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test StringBuffer serialize`() { fun `test StringBuffer serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer) factory.register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.StringBufferSerializer)
val obj = StringBuffer("Bob") val obj = StringBuffer("Bob")
@ -1069,10 +1207,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test SimpleString serialize`() { fun `test SimpleString serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer) factory.register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.SimpleStringSerializer)
val obj = SimpleString("Bob") val obj = SimpleString("Bob")
@ -1093,10 +1235,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test InputStream serialize`() { fun `test InputStream serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer) factory.register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer)
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer) factory2.register(net.corda.serialization.internal.amqp.custom.InputStreamSerializer)
val bytes = ByteArray(10) { it.toByte() } val bytes = ByteArray(10) { it.toByte() }
val obj = bytes.inputStream() val obj = bytes.inputStream()
@ -1108,10 +1254,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test EnumSet serialize`() { fun `test EnumSet serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.EnumSetSerializer(factory2))
val obj = EnumSet.of(Month.APRIL, Month.AUGUST) val obj = EnumSet.of(Month.APRIL, Month.AUGUST)
@ -1120,10 +1270,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test BitSet serialize`() { fun `test BitSet serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.BitSetSerializer(factory2))
val obj = BitSet.valueOf(kotlin.ByteArray(16) { it.toByte() }).get(0, 123) val obj = BitSet.valueOf(kotlin.ByteArray(16) { it.toByte() }).get(0, 123)
@ -1140,10 +1294,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test contract attachment serialize`() { fun `test contract attachment serialize`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory2))
val obj = ContractAttachment(GeneratedAttachment("test".toByteArray()), DummyContract.PROGRAM_ID) val obj = ContractAttachment(GeneratedAttachment("test".toByteArray()), DummyContract.PROGRAM_ID)
@ -1156,10 +1314,14 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `test contract attachment throws if missing attachment`() { fun `test contract attachment throws if missing attachment`() {
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory)) factory.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory))
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val factory2 = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
factory2.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory2)) factory2.register(net.corda.serialization.internal.amqp.custom.ContractAttachmentSerializer(factory2))
val obj = ContractAttachment(object : AbstractAttachment({ throw Exception() }) { val obj = ContractAttachment(object : AbstractAttachment({ throw Exception() }) {
@ -1351,7 +1513,9 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
@Test @Test
fun `compression reduces number of bytes significantly`() { fun `compression reduces number of bytes significantly`() {
val ser = SerializationOutput(SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())) val ser = SerializationOutput(SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
))
val obj = ByteArray(20000) val obj = ByteArray(20000)
val uncompressedSize = ser.serialize(obj).bytes.size val uncompressedSize = ser.serialize(obj).bytes.size
val compressedSize = ser.serialize(obj, CordaSerializationEncoding.SNAPPY).bytes.size val compressedSize = ser.serialize(obj, CordaSerializationEncoding.SNAPPY).bytes.size

View File

@ -102,14 +102,13 @@ class SerializationPropertyOrdering {
// Test needs to look at a bunch of private variables, change the access semantics for them // Test needs to look at a bunch of private variables, change the access semantics for them
val fields : Map<String, java.lang.reflect.Field> = mapOf ( val fields : Map<String, java.lang.reflect.Field> = mapOf (
"serializersByDesc" to SerializerFactory::class.java.getDeclaredField("serializersByDescriptor"),
"setter" to PropertyAccessorGetterSetter::class.java.getDeclaredField("setter")).apply { "setter" to PropertyAccessorGetterSetter::class.java.getDeclaredField("setter")).apply {
this.values.forEach { this.values.forEach {
it.isAccessible = true it.isAccessible = true
} }
} }
val serializersByDescriptor = fields["serializersByDesc"]!!.get(sf) as ConcurrentHashMap<Any, AMQPSerializer<Any>> val serializersByDescriptor = sf.serializersByDescriptor
val schemaDescriptor = output.schema.types.first().descriptor.name val schemaDescriptor = output.schema.types.first().descriptor.name
// make sure that each property accessor has a setter to ensure we're using getter / setter instantiation // make sure that each property accessor has a setter to ensure we're using getter / setter instantiation

View File

@ -6,6 +6,7 @@ import net.corda.serialization.internal.BuiltInExceptionsWhitelist
import net.corda.serialization.internal.CordaSerializationMagic import net.corda.serialization.internal.CordaSerializationMagic
import net.corda.serialization.internal.GlobalTransientClassWhiteList import net.corda.serialization.internal.GlobalTransientClassWhiteList
import net.corda.serialization.internal.SerializationContextImpl import net.corda.serialization.internal.SerializationContextImpl
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -22,7 +23,7 @@ val TESTING_CONTEXT = SerializationContextImpl(amqpMagic,
class TestSerializerFactory( class TestSerializerFactory(
wl: ClassWhitelist, wl: ClassWhitelist,
cl: ClassLoader cl: ClassLoader
) : SerializerFactory(wl, cl) { ) : DefaultSerializerFactory(wl, ClassCarpenterImpl(wl, cl, false), DefaultEvolutionSerializerProvider, ::SerializerFingerPrinter) {
var registerCount = 0 var registerCount = 0
override fun register(customSerializer: CustomSerializer<out Any>) { override fun register(customSerializer: CustomSerializer<out Any>) {

View File

@ -48,7 +48,9 @@ class StaticInitialisationOfSerializedObjectTest {
fun kotlinObjectWithCompanionObject() { fun kotlinObjectWithCompanionObject() {
data class D(val c: C) data class D(val c: C)
val sf = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) val sf = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
val typeMap = sf::class.java.getDeclaredField("serializersByType") val typeMap = sf::class.java.getDeclaredField("serializersByType")
typeMap.isAccessible = true typeMap.isAccessible = true
@ -87,7 +89,10 @@ class StaticInitialisationOfSerializedObjectTest {
".StaticInitialisationOfSerializedObjectTest\$deserializeTest\$D" ".StaticInitialisationOfSerializedObjectTest\$deserializeTest\$D"
} }
val sf2 = SerializerFactory(WL(), ClassLoader.getSystemClassLoader()) val whitelist = WL()
val sf2 = SerializerFactoryBuilder.build(whitelist,
ClassCarpenterImpl(whitelist, ClassLoader.getSystemClassLoader())
)
val bytes = url.readBytes() val bytes = url.readBytes()
assertThatThrownBy { assertThatThrownBy {
@ -97,8 +102,8 @@ class StaticInitialisationOfSerializedObjectTest {
// Version of a serializer factory that will allow the class carpenter living on the // Version of a serializer factory that will allow the class carpenter living on the
// factory to have a different whitelist applied to it than the factory // factory to have a different whitelist applied to it than the factory
class TestSerializerFactory(wl1: ClassWhitelist, wl2: ClassWhitelist) : private fun testSerializerFactory(wl1: ClassWhitelist, wl2: ClassWhitelist) =
SerializerFactory(wl1, ClassCarpenterImpl(wl2, ClassLoader.getSystemClassLoader())) SerializerFactoryBuilder.build(wl1, ClassCarpenterImpl(wl2, ClassLoader.getSystemClassLoader()))
// This time have the serialization factory and the carpenter use different whitelists // This time have the serialization factory and the carpenter use different whitelists
@Test @Test
@ -126,7 +131,7 @@ class StaticInitialisationOfSerializedObjectTest {
override fun hasListed(type: Class<*>) = true override fun hasListed(type: Class<*>) = true
} }
val sf2 = TestSerializerFactory(WL1(), WL2()) val sf2 = testSerializerFactory(WL1(), WL2())
val bytes = url.readBytes() val bytes = url.readBytes()
// Deserializing should throw because C is not on the whitelist NOT because // Deserializing should throw because C is not on the whitelist NOT because

View File

@ -10,6 +10,7 @@ import net.corda.core.utilities.OpaqueBytes
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.EmptyWhitelist import net.corda.serialization.internal.EmptyWhitelist
import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.*
import net.corda.serialization.internal.carpenter.ClassCarpenterImpl
import net.corda.testing.common.internal.ProjectStructure import net.corda.testing.common.internal.ProjectStructure
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import org.junit.Test import org.junit.Test
@ -17,16 +18,20 @@ import java.io.File.separatorChar
import java.io.NotSerializableException import java.io.NotSerializableException
import java.nio.file.StandardCopyOption.REPLACE_EXISTING import java.nio.file.StandardCopyOption.REPLACE_EXISTING
fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) fun testDefaultFactory() = SerializerFactoryBuilder.build(AllWhitelist,
ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader())
)
fun testDefaultFactoryNoEvolution(): SerializerFactory { fun testDefaultFactoryNoEvolution(): SerializerFactory {
return SerializerFactory( return SerializerFactoryBuilder.build(
AllWhitelist, AllWhitelist,
ClassLoader.getSystemClassLoader(), ClassCarpenterImpl(AllWhitelist, ClassLoader.getSystemClassLoader()),
evolutionSerializerProvider = FailIfEvolutionAttempted) FailIfEvolutionAttempted)
} }
fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()) fun testDefaultFactoryWithWhitelist() = SerializerFactoryBuilder.build(EmptyWhitelist,
ClassCarpenterImpl(EmptyWhitelist, ClassLoader.getSystemClassLoader())
)
class TestSerializationOutput( class TestSerializationOutput(
private val verbose: Boolean, private val verbose: Boolean,

View File

@ -5,7 +5,6 @@ import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.*
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
import net.corda.serialization.internal.amqp.testutils.deserialize import net.corda.serialization.internal.amqp.testutils.deserialize
import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions
import org.junit.Test import org.junit.Test
@ -33,8 +32,8 @@ interface TestInterface {
// Create a custom serialization factory where we need to be able to both specify a carpenter // Create a custom serialization factory where we need to be able to both specify a carpenter
// but also have the class loader used by the carpenter be substantially different from the // but also have the class loader used by the carpenter be substantially different from the
// one used by the factory so as to ensure we can control their behaviour independently. // one used by the factory so as to ensure we can control their behaviour independently.
class TestFactory(classCarpenter: ClassCarpenter) private fun testFactory(classCarpenter: ClassCarpenter)
: SerializerFactory(classCarpenter.whitelist, classCarpenter) = SerializerFactoryBuilder.build(classCarpenter.whitelist, classCarpenter)
class CarpenterExceptionTests { class CarpenterExceptionTests {
companion object { companion object {
@ -90,7 +89,7 @@ class CarpenterExceptionTests {
// we set the class loader of the ClassCarpenter to reject one of them, resulting in a CarpentryError // we set the class loader of the ClassCarpenter to reject one of them, resulting in a CarpentryError
// which we then want the code to wrap in a NotSerializeableException // which we then want the code to wrap in a NotSerializeableException
val cc = ClassCarpenterImpl(AllWhitelist, TestClassLoader(listOf(C2::class.jvmName))) val cc = ClassCarpenterImpl(AllWhitelist, TestClassLoader(listOf(C2::class.jvmName)))
val factory = TestFactory(cc) val factory = testFactory(cc)
Assertions.assertThatThrownBy { Assertions.assertThatThrownBy {
DeserializationInput(factory).deserialize(ser) DeserializationInput(factory).deserialize(ser)

View File

@ -41,12 +41,12 @@ fun Schema.mangleNames(names: List<String>): Schema {
* Custom implementation of a [SerializerFactory] where we need to give it a class carpenter * Custom implementation of a [SerializerFactory] where we need to give it a class carpenter
* rather than have it create its own * rather than have it create its own
*/ */
class SerializerFactoryExternalCarpenter(classCarpenter: ClassCarpenter) private fun serializerFactoryExternalCarpenter(classCarpenter: ClassCarpenter)
: SerializerFactory(classCarpenter.whitelist, classCarpenter) = SerializerFactoryBuilder.build(classCarpenter.whitelist, classCarpenter)
open class AmqpCarpenterBase(whitelist: ClassWhitelist) { open class AmqpCarpenterBase(whitelist: ClassWhitelist) {
var cc = ClassCarpenterImpl(whitelist = whitelist) var cc = ClassCarpenterImpl(whitelist = whitelist)
var factory = SerializerFactoryExternalCarpenter(cc) var factory = serializerFactoryExternalCarpenter(cc)
fun <T: Any> serialise(obj: T): SerializedBytes<T> = SerializationOutput(factory).serialize(obj) fun <T: Any> serialise(obj: T): SerializedBytes<T> = SerializationOutput(factory).serialize(obj)
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@ -2,17 +2,15 @@ package net.corda.cliutils
import net.corda.core.internal.rootMessage import net.corda.core.internal.rootMessage
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.loggerFor
import org.fusesource.jansi.AnsiConsole import org.fusesource.jansi.AnsiConsole
import org.slf4j.event.Level import org.slf4j.event.Level
import picocli.CommandLine import picocli.CommandLine
import picocli.CommandLine.* import picocli.CommandLine.*
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.system.exitProcess
import java.util.* import java.util.*
import java.util.concurrent.Callable import java.util.concurrent.Callable
import kotlin.system.exitProcess
/** /**
* When we have errors in command line flags that are not handled by picocli (e.g. non existing files), an error is thrown * When we have errors in command line flags that are not handled by picocli (e.g. non existing files), an error is thrown
@ -64,18 +62,6 @@ fun CordaCliWrapper.start(args: Array<String>) {
// This line makes sure ANSI escapes work on Windows, where they aren't supported out of the box. // This line makes sure ANSI escapes work on Windows, where they aren't supported out of the box.
AnsiConsole.systemInstall() AnsiConsole.systemInstall()
val cmd = CommandLine(this)
// Make sure any provided paths are absolute. Relative paths have caused issues and are less clear in logs.
cmd.registerConverter(Path::class.java) { Paths.get(it).toAbsolutePath().normalize() }
cmd.commandSpec.name(alias)
cmd.commandSpec.usageMessage().description(description)
this.subCommands().forEach {
val subCommand = CommandLine(it)
it.args = args
subCommand.commandSpec.usageMessage().description(it.description)
cmd.commandSpec.addSubcommand(it.alias, subCommand)
}
try { try {
val defaultAnsiMode = if (CordaSystemUtils.isOsWindows()) { val defaultAnsiMode = if (CordaSystemUtils.isOsWindows()) {
Help.Ansi.ON Help.Ansi.ON
@ -97,7 +83,7 @@ fun CordaCliWrapper.start(args: Array<String>) {
exitProcess(ExitCodes.SUCCESS) exitProcess(ExitCodes.SUCCESS)
} catch (e: ExecutionException) { } catch (e: ExecutionException) {
val throwable = e.cause ?: e val throwable = e.cause ?: e
if (this.verbose || this.subCommands().any { it.verbose} ) { if (this.verbose || this.subCommands().any { it.verbose }) {
throwable.printStackTrace() throwable.printStackTrace()
} else { } else {
System.err.println("*ERROR*: ${throwable.rootMessage ?: "Use --verbose for more details"}") System.err.println("*ERROR*: ${throwable.rootMessage ?: "Use --verbose for more details"}")
@ -171,6 +157,21 @@ abstract class CordaCliWrapper(alias: String, description: String) : CliWrapperB
protected open fun additionalSubCommands(): Set<CliWrapperBase> = emptySet() protected open fun additionalSubCommands(): Set<CliWrapperBase> = emptySet()
val cmd by lazy {
CommandLine(this).apply {
// Make sure any provided paths are absolute. Relative paths have caused issues and are less clear in logs.
registerConverter(Path::class.java) { Paths.get(it).toAbsolutePath().normalize() }
commandSpec.name(alias)
commandSpec.usageMessage().description(description)
subCommands().forEach {
val subCommand = CommandLine(it)
it.args = args
subCommand.commandSpec.usageMessage().description(it.description)
commandSpec.addSubcommand(it.alias, subCommand)
}
}
}
fun subCommands(): Set<CliWrapperBase> { fun subCommands(): Set<CliWrapperBase> {
return additionalSubCommands() + installShellExtensionsParser return additionalSubCommands() + installShellExtensionsParser
} }
@ -181,6 +182,8 @@ abstract class CordaCliWrapper(alias: String, description: String) : CliWrapperB
installShellExtensionsParser.updateShellExtensions() installShellExtensionsParser.updateShellExtensions()
return runProgram() return runProgram()
} }
fun printHelp() = cmd.usage(System.out)
} }
/** /**

View File

@ -29,7 +29,7 @@ class InteractiveShellTest {
@Suppress("UNUSED") @Suppress("UNUSED")
class FlowA(val a: String) : FlowLogic<String>() { class FlowA(val a: String) : FlowLogic<String>() {
constructor(b: Int) : this(b.toString()) constructor(b: Int?) : this(b.toString())
constructor(b: Int?, c: String) : this(b.toString() + c) constructor(b: Int?, c: String) : this(b.toString() + c)
constructor(amount: Amount<Currency>) : this(amount.toString()) constructor(amount: Amount<Currency>) : this(amount.toString())
constructor(pair: Pair<Amount<Currency>, SecureHash.SHA256>) : this(pair.toString()) constructor(pair: Pair<Amount<Currency>, SecureHash.SHA256>) : this(pair.toString())
@ -115,7 +115,7 @@ class InteractiveShellTest {
"[b: String[]]: missing parameter b", "[b: String[]]: missing parameter b",
"[b: Integer, c: String]: missing parameter b", "[b: Integer, c: String]: missing parameter b",
"[a: String]: missing parameter a", "[a: String]: missing parameter a",
"[b: int]: missing parameter b" "[b: Integer]: missing parameter b"
) )
val errors = e.errors.toHashSet() val errors = e.errors.toHashSet()
errors.removeAll(correct) errors.removeAll(correct)