mirror of
https://github.com/corda/corda.git
synced 2024-12-24 07:06:44 +00:00
Merge remote-tracking branch 'remote-djvm/chrisr3-djvm-serialization' into chrisr3-djvm-integration
This commit is contained in:
commit
833ea3d40b
@ -483,6 +483,7 @@ bintrayConfig {
|
|||||||
'corda-core',
|
'corda-core',
|
||||||
'corda-core-deterministic',
|
'corda-core-deterministic',
|
||||||
'corda-deterministic-verifier',
|
'corda-deterministic-verifier',
|
||||||
|
'corda-deserializers-djvm',
|
||||||
'corda',
|
'corda',
|
||||||
'corda-finance-workflows',
|
'corda-finance-workflows',
|
||||||
'corda-finance-contracts',
|
'corda-finance-contracts',
|
||||||
@ -501,6 +502,7 @@ bintrayConfig {
|
|||||||
'corda-tools-shell-cli',
|
'corda-tools-shell-cli',
|
||||||
'corda-serialization',
|
'corda-serialization',
|
||||||
'corda-serialization-deterministic',
|
'corda-serialization-deterministic',
|
||||||
|
'corda-serialization-djvm',
|
||||||
'corda-tools-blob-inspector',
|
'corda-tools-blob-inspector',
|
||||||
'corda-tools-explorer',
|
'corda-tools-explorer',
|
||||||
'corda-tools-network-bootstrapper',
|
'corda-tools-network-bootstrapper',
|
||||||
|
@ -170,21 +170,15 @@ dependencies {
|
|||||||
|
|
||||||
// Sandbox for deterministic contract verification
|
// Sandbox for deterministic contract verification
|
||||||
compile "net.corda.djvm:corda-djvm:$djvm_version"
|
compile "net.corda.djvm:corda-djvm:$djvm_version"
|
||||||
compile("net.corda.djvm:corda-djvm-serialization:$djvm_version") {
|
compile project(':serialization-djvm')
|
||||||
exclude group: 'net.corda'
|
|
||||||
}
|
|
||||||
compile(project(':node:djvm')) {
|
compile(project(':node:djvm')) {
|
||||||
transitive = false
|
transitive = false
|
||||||
}
|
}
|
||||||
jdkRt "net.corda:deterministic-rt:latest.integration"
|
jdkRt "net.corda:deterministic-rt:latest.integration"
|
||||||
deterministic project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
|
deterministic project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
|
||||||
deterministic project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
deterministic project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
||||||
deterministic("net.corda.djvm:corda-djvm-deserializers:$djvm_version") {
|
deterministic project(':serialization-djvm:deserializers')
|
||||||
transitive = false
|
deterministic project(':node:djvm')
|
||||||
}
|
|
||||||
deterministic(project(':node:djvm')) {
|
|
||||||
transitive = false
|
|
||||||
}
|
|
||||||
deterministic "org.slf4j:slf4j-nop:$slf4j_version"
|
deterministic "org.slf4j:slf4j-nop:$slf4j_version"
|
||||||
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
|
||||||
|
@ -13,6 +13,10 @@ dependencies {
|
|||||||
|
|
||||||
jar {
|
jar {
|
||||||
archiveBaseName = 'corda-node-djvm'
|
archiveBaseName = 'corda-node-djvm'
|
||||||
|
manifest {
|
||||||
|
attributes('Automatic-Module-Name': 'net.corda.node.djvm')
|
||||||
|
attributes('Sealed': true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publish {
|
publish {
|
||||||
|
@ -7,9 +7,9 @@ import net.corda.core.serialization.SerializedBytes
|
|||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.ByteSequence
|
import net.corda.core.utilities.ByteSequence
|
||||||
import net.corda.djvm.rewiring.SandboxClassLoader
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
import net.corda.djvm.serialization.createSandboxSerializationEnv
|
|
||||||
import net.corda.djvm.serialization.deserializeTo
|
|
||||||
import net.corda.node.djvm.ComponentBuilder
|
import net.corda.node.djvm.ComponentBuilder
|
||||||
|
import net.corda.serialization.djvm.createSandboxSerializationEnv
|
||||||
|
import net.corda.serialization.djvm.deserializeTo
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
|
|
||||||
class Serializer(private val classLoader: SandboxClassLoader) {
|
class Serializer(private val classLoader: SandboxClassLoader) {
|
||||||
|
69
serialization-djvm/build.gradle
Normal file
69
serialization-djvm/build.gradle
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.jetbrains.kotlin.jvm'
|
||||||
|
id 'net.corda.plugins.publish-utils'
|
||||||
|
id 'com.jfrog.artifactory'
|
||||||
|
id 'java-library'
|
||||||
|
id 'idea'
|
||||||
|
}
|
||||||
|
|
||||||
|
description 'Serialization support for the DJVM'
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
sandboxTesting
|
||||||
|
jdkRt.resolutionStrategy {
|
||||||
|
// Always check the repository for a newer SNAPSHOT.
|
||||||
|
cacheChangingModulesFor 0, 'seconds'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api project(':core')
|
||||||
|
api project(':serialization')
|
||||||
|
api "net.corda.djvm:corda-djvm:$djvm_version"
|
||||||
|
implementation(project(':serialization-djvm:deserializers')) {
|
||||||
|
transitive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_jupiter_version"
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_jupiter_version"
|
||||||
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_jupiter_version"
|
||||||
|
|
||||||
|
// Test utilities
|
||||||
|
testImplementation "org.assertj:assertj-core:$assertj_version"
|
||||||
|
testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
|
||||||
|
jdkRt "net.corda:deterministic-rt:latest.integration"
|
||||||
|
|
||||||
|
// The DJVM will need this classpath to run the unit tests.
|
||||||
|
sandboxTesting files(sourceSets.getByName("test").output)
|
||||||
|
sandboxTesting project(':serialization-djvm:deserializers')
|
||||||
|
sandboxTesting project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
||||||
|
sandboxTesting "org.slf4j:slf4j-nop:$slf4j_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'corda-serialization-djvm'
|
||||||
|
manifest {
|
||||||
|
attributes('Automatic-Module-Name': 'net.corda.serialization.djvm')
|
||||||
|
attributes('Sealed': true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test) {
|
||||||
|
useJUnitPlatform()
|
||||||
|
systemProperty 'deterministic-rt.path', configurations.jdkRt.asPath
|
||||||
|
systemProperty 'sandbox-libraries.path', configurations.sandboxTesting.asPath
|
||||||
|
|
||||||
|
// Configure the host timezone to match the DJVM's.
|
||||||
|
systemProperty 'user.timezone', 'UTC'
|
||||||
|
}
|
||||||
|
|
||||||
|
publish {
|
||||||
|
name jar.archiveBaseName.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
downloadJavadoc = true
|
||||||
|
downloadSources = true
|
||||||
|
}
|
||||||
|
}
|
34
serialization-djvm/deserializers/build.gradle
Normal file
34
serialization-djvm/deserializers/build.gradle
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.jetbrains.kotlin.jvm'
|
||||||
|
id 'net.corda.plugins.publish-utils'
|
||||||
|
id 'com.jfrog.artifactory'
|
||||||
|
id 'java-library'
|
||||||
|
id 'idea'
|
||||||
|
}
|
||||||
|
apply from: '../../deterministic.gradle'
|
||||||
|
|
||||||
|
description 'Deserializers for the DJVM'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
|
||||||
|
api project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'corda-deserializers-djvm'
|
||||||
|
manifest {
|
||||||
|
attributes('Automatic-Module-Name': 'net.corda.serialization.djvm.deserializers')
|
||||||
|
attributes('Sealed': true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publish {
|
||||||
|
name jar.archiveBaseName.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
downloadJavadoc = true
|
||||||
|
downloadSources = true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.BitSetSerializer.BitSetProxy
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class BitSetDeserializer : Function<BitSetProxy, BitSet> {
|
||||||
|
override fun apply(proxy: BitSetProxy): BitSet {
|
||||||
|
return BitSet.valueOf(proxy.bytes)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.CertPathSerializer.CertPathProxy
|
||||||
|
import java.security.cert.CertPath
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class CertPathDeserializer : Function<CertPathProxy, CertPath> {
|
||||||
|
override fun apply(proxy: CertPathProxy): CertPath {
|
||||||
|
val factory = CertificateFactory.getInstance(proxy.type)
|
||||||
|
return factory.generateCertPath(proxy.encoded.inputStream())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.ClassSerializer.ClassProxy
|
||||||
|
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class ClassDeserializer : Function<ClassProxy, Class<*>> {
|
||||||
|
override fun apply(proxy: ClassProxy): Class<*> {
|
||||||
|
return Class.forName(proxy.className)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.core.utilities.NonEmptySet
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class CreateCollection : Function<Array<Any?>, Collection<Any?>> {
|
||||||
|
private val concreteConstructors: Map<Class<out Collection<*>>, (Array<Any?>) -> Collection<Any?>> = mapOf(
|
||||||
|
List::class.java to ::createList,
|
||||||
|
Set::class.java to ::createSet,
|
||||||
|
SortedSet::class.java to ::createSortedSet,
|
||||||
|
NavigableSet::class.java to ::createNavigableSet,
|
||||||
|
Collection::class.java to ::createCollection,
|
||||||
|
NonEmptySet::class.java to ::createNonEmptySet
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun createList(values: Array<Any?>): List<Any?> {
|
||||||
|
return Collections.unmodifiableList(arrayListOf(*values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSet(values: Array<Any?>): Set<Any?> {
|
||||||
|
return Collections.unmodifiableSet(linkedSetOf(*values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSortedSet(values: Array<Any?>): SortedSet<Any?> {
|
||||||
|
return Collections.unmodifiableSortedSet(sortedSetOf(*values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNavigableSet(values: Array<Any?>): NavigableSet<Any?> {
|
||||||
|
return Collections.unmodifiableNavigableSet(sortedSetOf(*values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCollection(values: Array<Any?>): Collection<Any?> {
|
||||||
|
return Collections.unmodifiableCollection(arrayListOf(*values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNonEmptySet(values: Array<Any?>): NonEmptySet<Any?> {
|
||||||
|
return NonEmptySet.copyOf(arrayListOf(*values))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
override fun apply(inputs: Array<Any?>): Collection<Any?> {
|
||||||
|
val collectionClass = inputs[0] as Class<out Collection<Any?>>
|
||||||
|
val args = inputs[1] as Array<Any?>
|
||||||
|
return concreteConstructors[collectionClass]?.invoke(args)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class CreateCurrency : Function<String, Currency> {
|
||||||
|
override fun apply(currencyCode: String): Currency {
|
||||||
|
return Currency.getInstance(currencyCode)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class CreateFromString(private val factory: Constructor<Any>) : Function<String, Any> {
|
||||||
|
override fun apply(text: String): Any {
|
||||||
|
return factory.newInstance(text)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class CreateMap : Function<Array<Any>, Map<Any?, Any?>> {
|
||||||
|
private val concreteConstructors: Map<Class<out Map<*, *>>, (Array<Array<Any>>) -> Map<Any?, Any?>> = mapOf(
|
||||||
|
Map::class.java to ::createMap,
|
||||||
|
SortedMap::class.java to ::createSortedMap,
|
||||||
|
LinkedHashMap::class.java to ::createLinkedHashMap,
|
||||||
|
NavigableMap::class.java to ::createNavigableMap,
|
||||||
|
TreeMap::class.java to ::createTreeMap,
|
||||||
|
EnumMap::class.java to ::createEnumMap
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun createMap(values: Array<Array<Any>>): Map<Any?, Any?> {
|
||||||
|
return Collections.unmodifiableMap(values.map { it[0] to it[1] }.toMap())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSortedMap(values: Array<Array<Any>>): SortedMap<Any?, out Any?> {
|
||||||
|
return Collections.unmodifiableSortedMap(createTreeMap(values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNavigableMap(values: Array<Array<Any>>): NavigableMap<Any?, out Any?> {
|
||||||
|
return Collections.unmodifiableNavigableMap(createTreeMap(values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createLinkedHashMap(values: Array<Array<Any>>): LinkedHashMap<Any?, out Any?> {
|
||||||
|
return values.map { it[0] to it[1] }.toMap(LinkedHashMap())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTreeMap(values: Array<Array<Any>>): TreeMap<Any?, out Any?> {
|
||||||
|
return values.map { it[0] to it[1] }.toMap(TreeMap())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEnumMap(values: Array<Array<Any>>): Map<Any?, Any?> {
|
||||||
|
val map = values.map { it[0] to it[1] }.toMap()
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
return EnumMap(map as Map<JustForCasting, Any?>) as Map<Any?, Any?>
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
override fun apply(inputs: Array<Any>): Map<Any?, Any?> {
|
||||||
|
val mapClass = inputs[0] as Class<out Map<Any?, Any?>>
|
||||||
|
val args = inputs[1] as Array<Array<Any>>
|
||||||
|
return concreteConstructors[mapClass]?.invoke(args)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.Decimal128
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class Decimal128Deserializer : Function<LongArray, Decimal128> {
|
||||||
|
override fun apply(underlying: LongArray): Decimal128 {
|
||||||
|
return Decimal128(underlying[0], underlying[1])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.Decimal32
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class Decimal32Deserializer : Function<IntArray, Decimal32> {
|
||||||
|
override fun apply(underlying: IntArray): Decimal32 {
|
||||||
|
return Decimal32(underlying[0])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.Decimal64
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class Decimal64Deserializer : Function<LongArray, Decimal64> {
|
||||||
|
override fun apply(underlying: LongArray): Decimal64 {
|
||||||
|
return Decimal64(underlying[0])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class DescribeEnum : Function<Class<*>, Array<out Any?>> {
|
||||||
|
override fun apply(enumClass: Class<*>): Array<out Any?> {
|
||||||
|
return enumClass.enumConstants
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.DurationSerializer.DurationProxy
|
||||||
|
import java.time.Duration
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class DurationDeserializer : Function<DurationProxy, Duration> {
|
||||||
|
override fun apply(proxy: DurationProxy): Duration {
|
||||||
|
return Duration.ofSeconds(proxy.seconds, proxy.nanos.toLong())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.core.internal.uncheckedCast
|
||||||
|
import net.corda.serialization.internal.amqp.custom.EnumSetSerializer.EnumSetProxy
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class EnumSetDeserializer : Function<EnumSetProxy, EnumSet<*>> {
|
||||||
|
override fun apply(proxy: EnumSetProxy): EnumSet<*> {
|
||||||
|
return if (proxy.elements.isEmpty()) {
|
||||||
|
EnumSet.noneOf(uncheckedCast<Class<*>, Class<JustForCasting>>(proxy.clazz))
|
||||||
|
} else {
|
||||||
|
EnumSet.copyOf(uncheckedCast<List<Any>, List<JustForCasting>>(proxy.elements))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class InputStreamDeserializer : Function<ByteArray, InputStream?> {
|
||||||
|
override fun apply(bytes: ByteArray): InputStream? {
|
||||||
|
return ByteArrayInputStream(bytes)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.InstantSerializer.InstantProxy
|
||||||
|
import java.time.Instant
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class InstantDeserializer : Function<InstantProxy, Instant> {
|
||||||
|
override fun apply(proxy: InstantProxy): Instant {
|
||||||
|
return Instant.ofEpochSecond(proxy.epochSeconds, proxy.nanos.toLong())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
enum class JustForCasting {
|
||||||
|
UNUSED
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.LocalDateSerializer.LocalDateProxy
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class LocalDateDeserializer : Function<LocalDateProxy, LocalDate> {
|
||||||
|
override fun apply(proxy: LocalDateProxy): LocalDate {
|
||||||
|
return LocalDate.of(proxy.year, proxy.month.toInt(), proxy.day.toInt())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer.LocalDateTimeProxy
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class LocalDateTimeDeserializer : Function<LocalDateTimeProxy, LocalDateTime> {
|
||||||
|
override fun apply(proxy: LocalDateTimeProxy): LocalDateTime {
|
||||||
|
return LocalDateTime.of(proxy.date, proxy.time)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.LocalTimeSerializer.LocalTimeProxy
|
||||||
|
import java.time.LocalTime
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class LocalTimeDeserializer : Function<LocalTimeProxy, LocalTime> {
|
||||||
|
override fun apply(proxy: LocalTimeProxy): LocalTime {
|
||||||
|
return LocalTime.of(proxy.hour.toInt(), proxy.minute.toInt(), proxy.second.toInt(), proxy.nano)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.MonthDaySerializer.MonthDayProxy
|
||||||
|
import java.time.MonthDay
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class MonthDayDeserializer : Function<MonthDayProxy, MonthDay> {
|
||||||
|
override fun apply(proxy: MonthDayProxy): MonthDay {
|
||||||
|
return MonthDay.of(proxy.month.toInt(), proxy.day.toInt())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer.OffsetDateTimeProxy
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class OffsetDateTimeDeserializer : Function<OffsetDateTimeProxy, OffsetDateTime> {
|
||||||
|
override fun apply(proxy: OffsetDateTimeProxy): OffsetDateTime {
|
||||||
|
return OffsetDateTime.of(proxy.dateTime, proxy.offset)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer.OffsetTimeProxy
|
||||||
|
import java.time.OffsetTime
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class OffsetTimeDeserializer : Function<OffsetTimeProxy, OffsetTime> {
|
||||||
|
override fun apply(proxy: OffsetTimeProxy): OffsetTime {
|
||||||
|
return OffsetTime.of(proxy.time, proxy.offset)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
|
import net.corda.core.utilities.OpaqueBytesSubSequence
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class OpaqueBytesSubSequenceDeserializer : Function<OpaqueBytes, OpaqueBytesSubSequence> {
|
||||||
|
override fun apply(proxy: OpaqueBytes): OpaqueBytesSubSequence {
|
||||||
|
return OpaqueBytesSubSequence(proxy.bytes, proxy.offset, proxy.size)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OptionalSerializer.OptionalProxy
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class OptionalDeserializer : Function<OptionalProxy, Optional<Any>> {
|
||||||
|
override fun apply(proxy: OptionalProxy): Optional<Any> {
|
||||||
|
return Optional.ofNullable(proxy.item)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.PeriodSerializer.PeriodProxy
|
||||||
|
import java.time.Period
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class PeriodDeserializer : Function<PeriodProxy, Period> {
|
||||||
|
override fun apply(proxy: PeriodProxy): Period {
|
||||||
|
return Period.of(proxy.years, proxy.months, proxy.days)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.core.crypto.Crypto
|
||||||
|
import java.security.PublicKey
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class PublicKeyDecoder : Function<ByteArray, PublicKey> {
|
||||||
|
override fun apply(encoded: ByteArray): PublicKey {
|
||||||
|
return Crypto.decodePublicKey(encoded)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.Symbol
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SymbolDeserializer : Function<String, Symbol> {
|
||||||
|
override fun apply(value: String): Symbol {
|
||||||
|
return Symbol.valueOf(value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedByte
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class UnsignedByteDeserializer : Function<ByteArray, UnsignedByte> {
|
||||||
|
override fun apply(underlying: ByteArray): UnsignedByte {
|
||||||
|
return UnsignedByte(underlying[0])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedInteger
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class UnsignedIntegerDeserializer : Function<IntArray, UnsignedInteger> {
|
||||||
|
override fun apply(underlying: IntArray): UnsignedInteger {
|
||||||
|
return UnsignedInteger(underlying[0])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedLong
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class UnsignedLongDeserializer : Function<LongArray, UnsignedLong> {
|
||||||
|
override fun apply(underlying: LongArray): UnsignedLong {
|
||||||
|
return UnsignedLong(underlying[0])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedShort
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class UnsignedShortDeserializer : Function<ShortArray, UnsignedShort> {
|
||||||
|
override fun apply(underlying: ShortArray): UnsignedShort {
|
||||||
|
return UnsignedShort(underlying[0])
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509CRL
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class X509CRLDeserializer : Function<ByteArray, X509CRL> {
|
||||||
|
override fun apply(bytes: ByteArray): X509CRL {
|
||||||
|
val factory = CertificateFactory.getInstance("X.509")
|
||||||
|
return factory.generateCRL(bytes.inputStream()) as X509CRL
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class X509CertificateDeserializer : Function<ByteArray, X509Certificate> {
|
||||||
|
override fun apply(bits: ByteArray): X509Certificate {
|
||||||
|
val factory = CertificateFactory.getInstance("X.509")
|
||||||
|
return factory.generateCertificate(bits.inputStream()) as X509Certificate
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.YearSerializer.YearProxy
|
||||||
|
import java.time.Year
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class YearDeserializer : Function<YearProxy, Year> {
|
||||||
|
override fun apply(proxy: YearProxy): Year {
|
||||||
|
return Year.of(proxy.year)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.YearMonthSerializer.YearMonthProxy
|
||||||
|
import java.time.YearMonth
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class YearMonthDeserializer : Function<YearMonthProxy, YearMonth> {
|
||||||
|
override fun apply(proxy: YearMonthProxy): YearMonth {
|
||||||
|
return YearMonth.of(proxy.year, proxy.month.toInt())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.ZoneIdSerializer.ZoneIdProxy
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class ZoneIdDeserializer : Function<ZoneIdProxy, ZoneId> {
|
||||||
|
override fun apply(proxy: ZoneIdProxy): ZoneId {
|
||||||
|
return ZoneId.of(proxy.id)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm.deserializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer.ZonedDateTimeProxy
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class ZonedDateTimeDeserializer : Function<ZonedDateTimeProxy, Array<out Any>?> {
|
||||||
|
override fun apply(proxy: ZonedDateTimeProxy): Array<out Any>? {
|
||||||
|
return arrayOf(proxy.dateTime, proxy.offset, proxy.zone)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.core.serialization.SerializationContext.UseCase
|
||||||
|
import net.corda.core.serialization.SerializedBytes
|
||||||
|
import net.corda.core.utilities.ByteSequence
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.serializers.*
|
||||||
|
import net.corda.serialization.internal.CordaSerializationMagic
|
||||||
|
import net.corda.serialization.internal.SerializationScheme
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class AMQPSerializationScheme(
|
||||||
|
private val classLoader: SandboxClassLoader,
|
||||||
|
private val sandboxBasicInput: Function<in Any?, out Any?>,
|
||||||
|
private val taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
private val serializerFactoryFactory: SerializerFactoryFactory
|
||||||
|
) : SerializationScheme {
|
||||||
|
|
||||||
|
private fun getSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
|
return serializerFactoryFactory.make(context).apply {
|
||||||
|
register(SandboxBitSetSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxCertPathSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxDurationSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxEnumSetSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxInputStreamSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxInstantSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxLocalDateSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxLocalDateTimeSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxLocalTimeSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxMonthDaySerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxOffsetDateTimeSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxOffsetTimeSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxPeriodSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxYearMonthSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxYearSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxZonedDateTimeSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxZoneIdSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxOpaqueBytesSubSequenceSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxOptionalSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxPrimitiveSerializer(UUID::class.java, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(String::class.java, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Byte::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Short::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Int::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Long::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Float::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Double::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Boolean::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxPrimitiveSerializer(Date::class.javaObjectType, classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxCharacterSerializer(classLoader, sandboxBasicInput))
|
||||||
|
register(SandboxCollectionSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxMapSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxEnumSerializer(classLoader, taskFactory, this))
|
||||||
|
register(SandboxPublicKeySerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxToStringSerializer(BigDecimal::class.java, classLoader, taskFactory, sandboxBasicInput))
|
||||||
|
register(SandboxToStringSerializer(BigInteger::class.java, classLoader, taskFactory, sandboxBasicInput))
|
||||||
|
register(SandboxToStringSerializer(StringBuffer::class.java, classLoader, taskFactory, sandboxBasicInput))
|
||||||
|
register(SandboxCurrencySerializer(classLoader, taskFactory, sandboxBasicInput))
|
||||||
|
register(SandboxX509CertificateSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxX509CRLSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxUnsignedLongSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxUnsignedIntegerSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxUnsignedShortSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxUnsignedByteSerializer(classLoader, taskFactory))
|
||||||
|
register(SandboxDecimal128Serializer(classLoader, taskFactory))
|
||||||
|
register(SandboxDecimal64Serializer(classLoader, taskFactory))
|
||||||
|
register(SandboxDecimal32Serializer(classLoader, taskFactory))
|
||||||
|
register(SandboxSymbolSerializer(classLoader, taskFactory, sandboxBasicInput))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T {
|
||||||
|
val serializerFactory = getSerializerFactory(context)
|
||||||
|
return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
||||||
|
val serializerFactory = getSerializerFactory(context)
|
||||||
|
return SerializationOutput(serializerFactory).serialize(obj, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: UseCase): Boolean {
|
||||||
|
return magic == amqpMagic && target == UseCase.P2P
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
|
||||||
|
class DelegatingClassLoader(private val delegate: SandboxClassLoader) : ClassLoader(null) {
|
||||||
|
@Throws(ClassNotFoundException::class)
|
||||||
|
override fun loadClass(name: String, resolve: Boolean): Class<*> {
|
||||||
|
return delegate.loadForSandbox(name).type
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
@file:Suppress("platform_class_mapped_to_kotlin")
|
||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import net.corda.serialization.internal.model.*
|
||||||
|
import java.lang.Boolean
|
||||||
|
import java.lang.Byte
|
||||||
|
import java.lang.Double
|
||||||
|
import java.lang.Float
|
||||||
|
import java.lang.Long
|
||||||
|
import java.lang.Short
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.Collections.unmodifiableMap
|
||||||
|
import java.util.function.Function
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This has all been lovingly copied from [SerializerFactoryBuilder].
|
||||||
|
*/
|
||||||
|
class SandboxSerializerFactoryFactory(
|
||||||
|
private val primitiveSerializerFactory: Function<Class<*>, AMQPSerializer<Any>>
|
||||||
|
) : SerializerFactoryFactory {
|
||||||
|
|
||||||
|
override fun make(context: SerializationContext): SerializerFactory {
|
||||||
|
val classLoader = context.deserializationClassLoader
|
||||||
|
|
||||||
|
val primitiveTypes = unmodifiableMap(mapOf<Class<*>, Class<*>>(
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Boolean") to Boolean.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Byte") to Byte.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Character") to Character.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Double") to Double.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Float") to Float.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Integer") to Integer.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Long") to Long.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.Short") to Short.TYPE,
|
||||||
|
classLoader.loadClass("sandbox.java.lang.String") to String::class.java,
|
||||||
|
classLoader.loadClass("sandbox.java.util.Date") to Date::class.java,
|
||||||
|
classLoader.loadClass("sandbox.java.util.UUID") to UUID::class.java,
|
||||||
|
Void::class.java to Void.TYPE
|
||||||
|
))
|
||||||
|
|
||||||
|
val classCarpenter = createClassCarpenter(context)
|
||||||
|
val descriptorBasedSerializerRegistry = DefaultDescriptorBasedSerializerRegistry()
|
||||||
|
val customSerializerRegistry = CachingCustomSerializerRegistry(
|
||||||
|
descriptorBasedSerializerRegistry = descriptorBasedSerializerRegistry,
|
||||||
|
allowedFor = singleton(classLoader.loadClass("sandbox.java.lang.Object"))
|
||||||
|
)
|
||||||
|
|
||||||
|
val localTypeModel = ConfigurableLocalTypeModel(
|
||||||
|
WhitelistBasedTypeModelConfiguration(context.whitelist, customSerializerRegistry)
|
||||||
|
)
|
||||||
|
|
||||||
|
val fingerPrinter = TypeModellingFingerPrinter(customSerializerRegistry)
|
||||||
|
|
||||||
|
val localSerializerFactory = DefaultLocalSerializerFactory(
|
||||||
|
whitelist = context.whitelist,
|
||||||
|
typeModel = localTypeModel,
|
||||||
|
fingerPrinter = fingerPrinter,
|
||||||
|
classloader = classLoader,
|
||||||
|
descriptorBasedSerializerRegistry = descriptorBasedSerializerRegistry,
|
||||||
|
primitiveSerializerFactory = primitiveSerializerFactory,
|
||||||
|
isPrimitiveType = Predicate { clazz -> clazz.isPrimitive || clazz in primitiveTypes.keys },
|
||||||
|
customSerializerRegistry = customSerializerRegistry,
|
||||||
|
onlyCustomSerializers = false
|
||||||
|
)
|
||||||
|
|
||||||
|
val typeLoader: TypeLoader = ClassCarpentingTypeLoader(
|
||||||
|
carpenter = SchemaBuildingRemoteTypeCarpenter(classCarpenter),
|
||||||
|
classLoader = classLoader
|
||||||
|
)
|
||||||
|
|
||||||
|
val evolutionSerializerFactory = DefaultEvolutionSerializerFactory(
|
||||||
|
localSerializerFactory = localSerializerFactory,
|
||||||
|
classLoader = classLoader,
|
||||||
|
mustPreserveDataWhenEvolving = context.preventDataLoss,
|
||||||
|
primitiveTypes = primitiveTypes
|
||||||
|
)
|
||||||
|
|
||||||
|
val remoteSerializerFactory = DefaultRemoteSerializerFactory(
|
||||||
|
evolutionSerializerFactory = evolutionSerializerFactory,
|
||||||
|
descriptorBasedSerializerRegistry = descriptorBasedSerializerRegistry,
|
||||||
|
remoteTypeModel = AMQPRemoteTypeModel(),
|
||||||
|
localTypeModel = localTypeModel,
|
||||||
|
typeLoader = typeLoader,
|
||||||
|
localSerializerFactory = localSerializerFactory
|
||||||
|
)
|
||||||
|
|
||||||
|
return ComposedSerializerFactory(localSerializerFactory, remoteSerializerFactory, customSerializerRegistry)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.ClassWhitelist
|
||||||
|
|
||||||
|
class SandboxWhitelist : ClassWhitelist {
|
||||||
|
companion object {
|
||||||
|
private val packageName = "^sandbox\\.(?:java|kotlin)(?:[.]|$)".toRegex()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasListed(type: Class<*>): Boolean {
|
||||||
|
return packageName.containsMatchIn(type.`package`.name)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
@file:JvmName("Serialization")
|
||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.core.serialization.SerializationContext.UseCase
|
||||||
|
import net.corda.core.serialization.SerializationFactory
|
||||||
|
import net.corda.core.serialization.SerializedBytes
|
||||||
|
import net.corda.core.serialization.internal.SerializationEnvironment
|
||||||
|
import net.corda.core.utilities.ByteSequence
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.serializers.PrimitiveSerializer
|
||||||
|
import net.corda.serialization.internal.GlobalTransientClassWhiteList
|
||||||
|
import net.corda.serialization.internal.SerializationContextImpl
|
||||||
|
import net.corda.serialization.internal.SerializationFactoryImpl
|
||||||
|
import net.corda.serialization.internal.amqp.AMQPSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.amqpMagic
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun SandboxClassLoader.toSandboxAnyClass(clazz: Class<*>): Class<Any> {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
return toSandboxClass(clazz) as Class<Any>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createSandboxSerializationEnv(classLoader: SandboxClassLoader): SerializationEnvironment {
|
||||||
|
val p2pContext: SerializationContext = SerializationContextImpl(
|
||||||
|
preferredSerializationVersion = amqpMagic,
|
||||||
|
deserializationClassLoader = DelegatingClassLoader(classLoader),
|
||||||
|
whitelist = GlobalTransientClassWhiteList(SandboxWhitelist()),
|
||||||
|
properties = emptyMap(),
|
||||||
|
objectReferencesEnabled = true,
|
||||||
|
carpenterDisabled = true,
|
||||||
|
useCase = UseCase.P2P,
|
||||||
|
encoding = null
|
||||||
|
)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val sandboxBasicInput = classLoader.createBasicInput()
|
||||||
|
|
||||||
|
val primitiveSerializerFactory: Function<Class<*>, AMQPSerializer<Any>> = Function { clazz ->
|
||||||
|
PrimitiveSerializer(clazz, sandboxBasicInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
val factory = SerializationFactoryImpl(mutableMapOf()).apply {
|
||||||
|
registerScheme(AMQPSerializationScheme(
|
||||||
|
classLoader = classLoader,
|
||||||
|
sandboxBasicInput = sandboxBasicInput,
|
||||||
|
taskFactory = taskFactory,
|
||||||
|
serializerFactoryFactory = SandboxSerializerFactoryFactory(primitiveSerializerFactory)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return SerializationEnvironment.with(factory, p2pContext = p2pContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Any> SerializedBytes<T>.deserializeFor(classLoader: SandboxClassLoader): Any {
|
||||||
|
val clazz = classLoader.toSandboxClass(T::class.java)
|
||||||
|
return deserializeTo(clazz, classLoader, SerializationFactory.defaultFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteSequence.deserializeTo(clazz: Class<*>, classLoader: SandboxClassLoader, factory: SerializationFactory): Any {
|
||||||
|
return deserializeTo(clazz, classLoader, factory, factory.defaultContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteSequence.deserializeTo(
|
||||||
|
clazz: Class<*>,
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
factory: SerializationFactory,
|
||||||
|
context: SerializationContext
|
||||||
|
): Any {
|
||||||
|
val obj = factory.deserialize(this, Any::class.java, context)
|
||||||
|
return if (clazz.isInstance(obj)) {
|
||||||
|
obj
|
||||||
|
} else {
|
||||||
|
classLoader.createBasicInput().apply(obj)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
@file:JvmName("ExceptionUtils")
|
||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.AMQPNotSerializableException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function which helps tracking the path in the object graph when exceptions are thrown.
|
||||||
|
* Since there might be a chain of nested calls it is useful to record which part of the graph caused an issue.
|
||||||
|
* Path information is added to the message of the exception being thrown.
|
||||||
|
*/
|
||||||
|
internal inline fun <T> ifThrowsAppend(strToAppendFn: () -> String, block: () -> T): T {
|
||||||
|
try {
|
||||||
|
return block()
|
||||||
|
} catch (th: Throwable) {
|
||||||
|
when (th) {
|
||||||
|
is AMQPNotSerializableException -> th.classHierarchy.add(strToAppendFn())
|
||||||
|
// Do not overwrite the message of these exceptions as it may be used.
|
||||||
|
is ClassNotFoundException -> {}
|
||||||
|
is NoClassDefFoundError -> {}
|
||||||
|
else -> th.resetMessage("${strToAppendFn()} -> ${th.message}")
|
||||||
|
}
|
||||||
|
throw th
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not a public property so will have to use reflection
|
||||||
|
*/
|
||||||
|
private fun Throwable.resetMessage(newMsg: String) {
|
||||||
|
val detailMessageField = Throwable::class.java.getDeclaredField("detailMessage")
|
||||||
|
detailMessageField.isAccessible = true
|
||||||
|
detailMessageField.set(this, newMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We currently only support deserialisation, and so we're going to need this.
|
||||||
|
*/
|
||||||
|
fun abortReadOnly(): Nothing = throw UnsupportedOperationException("Read Only!")
|
@ -0,0 +1,28 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.Binary
|
||||||
|
import org.apache.qpid.proton.amqp.Symbol
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class PrimitiveSerializer(
|
||||||
|
override val type: Class<*>,
|
||||||
|
private val sandboxBasicInput: Function<in Any?, out Any?>
|
||||||
|
) : AMQPSerializer<Any> {
|
||||||
|
override val typeDescriptor: Symbol = typeDescriptorFor(type)
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return (obj as? Binary)?.array ?: sandboxBasicInput.apply(obj)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeClassInfo(output: SerializationOutput) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.BitSetDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.BitSetSerializer.BitSetProxy
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxBitSetSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(BitSet::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(BitSetProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, BitSetDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(BitSet::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.CertPathDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.CertPathSerializer.CertPathProxy
|
||||||
|
import java.security.cert.CertPath
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxCertPathSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(CertPath::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(CertPathProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, CertPathDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(CertPath::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxCharacterSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
private val basicInput: Function<in Any?, out Any?>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(Char::class.javaObjectType)) {
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return basicInput.apply(convertToChar(obj))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertToChar(obj: Any): Any {
|
||||||
|
return when (obj) {
|
||||||
|
is Short -> obj.toChar()
|
||||||
|
is Int -> obj.toChar()
|
||||||
|
else -> obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.ClassDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.AMQPNotSerializableException
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.ClassSerializer.ClassProxy
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
class SandboxClassSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = Class::class.java as Class<Any>,
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(ClassProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, ClassDeserializer::class.java)
|
||||||
|
private val nameOf: Function<Any, String>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val fetch = proxyClass.getMethod("getClassName")
|
||||||
|
nameOf = Function { proxy ->
|
||||||
|
fetch(proxy).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return try {
|
||||||
|
task.apply(proxy)!!
|
||||||
|
} catch (e: ClassNotFoundException) {
|
||||||
|
val className = nameOf.apply(proxy)
|
||||||
|
throw AMQPNotSerializableException(type,
|
||||||
|
"Could not instantiate $className - not on the classpath",
|
||||||
|
"$className was not found by the node, check the Node containing the CorDapp that " +
|
||||||
|
"implements $className is loaded and on the Classpath",
|
||||||
|
mutableListOf(className)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.core.utilities.NonEmptySet
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.CreateCollection
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||||
|
import net.corda.serialization.internal.model.TypeIdentifier
|
||||||
|
import org.apache.qpid.proton.amqp.Symbol
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxCollectionSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
private val localFactory: LocalSerializerFactory
|
||||||
|
) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Collection::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val creator: Function<Array<Any>, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, CreateCollection::class.java) as Function<Array<Any>, out Any?>
|
||||||
|
|
||||||
|
private val unsupportedTypes: Set<Class<Any>> = listOf(
|
||||||
|
EnumSet::class.java
|
||||||
|
).map {
|
||||||
|
classLoader.toSandboxAnyClass(it)
|
||||||
|
}.toSet()
|
||||||
|
|
||||||
|
// The order matters here - the first match should be the most specific one.
|
||||||
|
// Kotlin preserves the ordering for us by associating into a LinkedHashMap.
|
||||||
|
private val supportedTypes: Map<Class<Any>, Class<out Collection<*>>> = listOf(
|
||||||
|
List::class.java,
|
||||||
|
NonEmptySet::class.java,
|
||||||
|
NavigableSet::class.java,
|
||||||
|
SortedSet::class.java,
|
||||||
|
Set::class.java,
|
||||||
|
Collection::class.java
|
||||||
|
).associateBy {
|
||||||
|
classLoader.toSandboxAnyClass(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBestMatchFor(type: Class<Any>): Map.Entry<Class<Any>, Class<out Collection<*>>>
|
||||||
|
= supportedTypes.entries.first { it.key.isAssignableFrom(type) }
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun isSerializerFor(clazz: Class<*>): Boolean {
|
||||||
|
return super.isSerializerFor(clazz) && unsupportedTypes.none { it.isAssignableFrom(clazz) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun specialiseFor(declaredType: Type): AMQPSerializer<Any>? {
|
||||||
|
if (declaredType !is ParameterizedType) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
val rawType = declaredType.rawType as Class<Any>
|
||||||
|
return ConcreteCollectionSerializer(declaredType, getBestMatchFor(rawType), creator, localFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
throw UnsupportedOperationException("Factory only")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
throw UnsupportedOperationException("Factory Only")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConcreteCollectionSerializer(
|
||||||
|
declaredType: ParameterizedType,
|
||||||
|
private val matchingType: Map.Entry<Class<Any>, Class<out Collection<*>>>,
|
||||||
|
private val creator: Function<Array<Any>, out Any?>,
|
||||||
|
factory: LocalSerializerFactory
|
||||||
|
) : AMQPSerializer<Any> {
|
||||||
|
override val type: ParameterizedType = declaredType
|
||||||
|
|
||||||
|
override val typeDescriptor: Symbol by lazy {
|
||||||
|
factory.createDescriptor(
|
||||||
|
LocalTypeInformation.ACollection(
|
||||||
|
observedType = declaredType.rawType,
|
||||||
|
typeIdentifier = TypeIdentifier.forGenericType(declaredType),
|
||||||
|
elementType =factory.getTypeInformation(declaredType.actualTypeArguments[0])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readObject(
|
||||||
|
obj: Any,
|
||||||
|
schemas: SerializationSchemas,
|
||||||
|
input: DeserializationInput,
|
||||||
|
context: SerializationContext
|
||||||
|
): Any {
|
||||||
|
val inboundType = type.actualTypeArguments[0]
|
||||||
|
return ifThrowsAppend({ type.typeName }) {
|
||||||
|
val args = (obj as List<*>).map {
|
||||||
|
input.readObjectOrNull(redescribe(it, inboundType), schemas, inboundType, context)
|
||||||
|
}.toTypedArray()
|
||||||
|
creator.apply(arrayOf(matchingType.key, args))!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeClassInfo(output: SerializationOutput) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.CreateCurrency
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxCurrencySerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
basicInput: Function<in Any?, out Any?>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(Currency::class.java)) {
|
||||||
|
private val creator: Function<Any?, Any?>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val createTask = classLoader.createTaskFor(taskFactory, CreateCurrency::class.java)
|
||||||
|
creator = basicInput.andThen(createTask)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(Currency::class.java)
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return creator.apply(obj)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.Decimal128Deserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.Decimal128
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxDecimal128Serializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(Decimal128::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<LongArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, Decimal128Deserializer::class.java) as Function<LongArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
val decimal128 = obj as Decimal128
|
||||||
|
return transformer.apply(longArrayOf(decimal128.mostSignificantBits, decimal128.leastSignificantBits))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.Decimal32Deserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.Decimal32
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxDecimal32Serializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(Decimal32::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<IntArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, Decimal32Deserializer::class.java) as Function<IntArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply(intArrayOf((obj as Decimal32).bits))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.Decimal64Deserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.Decimal64
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxDecimal64Serializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(Decimal64::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<LongArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, Decimal64Deserializer::class.java) as Function<LongArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply(longArrayOf((obj as Decimal64).bits))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.DurationDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.DurationSerializer.DurationProxy
|
||||||
|
import java.time.Duration
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxDurationSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(Duration::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(DurationProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, DurationDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(Duration::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.DescribeEnum
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import net.corda.serialization.internal.model.EnumTransforms
|
||||||
|
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||||
|
import net.corda.serialization.internal.model.TypeIdentifier
|
||||||
|
import org.apache.qpid.proton.amqp.Symbol
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxEnumSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
private val localFactory: LocalSerializerFactory
|
||||||
|
) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Enum::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val describer: Function<Class<*>, Array<Any>>
|
||||||
|
= classLoader.createTaskFor(taskFactory, DescribeEnum::class.java) as Function<Class<*>, Array<Any>>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun specialiseFor(declaredType: Type): AMQPSerializer<Any>? {
|
||||||
|
if (declaredType !is Class<*>) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val members = describer.apply(declaredType)
|
||||||
|
return ConcreteEnumSerializer(declaredType, members, localFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
throw UnsupportedOperationException("Factory only")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
throw UnsupportedOperationException("Factory Only")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConcreteEnumSerializer(
|
||||||
|
declaredType: Class<*>,
|
||||||
|
private val members: Array<Any>,
|
||||||
|
factory: LocalSerializerFactory
|
||||||
|
) : AMQPSerializer<Any> {
|
||||||
|
override val type: Class<*> = declaredType
|
||||||
|
|
||||||
|
override val typeDescriptor: Symbol by lazy {
|
||||||
|
factory.createDescriptor(
|
||||||
|
/*
|
||||||
|
* Partially populated, providing just the information
|
||||||
|
* required by the fingerprinter.
|
||||||
|
*/
|
||||||
|
LocalTypeInformation.AnEnum(
|
||||||
|
declaredType,
|
||||||
|
TypeIdentifier.forGenericType(declaredType),
|
||||||
|
members.map { it.toString() },
|
||||||
|
emptyList(),
|
||||||
|
EnumTransforms.empty
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
val enumName = (obj as List<*>)[0] as String
|
||||||
|
val enumOrd = obj[1] as Int
|
||||||
|
val fromOrd = members[enumOrd]
|
||||||
|
|
||||||
|
if (enumName != fromOrd.toString()) {
|
||||||
|
throw AMQPNotSerializableException(
|
||||||
|
type,
|
||||||
|
"Deserializing obj as enum $type with value $enumName.$enumOrd but ordinality has changed"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return fromOrd
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeClassInfo(output: SerializationOutput) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.EnumSetDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.EnumSetSerializer.EnumSetProxy
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxEnumSetSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(EnumSet::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(EnumSetProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, EnumSetDeserializer::class.java)
|
||||||
|
|
||||||
|
override val additionalSerializers: Set<CustomSerializer<out Any>> = singleton(
|
||||||
|
SandboxClassSerializer(classLoader, taskFactory, factory)
|
||||||
|
)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(EnumSet::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.InputStreamDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxInputStreamSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Implements<Any>(classLoader.toSandboxAnyClass(InputStream::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val decoder: Function<ByteArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, InputStreamDeserializer::class.java) as Function<ByteArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(InputStream::class.java)
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
|
||||||
|
return decoder.apply(bits)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.InstantDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.InstantSerializer.InstantProxy
|
||||||
|
import java.time.Instant
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxInstantSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(Instant::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(InstantProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, InstantDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(Instant::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.LocalDateDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.LocalDateSerializer.LocalDateProxy
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxLocalDateSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(LocalDate::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(LocalDateProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, LocalDateDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(LocalDate::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.LocalDateTimeDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.LocalDateTimeSerializer.LocalDateTimeProxy
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxLocalDateTimeSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(LocalDateTime::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(LocalDateTimeProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, LocalDateTimeDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(LocalDateTime::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.LocalTimeDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.LocalTimeSerializer.LocalTimeProxy
|
||||||
|
import java.time.LocalTime
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxLocalTimeSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(LocalTime::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(LocalTimeProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, LocalTimeDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(LocalTime::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.CreateMap
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import net.corda.serialization.internal.model.LocalTypeInformation
|
||||||
|
import net.corda.serialization.internal.model.TypeIdentifier
|
||||||
|
import org.apache.qpid.proton.amqp.Symbol
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxMapSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
private val localFactory: LocalSerializerFactory
|
||||||
|
) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Map::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val creator: Function<Array<Any>, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, CreateMap::class.java) as Function<Array<Any>, out Any?>
|
||||||
|
|
||||||
|
// The order matters here - the first match should be the most specific one.
|
||||||
|
// Kotlin preserves the ordering for us by associating into a LinkedHashMap.
|
||||||
|
private val supportedTypes: Map<Class<Any>, Class<out Map<*, *>>> = listOf(
|
||||||
|
TreeMap::class.java,
|
||||||
|
LinkedHashMap::class.java,
|
||||||
|
NavigableMap::class.java,
|
||||||
|
SortedMap::class.java,
|
||||||
|
EnumMap::class.java,
|
||||||
|
Map::class.java
|
||||||
|
).associateBy {
|
||||||
|
classLoader.toSandboxAnyClass(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBestMatchFor(type: Class<Any>): Map.Entry<Class<Any>, Class<out Map<*, *>>>
|
||||||
|
= supportedTypes.entries.first { it.key.isAssignableFrom(type) }
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun specialiseFor(declaredType: Type): AMQPSerializer<Any>? {
|
||||||
|
if (declaredType !is ParameterizedType) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
val rawType = declaredType.rawType as Class<Any>
|
||||||
|
return ConcreteMapSerializer(declaredType, getBestMatchFor(rawType), creator, localFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
throw UnsupportedOperationException("Factory only")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
throw UnsupportedOperationException("Factory Only")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConcreteMapSerializer(
|
||||||
|
declaredType: ParameterizedType,
|
||||||
|
private val matchingType: Map.Entry<Class<Any>, Class<out Map<*, *>>>,
|
||||||
|
private val creator: Function<Array<Any>, out Any?>,
|
||||||
|
factory: LocalSerializerFactory
|
||||||
|
) : AMQPSerializer<Any> {
|
||||||
|
override val type: ParameterizedType = declaredType
|
||||||
|
|
||||||
|
override val typeDescriptor: Symbol by lazy {
|
||||||
|
factory.createDescriptor(
|
||||||
|
LocalTypeInformation.AMap(
|
||||||
|
observedType = declaredType.rawType,
|
||||||
|
typeIdentifier = TypeIdentifier.forGenericType(declaredType),
|
||||||
|
keyType =factory.getTypeInformation(declaredType.actualTypeArguments[0]),
|
||||||
|
valueType = factory.getTypeInformation(declaredType.actualTypeArguments[1])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readObject(
|
||||||
|
obj: Any,
|
||||||
|
schemas: SerializationSchemas,
|
||||||
|
input: DeserializationInput,
|
||||||
|
context: SerializationContext
|
||||||
|
): Any {
|
||||||
|
val inboundKeyType = type.actualTypeArguments[0]
|
||||||
|
val inboundValueType = type.actualTypeArguments[1]
|
||||||
|
return ifThrowsAppend({ type.typeName }) {
|
||||||
|
val entries = (obj as Map<*, *>).map {
|
||||||
|
arrayOf(
|
||||||
|
input.readObjectOrNull(redescribe(it.key, inboundKeyType), schemas, inboundKeyType, context),
|
||||||
|
input.readObjectOrNull(redescribe(it.value, inboundValueType), schemas, inboundValueType, context)
|
||||||
|
)
|
||||||
|
}.toTypedArray()
|
||||||
|
creator.apply(arrayOf(matchingType.key, entries))!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeClassInfo(output: SerializationOutput) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.MonthDayDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.MonthDaySerializer.MonthDayProxy
|
||||||
|
import java.time.MonthDay
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxMonthDaySerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(MonthDay::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(MonthDayProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, MonthDayDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(MonthDay::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.OffsetDateTimeDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer.OffsetDateTimeProxy
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxOffsetDateTimeSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(OffsetDateTime::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(OffsetDateTimeProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, OffsetDateTimeDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(OffsetDateTime::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.OffsetTimeDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer.OffsetTimeProxy
|
||||||
|
import java.time.OffsetTime
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxOffsetTimeSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(OffsetTime::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(OffsetTimeProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, OffsetTimeDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(OffsetTime::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
|
import net.corda.core.utilities.OpaqueBytesSubSequence
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.OpaqueBytesSubSequenceDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxOpaqueBytesSubSequenceSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(OpaqueBytesSubSequence::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(OpaqueBytes::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, OpaqueBytesSubSequenceDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(OpaqueBytesSubSequence::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.OptionalDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OptionalSerializer.OptionalProxy
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxOptionalSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(Optional::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(OptionalProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, OptionalDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(Optional::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.PeriodDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.PeriodSerializer.PeriodProxy
|
||||||
|
import java.time.Period
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxPeriodSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(Period::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(PeriodProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, PeriodDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(Period::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxPrimitiveSerializer(
|
||||||
|
clazz: Class<*>,
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
private val basicInput: Function<in Any?, out Any?>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(clazz)) {
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return basicInput.apply(obj)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.PublicKeyDecoder
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.security.PublicKey
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxPublicKeySerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Implements<Any>(classLoader.toSandboxAnyClass(PublicKey::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val decoder: Function<ByteArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, PublicKeyDecoder::class.java) as Function<ByteArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(PublicKey::class.java)
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
|
||||||
|
return decoder.apply(bits)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.SymbolDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.Symbol
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxSymbolSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
basicInput: Function<in Any?, out Any?>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(Symbol::class.java)) {
|
||||||
|
private val transformer: Function<String, out Any?>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val transformTask = classLoader.createTaskFor(taskFactory, SymbolDeserializer::class.java)
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
transformer = basicInput.andThen(transformTask) as Function<String, Any?>
|
||||||
|
}
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply((obj as Symbol).toString())!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.CreateFromString
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Constructor
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxToStringSerializer(
|
||||||
|
unsafeClass: Class<*>,
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
basicInput: Function<in Any?, out Any?>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(unsafeClass)) {
|
||||||
|
private val creator: Function<Any?, Any?>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val stringClass = classLoader.loadClass("sandbox.java.lang.String")
|
||||||
|
val createTask = classLoader.toSandboxClass(CreateFromString::class.java)
|
||||||
|
.getConstructor(Constructor::class.java)
|
||||||
|
.newInstance(clazz.getConstructor(stringClass))
|
||||||
|
creator = basicInput.andThen(taskFactory.apply(createTask))
|
||||||
|
}
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(unsafeClass)
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return creator.apply(obj)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.UnsignedByteDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedByte
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxUnsignedByteSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(UnsignedByte::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<ByteArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, UnsignedByteDeserializer::class.java) as Function<ByteArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply(byteArrayOf((obj as UnsignedByte).toByte()))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.UnsignedIntegerDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedInteger
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxUnsignedIntegerSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(UnsignedInteger::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<IntArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, UnsignedIntegerDeserializer::class.java) as Function<IntArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply(intArrayOf((obj as UnsignedInteger).toInt()))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.UnsignedLongDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedLong
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxUnsignedLongSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(UnsignedLong::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<LongArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, UnsignedLongDeserializer::class.java) as Function<LongArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply(longArrayOf((obj as UnsignedLong).toLong()))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.UnsignedShortDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.amqp.UnsignedShort
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxUnsignedShortSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Is<Any>(classLoader.toSandboxAnyClass(UnsignedShort::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val transformer: Function<ShortArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, UnsignedShortDeserializer::class.java) as Function<ShortArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
return transformer.apply(shortArrayOf((obj as UnsignedShort).toShort()))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.X509CRLDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.security.cert.X509CRL
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxX509CRLSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Implements<Any>(classLoader.toSandboxAnyClass(X509CRL::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val generator: Function<ByteArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, X509CRLDeserializer::class.java) as Function<ByteArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(X509CRL::class.java)
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
|
||||||
|
return generator.apply(bits)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.X509CertificateDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.*
|
||||||
|
import org.apache.qpid.proton.codec.Data
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxX509CertificateSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>
|
||||||
|
) : CustomSerializer.Implements<Any>(classLoader.toSandboxAnyClass(X509Certificate::class.java)) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
private val generator: Function<ByteArray, out Any?>
|
||||||
|
= classLoader.createTaskFor(taskFactory, X509CertificateDeserializer::class.java) as Function<ByteArray, out Any?>
|
||||||
|
|
||||||
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(X509Certificate::class.java)
|
||||||
|
|
||||||
|
override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput, context: SerializationContext): Any {
|
||||||
|
val bits = input.readObject(obj, schemas, ByteArray::class.java, context) as ByteArray
|
||||||
|
return generator.apply(bits)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDescribedObject(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext) {
|
||||||
|
abortReadOnly()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.YearMonthDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.YearMonthSerializer.YearMonthProxy
|
||||||
|
import java.time.YearMonth
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxYearMonthSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(YearMonth::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(YearMonthProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, YearMonthDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(YearMonth::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.YearDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.YearSerializer.YearProxy
|
||||||
|
import java.time.Year
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxYearSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(Year::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(YearProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, YearDeserializer::class.java)
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(Year::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.ZoneIdDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.ZoneIdSerializer.ZoneIdProxy
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxZoneIdSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(ZoneId::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(ZoneIdProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, ZoneIdDeserializer::class.java)
|
||||||
|
|
||||||
|
override val revealSubclassesInSchema: Boolean = true
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(ZoneId::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return task.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package net.corda.serialization.djvm.serializers
|
||||||
|
|
||||||
|
import net.corda.djvm.rewiring.SandboxClassLoader
|
||||||
|
import net.corda.serialization.djvm.deserializers.ZonedDateTimeDeserializer
|
||||||
|
import net.corda.serialization.djvm.toSandboxAnyClass
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import net.corda.serialization.internal.amqp.custom.ZonedDateTimeSerializer.ZonedDateTimeProxy
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
import java.time.ZonedDateTime
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class SandboxZonedDateTimeSerializer(
|
||||||
|
classLoader: SandboxClassLoader,
|
||||||
|
taskFactory: Function<in Any, out Function<in Any?, out Any?>>,
|
||||||
|
factory: SerializerFactory
|
||||||
|
) : CustomSerializer.Proxy<Any, Any>(
|
||||||
|
clazz = classLoader.toSandboxAnyClass(ZonedDateTime::class.java),
|
||||||
|
proxyClass = classLoader.toSandboxAnyClass(ZonedDateTimeProxy::class.java),
|
||||||
|
factory = factory
|
||||||
|
) {
|
||||||
|
private val task = classLoader.createTaskFor(taskFactory, ZonedDateTimeDeserializer::class.java)
|
||||||
|
private val creator: Function<in Any?, out Any?>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val createTask = clazz.getMethod(
|
||||||
|
"createDJVM",
|
||||||
|
classLoader.toSandboxClass(LocalDateTime::class.java),
|
||||||
|
classLoader.toSandboxClass(ZoneOffset::class.java),
|
||||||
|
classLoader.toSandboxClass(ZoneId::class.java)
|
||||||
|
)
|
||||||
|
creator = task.andThen { input ->
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
createTask(null, *(input as Array<Any>))!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val deserializationAliases: Set<Class<*>> = singleton(ZonedDateTime::class.java)
|
||||||
|
|
||||||
|
override fun toProxy(obj: Any): Any = abortReadOnly()
|
||||||
|
|
||||||
|
override fun fromProxy(proxy: Any): Any {
|
||||||
|
return creator.apply(proxy)!!
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package greymalkin;
|
||||||
|
|
||||||
|
public class ExternalData {
|
||||||
|
private final String data;
|
||||||
|
|
||||||
|
public ExternalData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package greymalkin;
|
||||||
|
|
||||||
|
import net.corda.core.serialization.CordaSerializable;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@CordaSerializable
|
||||||
|
public enum ExternalEnum {
|
||||||
|
DOH,
|
||||||
|
RAY,
|
||||||
|
ME
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package net.corda.serialization.djvm;
|
||||||
|
|
||||||
|
import net.corda.core.serialization.CordaSerializable;
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
public class InnocentData {
|
||||||
|
private final String message;
|
||||||
|
private final Short number;
|
||||||
|
|
||||||
|
public InnocentData(String message, Short number) {
|
||||||
|
this.message = message;
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Short getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.corda.serialization.djvm;
|
||||||
|
|
||||||
|
import net.corda.core.serialization.ConstructorForDeserialization;
|
||||||
|
import net.corda.core.serialization.CordaSerializable;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
@CordaSerializable
|
||||||
|
public class MultiConstructorData {
|
||||||
|
private final String message;
|
||||||
|
private final long bigNumber;
|
||||||
|
private final Character tag;
|
||||||
|
|
||||||
|
@ConstructorForDeserialization
|
||||||
|
public MultiConstructorData(String message, long bigNumber, Character tag) {
|
||||||
|
this.message = message;
|
||||||
|
this.bigNumber = bigNumber;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiConstructorData(String message, long bigNumber) {
|
||||||
|
this(message, bigNumber, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiConstructorData(String message, char tag) {
|
||||||
|
this(message, 0, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiConstructorData(String message) {
|
||||||
|
this(message, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getBigNumber() {
|
||||||
|
return bigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Character getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("StringBufferReplaceableByString")
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new StringBuilder("MultiConstructor[message='").append(message)
|
||||||
|
.append("', bigNumber=").append(bigNumber)
|
||||||
|
.append(", tag=").append(tag)
|
||||||
|
.append(']')
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package net.corda.serialization.djvm;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class VeryEvilData extends InnocentData {
|
||||||
|
static {
|
||||||
|
if (!VeryEvilData.class.getName().startsWith("sandbox.")) {
|
||||||
|
// Execute our evil payload OUTSIDE the sandbox!
|
||||||
|
throw new IllegalStateException("Victory is mine!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public VeryEvilData(String message, Short number) {
|
||||||
|
super(message, number);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.serialization.djvm.SandboxType.*
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@ExtendWith(LocalSerialization::class)
|
||||||
|
class DeserializeBigDecimalTest : TestBase(KOTLIN) {
|
||||||
|
companion object {
|
||||||
|
const val VERY_BIG_DECIMAL = 994349993939.32737232
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing big decimal`() {
|
||||||
|
val bigDecimal = BigDecimalData(BigDecimal.valueOf(VERY_BIG_DECIMAL))
|
||||||
|
val data = bigDecimal.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxBigInteger = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showBigDecimal = classLoader.createTaskFor(taskFactory, ShowBigDecimal::class.java)
|
||||||
|
val result = showBigDecimal.apply(sandboxBigInteger) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(ShowBigDecimal().apply(bigDecimal), result.toString())
|
||||||
|
assertEquals(SANDBOX_STRING, result::class.java.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowBigDecimal : Function<BigDecimalData, String> {
|
||||||
|
override fun apply(data: BigDecimalData): String {
|
||||||
|
return with(data) {
|
||||||
|
"BigDecimal: $number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
data class BigDecimalData(val number: BigDecimal)
|
@ -0,0 +1,49 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.serialization.djvm.SandboxType.*
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@ExtendWith(LocalSerialization::class)
|
||||||
|
class DeserializeBigIntegerTest : TestBase(KOTLIN) {
|
||||||
|
companion object {
|
||||||
|
const val VERY_BIG_NUMBER = 1234567890123456789
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing big integer`() {
|
||||||
|
val bigInteger = BigIntegerData(BigInteger.valueOf(VERY_BIG_NUMBER))
|
||||||
|
val data = bigInteger.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxBigInteger = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showBigInteger = classLoader.createTaskFor(taskFactory, ShowBigInteger::class.java)
|
||||||
|
val result = showBigInteger.apply(sandboxBigInteger) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(ShowBigInteger().apply(bigInteger), result.toString())
|
||||||
|
assertEquals(SANDBOX_STRING, result::class.java.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowBigInteger : Function<BigIntegerData, String> {
|
||||||
|
override fun apply(data: BigIntegerData): String {
|
||||||
|
return with(data) {
|
||||||
|
"BigInteger: $number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
data class BigIntegerData(val number: BigInteger)
|
@ -0,0 +1,39 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.serialization.djvm.SandboxType.*
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@ExtendWith(LocalSerialization::class)
|
||||||
|
class DeserializeBitSetTest : TestBase(KOTLIN) {
|
||||||
|
@Test
|
||||||
|
fun `test deserializing bitset`() {
|
||||||
|
val bitSet = BitSet.valueOf(byteArrayOf(0x00, 0x70, 0x55, 0x3A, 0x48, 0x12))
|
||||||
|
val data = bitSet.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxBitSet = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showBitSet = classLoader.createTaskFor(taskFactory, ShowBitSet::class.java)
|
||||||
|
val result = showBitSet.apply(sandboxBitSet) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(bitSet.toString(), result.toString())
|
||||||
|
assertEquals(SANDBOX_STRING, result::class.java.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowBitSet : Function<BitSet, String> {
|
||||||
|
override fun apply(bitSet: BitSet): String {
|
||||||
|
return bitSet.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.serialization.djvm.SandboxType.*
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.bouncycastle.asn1.x509.CRLReason
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
import org.bouncycastle.cert.X509v2CRLBuilder
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
|
||||||
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.BeforeAll
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.security.KeyPairGenerator
|
||||||
|
import java.security.cert.CertPath
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509CRL
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@ExtendWith(LocalSerialization::class)
|
||||||
|
class DeserializeCertificatesTest : TestBase(KOTLIN) {
|
||||||
|
companion object {
|
||||||
|
// The sandbox's localisation may not match that of the host.
|
||||||
|
// E.g. line separator characters.
|
||||||
|
fun String.toUNIX(): String {
|
||||||
|
return replace(System.lineSeparator(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
val factory: CertificateFactory = CertificateFactory.getInstance("X.509")
|
||||||
|
lateinit var certificate: X509Certificate
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@BeforeAll
|
||||||
|
@JvmStatic
|
||||||
|
fun loadCertificate() {
|
||||||
|
certificate = this::class.java.classLoader.getResourceAsStream("testing.cert")?.use { input ->
|
||||||
|
factory.generateCertificate(input) as X509Certificate
|
||||||
|
} ?: fail("Certificate not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserialize certificate path`() {
|
||||||
|
val certPath = factory.generateCertPath(listOf(certificate))
|
||||||
|
val data = certPath.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxCertPath = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showCertPath = classLoader.createTaskFor(taskFactory, ShowCertPath::class.java)
|
||||||
|
val result = showCertPath.apply(sandboxCertPath) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(ShowCertPath().apply(certPath).toUNIX(), result.toString())
|
||||||
|
assertThat(result::class.java.name).startsWith("sandbox.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowCertPath : Function<CertPath, String> {
|
||||||
|
override fun apply(certPath: CertPath): String {
|
||||||
|
return "CertPath -> $certPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserialize X509 certificate`() {
|
||||||
|
val data = certificate.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxCertificate = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showCertificate = classLoader.createTaskFor(taskFactory, ShowCertificate::class.java)
|
||||||
|
val result = showCertificate.apply(sandboxCertificate) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(ShowCertificate().apply(certificate).toUNIX(), result.toString())
|
||||||
|
assertThat(result::class.java.name).startsWith("sandbox.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowCertificate : Function<X509Certificate, String> {
|
||||||
|
override fun apply(certificate: X509Certificate): String {
|
||||||
|
return "X.509 Certificate -> $certificate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test X509 CRL`() {
|
||||||
|
val caKeyPair = KeyPairGenerator.getInstance("RSA")
|
||||||
|
.generateKeyPair()
|
||||||
|
val signer = JcaContentSignerBuilder("SHA256WithRSAEncryption")
|
||||||
|
.build(caKeyPair.private)
|
||||||
|
|
||||||
|
val now = Date()
|
||||||
|
val crl = with(X509v2CRLBuilder(X500Name("CN=Test CA"), now)) {
|
||||||
|
addCRLEntry(certificate.serialNumber, now, CRLReason.privilegeWithdrawn)
|
||||||
|
JcaX509CRLConverter().getCRL(build(signer))
|
||||||
|
}
|
||||||
|
val data = crl.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxCRL = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showCRL = classLoader.createTaskFor(taskFactory, ShowCRL::class.java)
|
||||||
|
val result = showCRL.apply(sandboxCRL) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(ShowCRL().apply(crl).toUNIX(), result.toString())
|
||||||
|
assertThat(result::class.java.name).startsWith("sandbox.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowCRL : Function<X509CRL, String> {
|
||||||
|
override fun apply(crl: X509CRL): String {
|
||||||
|
return "X.509 CRL -> $crl"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import greymalkin.ExternalData
|
||||||
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.djvm.messages.Severity
|
||||||
|
import net.corda.serialization.djvm.SandboxType.*
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.io.NotSerializableException
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@ExtendWith(LocalSerialization::class)
|
||||||
|
class DeserializeClassTest : TestBase(KOTLIN) {
|
||||||
|
@Test
|
||||||
|
fun `test deserializing existing class`() {
|
||||||
|
val myClass = ExternalData::class.java
|
||||||
|
val data = myClass.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxInstant = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showClass = classLoader.createTaskFor(taskFactory, ShowClass::class.java)
|
||||||
|
val result = showClass.apply(sandboxInstant) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals("sandbox.${myClass.name}", result.toString())
|
||||||
|
assertEquals(SANDBOX_STRING, result::class.java.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing missing class`() {
|
||||||
|
// The DJVM will refuse to find this class because it belongs to net.corda.djvm.**.
|
||||||
|
val myClass = Severity::class.java
|
||||||
|
val data = myClass.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val ex = assertThrows<NotSerializableException>{ data.deserializeFor(classLoader) }
|
||||||
|
assertThat(ex)
|
||||||
|
.isExactlyInstanceOf(NotSerializableException::class.java)
|
||||||
|
.hasMessageContaining("Severity was not found by the node,")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowClass : Function<Class<*>, String> {
|
||||||
|
override fun apply(type: Class<*>): String {
|
||||||
|
return type.name
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
package net.corda.serialization.djvm
|
||||||
|
|
||||||
|
import greymalkin.ExternalEnum
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.core.utilities.NonEmptySet
|
||||||
|
import net.corda.serialization.djvm.SandboxType.*
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
@ExtendWith(LocalSerialization::class)
|
||||||
|
class DeserializeCollectionsTest : TestBase(KOTLIN) {
|
||||||
|
@Test
|
||||||
|
fun `test deserializing string list`() {
|
||||||
|
val stringList = StringList(listOf("Hello", "World", "!"))
|
||||||
|
val data = stringList.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxList = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showStringList = classLoader.createTaskFor(taskFactory, ShowStringList::class.java)
|
||||||
|
val result = showStringList.apply(sandboxList) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(stringList.lines.joinToString(), result.toString())
|
||||||
|
assertEquals("Hello, World, !", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowStringList : Function<StringList, String> {
|
||||||
|
override fun apply(data: StringList): String {
|
||||||
|
return data.lines.joinToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing integer set`() {
|
||||||
|
val integerSet = IntegerSet(linkedSetOf(10, 3, 15, 2, 10))
|
||||||
|
val data = integerSet.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxSet = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showIntegerSet = classLoader.createTaskFor(taskFactory, ShowIntegerSet::class.java)
|
||||||
|
val result = showIntegerSet.apply(sandboxSet) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(integerSet.numbers.joinToString(), result.toString())
|
||||||
|
assertEquals("10, 3, 15, 2", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowIntegerSet : Function<IntegerSet, String> {
|
||||||
|
override fun apply(data: IntegerSet): String {
|
||||||
|
return data.numbers.joinToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing integer sorted set`() {
|
||||||
|
val integerSortedSet = IntegerSortedSet(sortedSetOf(10, 15, 1000, 3, 2, 10))
|
||||||
|
val data = integerSortedSet.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxSet = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showIntegerSortedSet = classLoader.createTaskFor(taskFactory, ShowIntegerSortedSet::class.java)
|
||||||
|
val result = showIntegerSortedSet.apply(sandboxSet) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(integerSortedSet.numbers.joinToString(), result.toString())
|
||||||
|
assertEquals("2, 3, 10, 15, 1000", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowIntegerSortedSet : Function<IntegerSortedSet, String> {
|
||||||
|
override fun apply(data: IntegerSortedSet): String {
|
||||||
|
return data.numbers.joinToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing long navigable set`() {
|
||||||
|
val longNavigableSet = LongNavigableSet(sortedSetOf(99955L, 10, 15, 1000, 3, 2, 10))
|
||||||
|
val data = longNavigableSet.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxSet = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showLongNavigableSet = classLoader.createTaskFor(taskFactory, ShowLongNavigableSet::class.java)
|
||||||
|
val result = showLongNavigableSet.apply(sandboxSet) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(longNavigableSet.numbers.joinToString(), result.toString())
|
||||||
|
assertEquals("2, 3, 10, 15, 1000, 99955", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowLongNavigableSet : Function<LongNavigableSet, String> {
|
||||||
|
override fun apply(data: LongNavigableSet): String {
|
||||||
|
return data.numbers.joinToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing short collection`() {
|
||||||
|
val shortCollection = ShortCollection(listOf(10, 200, 3000))
|
||||||
|
val data = shortCollection.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxCollection = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showShortCollection = classLoader.createTaskFor(taskFactory, ShowShortCollection::class.java)
|
||||||
|
val result = showShortCollection.apply(sandboxCollection) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(shortCollection.numbers.joinToString(), result.toString())
|
||||||
|
assertEquals("10, 200, 3000", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowShortCollection : Function<ShortCollection, String> {
|
||||||
|
override fun apply(data: ShortCollection): String {
|
||||||
|
return data.numbers.joinToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing non-empty string set`() {
|
||||||
|
val nonEmptyStrings = NonEmptyStringSet(NonEmptySet.of("Hello", "World", "!"))
|
||||||
|
val data = nonEmptyStrings.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxSet = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showNonEmptyStringSet = classLoader.createTaskFor(taskFactory, ShowNonEmptyStringSet::class.java)
|
||||||
|
val result = showNonEmptyStringSet.apply(sandboxSet) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(nonEmptyStrings.lines.joinToString(), result.toString())
|
||||||
|
assertEquals("Hello, World, !", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowNonEmptyStringSet : Function<NonEmptyStringSet, String> {
|
||||||
|
override fun apply(data: NonEmptyStringSet): String {
|
||||||
|
return data.lines.joinToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test deserializing enum set`() {
|
||||||
|
val enumSet = HasEnumSet(EnumSet.of(ExternalEnum.DOH))
|
||||||
|
val data = enumSet.serialize()
|
||||||
|
|
||||||
|
sandbox {
|
||||||
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
|
val sandboxSet = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
|
val taskFactory = classLoader.createRawTaskFactory()
|
||||||
|
val showHasEnumSet = classLoader.createTaskFor(taskFactory, ShowHasEnumSet::class.java)
|
||||||
|
val result = showHasEnumSet.apply(sandboxSet) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
|
assertEquals(enumSet.values.toString(), result.toString())
|
||||||
|
assertEquals("[DOH]", result.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowHasEnumSet : Function<HasEnumSet, String> {
|
||||||
|
override fun apply(data: HasEnumSet): String {
|
||||||
|
return data.values.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class StringList(val lines: List<String>)
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class IntegerSet(val numbers: Set<Int>)
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class IntegerSortedSet(val numbers: SortedSet<Int>)
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class LongNavigableSet(val numbers: NavigableSet<Long>)
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class ShortCollection(val numbers: Collection<Short>)
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class NonEmptyStringSet(val lines: NonEmptySet<String>)
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
class HasEnumSet(val values: EnumSet<ExternalEnum>)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user