mirror of
https://github.com/corda/corda.git
synced 2025-04-16 07:27:17 +00:00
Some custom serializers, fixes to generics handling, some annotations and added NonEmptySet as a special case of Set. (#1330)
This commit is contained in:
parent
34b7c89b40
commit
c61b036844
@ -11,9 +11,9 @@ import java.security.SignatureException
|
||||
// should be renamed to match.
|
||||
/** A wrapper around a digital signature. */
|
||||
@CordaSerializable
|
||||
open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
open class DigitalSignature(bytes: ByteArray) : OpaqueBytes(bytes) {
|
||||
/** A digital signature that identifies who the public key is owned by. */
|
||||
open class WithKey(val by: PublicKey, bits: ByteArray) : DigitalSignature(bits) {
|
||||
open class WithKey(val by: PublicKey, bytes: ByteArray) : DigitalSignature(bytes) {
|
||||
/**
|
||||
* Utility to simplify the act of verifying a signature.
|
||||
*
|
||||
|
@ -1,7 +1,10 @@
|
||||
package net.corda.core.messaging
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
|
||||
|
||||
/** The interface for a group of message recipients (which may contain only one recipient) */
|
||||
@CordaSerializable
|
||||
interface MessageRecipients
|
||||
|
||||
/** A base class for the case of point-to-point messages */
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.core.utilities
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
@ -7,6 +8,7 @@ import java.net.URI
|
||||
* @param host a hostname or IP address. IPv6 addresses must not be enclosed in square brackets.
|
||||
* @param port a valid port number.
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class NetworkHostAndPort(val host: String, val port: Int) {
|
||||
companion object {
|
||||
internal val invalidPortFormat = "Invalid port: %s"
|
||||
|
@ -37,6 +37,8 @@ abstract class AbstractAMQPSerializationScheme : SerializationScheme {
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.MonthDaySerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PeriodSerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.ClassSerializer(this))
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateHolderSerializer)
|
||||
register(net.corda.nodeapi.internal.serialization.amqp.custom.PartyAndCertificateSerializer(factory))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.utilities.NonEmptySet
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.ParameterizedType
|
||||
@ -22,7 +23,8 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
|
||||
List::class.java to { list -> Collections.unmodifiableList(list) },
|
||||
Set::class.java to { list -> Collections.unmodifiableSet(LinkedHashSet(list)) },
|
||||
SortedSet::class.java to { list -> Collections.unmodifiableSortedSet(TreeSet(list)) },
|
||||
NavigableSet::class.java to { list -> Collections.unmodifiableNavigableSet(TreeSet(list)) }
|
||||
NavigableSet::class.java to { list -> Collections.unmodifiableNavigableSet(TreeSet(list)) },
|
||||
NonEmptySet::class.java to { list -> NonEmptySet.copyOf(list) }
|
||||
)
|
||||
|
||||
private fun findConcreteType(clazz: Class<*>): (List<*>) -> Collection<*> {
|
||||
|
@ -373,7 +373,7 @@ private fun fingerprintForType(type: Type, contextType: Type?, alreadySeen: Muta
|
||||
// to the CorDapp but maybe reference to the JAR in the short term.
|
||||
hasher.putUnencodedChars(type.name)
|
||||
} else {
|
||||
fingerprintForObject(type, contextType, alreadySeen, hasher, factory)
|
||||
fingerprintForObject(type, type, alreadySeen, hasher, factory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ private fun <T : Any> propertiesForSerializationFromConstructor(kotlinConstructo
|
||||
val getter = matchingProperty.readMethod ?: throw NotSerializableException("Property has no getter method for $name of $clazz." +
|
||||
" If using Java and the parameter name looks anonymous, check that you have the -parameters option specified in the Java compiler.")
|
||||
val returnType = resolveTypeVariables(getter.genericReturnType, type)
|
||||
if (constructorParamTakesReturnTypeOfGetter(getter, param)) {
|
||||
if (constructorParamTakesReturnTypeOfGetter(returnType, getter.genericReturnType, param)) {
|
||||
rc += PropertySerializer.make(name, getter, returnType, factory)
|
||||
} else {
|
||||
throw NotSerializableException("Property type $returnType for $name of $clazz differs from constructor parameter type ${param.type.javaType}")
|
||||
@ -90,7 +90,10 @@ private fun <T : Any> propertiesForSerializationFromConstructor(kotlinConstructo
|
||||
return rc
|
||||
}
|
||||
|
||||
private fun constructorParamTakesReturnTypeOfGetter(getter: Method, param: KParameter): Boolean = TypeToken.of(param.type.javaType).isSupertypeOf(getter.genericReturnType)
|
||||
private fun constructorParamTakesReturnTypeOfGetter(getterReturnType: Type, rawGetterReturnType: Type, param: KParameter): Boolean {
|
||||
val typeToken = TypeToken.of(param.type.javaType)
|
||||
return typeToken.isSupertypeOf(getterReturnType) || typeToken.isSupertypeOf(rawGetterReturnType)
|
||||
}
|
||||
|
||||
private fun propertiesForSerializationFromAbstract(clazz: Class<*>, type: Type, factory: SerializerFactory): Collection<PropertySerializer> {
|
||||
// Kotlin reflection doesn't work with Java getters the way you might expect, so we drop back to good ol' beans.
|
||||
|
@ -0,0 +1,30 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.NotSerializableException
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.CertificateFactory
|
||||
|
||||
/**
|
||||
* A serializer that writes out a party and certificate in encoded format.
|
||||
*/
|
||||
class PartyAndCertificateSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<PartyAndCertificate, PartyAndCertificateSerializer.PartyAndCertificateProxy>(PartyAndCertificate::class.java, PartyAndCertificateProxy::class.java, factory) {
|
||||
override fun toProxy(obj: PartyAndCertificate): PartyAndCertificateProxy = PartyAndCertificateProxy(obj.certPath.type, obj.certPath.encoded)
|
||||
|
||||
override fun fromProxy(proxy: PartyAndCertificateProxy): PartyAndCertificate {
|
||||
try {
|
||||
val cf = CertificateFactory.getInstance(proxy.type)
|
||||
return PartyAndCertificate(cf.generateCertPath(ByteArrayInputStream(proxy.encoded)))
|
||||
} catch (ce: CertificateException) {
|
||||
val nse = NotSerializableException("java.security.cert.CertPath: " + type)
|
||||
nse.initCause(ce)
|
||||
throw nse
|
||||
}
|
||||
}
|
||||
|
||||
data class PartyAndCertificateProxy(val type: String, val encoded: ByteArray)
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* A serializer that writes out a certificate in X.509 format.
|
||||
*/
|
||||
object X509CertificateHolderSerializer : CustomSerializer.Implements<X509CertificateHolder>(X509CertificateHolder::class.java) {
|
||||
override val schemaForDocumentation = Schema(listOf(RestrictedType(type.toString(), "", listOf(type.toString()), SerializerFactory.primitiveTypeName(ByteArray::class.java)!!, descriptor, emptyList())))
|
||||
|
||||
override fun writeDescribedObject(obj: X509CertificateHolder, data: Data, type: Type, output: SerializationOutput) {
|
||||
output.writeObject(obj.encoded, data, clazz)
|
||||
}
|
||||
|
||||
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X509CertificateHolder {
|
||||
val bits = input.readObject(obj, schema, ByteArray::class.java) as ByteArray
|
||||
return X509CertificateHolder(bits)
|
||||
}
|
||||
}
|
@ -15,11 +15,13 @@ import net.corda.nodeapi.internal.serialization.AbstractAMQPSerializationScheme
|
||||
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||
import net.corda.testing.BOB_IDENTITY
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.MEGA_CORP_PUBKEY
|
||||
import org.apache.qpid.proton.amqp.*
|
||||
import org.apache.qpid.proton.codec.DecoderImpl
|
||||
import org.apache.qpid.proton.codec.EncoderImpl
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.IOException
|
||||
import java.io.NotSerializableException
|
||||
@ -710,6 +712,48 @@ class SerializationOutputTests {
|
||||
serdes(obj, factory, factory2)
|
||||
}
|
||||
|
||||
// TODO: ignored due to Proton-J bug https://issues.apache.org/jira/browse/PROTON-1551
|
||||
@Ignore
|
||||
@Test
|
||||
fun `test certificate holder serialize`() {
|
||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateHolderSerializer)
|
||||
|
||||
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.X509CertificateHolderSerializer)
|
||||
|
||||
val obj = BOB_IDENTITY.certificate
|
||||
serdes(obj, factory, factory2)
|
||||
}
|
||||
|
||||
// TODO: ignored due to Proton-J bug https://issues.apache.org/jira/browse/PROTON-1551
|
||||
@Ignore
|
||||
@Test
|
||||
fun `test party and certificate serialize`() {
|
||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory.register(net.corda.nodeapi.internal.serialization.amqp.custom.PartyAndCertificateSerializer(factory))
|
||||
|
||||
val factory2 = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
factory2.register(net.corda.nodeapi.internal.serialization.amqp.custom.PartyAndCertificateSerializer(factory2))
|
||||
|
||||
val obj = BOB_IDENTITY
|
||||
serdes(obj, factory, factory2)
|
||||
}
|
||||
|
||||
class OtherGeneric<T : Any>
|
||||
|
||||
open class GenericSuperclass<T : Any>(val param: OtherGeneric<T>)
|
||||
|
||||
class GenericSubclass(param: OtherGeneric<String>) : GenericSuperclass<String>(param) {
|
||||
override fun equals(other: Any?): Boolean = other is GenericSubclass // This is a bit lame but we just want to check it doesn't throw exceptions
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test generic in constructor serialize`() {
|
||||
val obj = GenericSubclass(OtherGeneric<String>())
|
||||
serdes(obj)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test StateRef serialize`() {
|
||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
|
Loading…
x
Reference in New Issue
Block a user