Merge remote-tracking branch 'remote-djvm/chrisr3-djvm-serialization' into chrisr3-djvm-integration

This commit is contained in:
Chris Rankin 2019-10-22 14:31:56 +01:00
commit 833ea3d40b
137 changed files with 5544 additions and 11 deletions

View File

@ -483,6 +483,7 @@ bintrayConfig {
'corda-core',
'corda-core-deterministic',
'corda-deterministic-verifier',
'corda-deserializers-djvm',
'corda',
'corda-finance-workflows',
'corda-finance-contracts',
@ -501,6 +502,7 @@ bintrayConfig {
'corda-tools-shell-cli',
'corda-serialization',
'corda-serialization-deterministic',
'corda-serialization-djvm',
'corda-tools-blob-inspector',
'corda-tools-explorer',
'corda-tools-network-bootstrapper',

View File

@ -170,21 +170,15 @@ dependencies {
// Sandbox for deterministic contract verification
compile "net.corda.djvm:corda-djvm:$djvm_version"
compile("net.corda.djvm:corda-djvm-serialization:$djvm_version") {
exclude group: 'net.corda'
}
compile project(':serialization-djvm')
compile(project(':node:djvm')) {
transitive = false
}
jdkRt "net.corda:deterministic-rt:latest.integration"
deterministic project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
deterministic project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
deterministic("net.corda.djvm:corda-djvm-deserializers:$djvm_version") {
transitive = false
}
deterministic(project(':node:djvm')) {
transitive = false
}
deterministic project(':serialization-djvm:deserializers')
deterministic project(':node:djvm')
deterministic "org.slf4j:slf4j-nop:$slf4j_version"
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"

View File

@ -13,6 +13,10 @@ dependencies {
jar {
archiveBaseName = 'corda-node-djvm'
manifest {
attributes('Automatic-Module-Name': 'net.corda.node.djvm')
attributes('Sealed': true)
}
}
publish {

View File

@ -7,9 +7,9 @@ import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.serialize
import net.corda.core.utilities.ByteSequence
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.serialization.djvm.createSandboxSerializationEnv
import net.corda.serialization.djvm.deserializeTo
import java.util.function.Function
class Serializer(private val classLoader: SandboxClassLoader) {

View 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
}
}

View 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
}
}

View File

@ -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)
}
}

View File

@ -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())
}
}

View File

@ -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)
}
}

View File

@ -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)!!
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)!!
}
}

View File

@ -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])
}
}

View File

@ -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])
}
}

View File

@ -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])
}
}

View File

@ -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
}
}

View File

@ -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())
}
}

View File

@ -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))
}
}
}

View File

@ -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)
}
}

View File

@ -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())
}
}

View File

@ -0,0 +1,6 @@
package net.corda.serialization.djvm.deserializers
@Suppress("unused")
enum class JustForCasting {
UNUSED
}

View File

@ -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())
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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())
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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])
}
}

View File

@ -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])
}
}

View File

@ -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])
}
}

View File

@ -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])
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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())
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)!!
}
}

View File

@ -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!")

View File

@ -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()
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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()
}
}

View File

@ -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)
)
}
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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)!!
}
}

View File

@ -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()
}
}

View File

@ -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)!!
}
}

View File

@ -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()
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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()
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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)!!
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,11 @@
package greymalkin;
import net.corda.core.serialization.CordaSerializable;
@SuppressWarnings("unused")
@CordaSerializable
public enum ExternalEnum {
DOH,
RAY,
ME
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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()
}
}
}

View File

@ -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"
}
}
}

View File

@ -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
}
}

View File

@ -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