mirror of
https://github.com/corda/corda.git
synced 2024-12-21 22:07:55 +00:00
Merge branch 'master' into shams-master-merge-081217
This commit is contained in:
commit
e25158301f
@ -18,11 +18,11 @@ annotation class CordaSerializationTransformRenames(vararg val value: CordaSeria
|
|||||||
// TODO When we have class renaming update the docs
|
// TODO When we have class renaming update the docs
|
||||||
/**
|
/**
|
||||||
* This annotation is used to mark a class has having had a property element. It is used by the
|
* This annotation is used to mark a class has having had a property element. It is used by the
|
||||||
* AMQP deserialiser to allow instances with different versions of the class on their Class Path
|
* AMQP deserializer to allow instances with different versions of the class on their Class Path
|
||||||
* to successfully deserialize the object
|
* to successfully deserialize the object.
|
||||||
*
|
*
|
||||||
* NOTE: Renaming of the class itself is not be done with this annotation. For class renaming
|
* NOTE: Renaming of the class itself isn't done with this annotation or, at present, supported
|
||||||
* see ???
|
* by Corda
|
||||||
*
|
*
|
||||||
* @property to [String] representation of the properties new name
|
* @property to [String] representation of the properties new name
|
||||||
* @property from [String] representation of the properties old new
|
* @property from [String] representation of the properties old new
|
||||||
|
@ -2,10 +2,10 @@ package net.corda.core.serialization
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This annotation is a marker to indicate which secondary constructors should be considered, and in which
|
* This annotation is a marker to indicate which secondary constructors should be considered, and in which
|
||||||
* order, for evolving objects during their deserialisation.
|
* order, for evolving objects during their deserialization.
|
||||||
*
|
*
|
||||||
* Versions will be considered in descending order, currently duplicate versions will result in
|
* Versions will be considered in descending order, currently duplicate versions will result in
|
||||||
* non deterministic behaviour when deserialising objects
|
* non deterministic behaviour when deserializing objects
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CONSTRUCTOR)
|
@Target(AnnotationTarget.CONSTRUCTOR)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@ -3,6 +3,6 @@ package net.corda.core.serialization
|
|||||||
import net.corda.core.CordaException
|
import net.corda.core.CordaException
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
|
|
||||||
/** Thrown during deserialisation to indicate that an attachment needed to construct the [WireTransaction] is not found. */
|
/** Thrown during deserialization to indicate that an attachment needed to construct the [WireTransaction] is not found. */
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
class MissingAttachmentsException(val ids: List<SecureHash>) : CordaException()
|
class MissingAttachmentsException(val ids: List<SecureHash>) : CordaException()
|
@ -6,7 +6,7 @@ import net.corda.core.serialization.SingletonSerializationToken.Companion.single
|
|||||||
/**
|
/**
|
||||||
* The interfaces and classes in this file allow large, singleton style classes to
|
* The interfaces and classes in this file allow large, singleton style classes to
|
||||||
* mark themselves as needing converting to some form of token representation in the serialised form
|
* mark themselves as needing converting to some form of token representation in the serialised form
|
||||||
* and converting back again when deserialising.
|
* and converting back again when deserializing.
|
||||||
*
|
*
|
||||||
* Typically these classes would be used for node services and subsystems that might become reachable from
|
* Typically these classes would be used for node services and subsystems that might become reachable from
|
||||||
* Fibers and thus sucked into serialization when they are checkpointed.
|
* Fibers and thus sucked into serialization when they are checkpointed.
|
||||||
|
@ -50,7 +50,7 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
|
|||||||
@Volatile
|
@Volatile
|
||||||
@Transient private var cachedTransaction: CoreTransaction? = null
|
@Transient private var cachedTransaction: CoreTransaction? = null
|
||||||
|
|
||||||
/** Lazily calculated access to the deserialised/hashed transaction data. */
|
/** Lazily calculated access to the deserialized/hashed transaction data. */
|
||||||
private val transaction: CoreTransaction get() = cachedTransaction ?: txBits.deserialize().apply { cachedTransaction = this }
|
private val transaction: CoreTransaction get() = cachedTransaction ?: txBits.deserialize().apply { cachedTransaction = this }
|
||||||
|
|
||||||
/** The id of the contained [WireTransaction]. */
|
/** The id of the contained [WireTransaction]. */
|
||||||
|
@ -27,10 +27,8 @@ import java.util.*
|
|||||||
class CordaClassResolver(serializationContext: SerializationContext) : DefaultClassResolver() {
|
class CordaClassResolver(serializationContext: SerializationContext) : DefaultClassResolver() {
|
||||||
val whitelist: ClassWhitelist = TransientClassWhiteList(serializationContext.whitelist)
|
val whitelist: ClassWhitelist = TransientClassWhiteList(serializationContext.whitelist)
|
||||||
|
|
||||||
/*
|
// These classes are assignment-compatible Java equivalents of Kotlin classes.
|
||||||
* These classes are assignment-compatible Java equivalents of Kotlin classes.
|
// The point is that we do not want to send Kotlin types "over the wire" via RPC.
|
||||||
* The point is that we do not want to send Kotlin types "over the wire" via RPC.
|
|
||||||
*/
|
|
||||||
private val javaAliases: Map<Class<*>, Class<*>> = mapOf(
|
private val javaAliases: Map<Class<*>, Class<*>> = mapOf(
|
||||||
listOf<Any>().javaClass to Collections.emptyList<Any>().javaClass,
|
listOf<Any>().javaClass to Collections.emptyList<Any>().javaClass,
|
||||||
setOf<Any>().javaClass to Collections.emptySet<Any>().javaClass,
|
setOf<Any>().javaClass to Collections.emptySet<Any>().javaClass,
|
||||||
@ -176,7 +174,8 @@ class GlobalTransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableC
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A whitelist that can be customised via the [net.corda.core.node.SerializationWhitelist], since it implements [MutableClassWhitelist].
|
* A whitelist that can be customised via the [net.corda.core.serialization.SerializationWhitelist],
|
||||||
|
* since it implements [MutableClassWhitelist].
|
||||||
*/
|
*/
|
||||||
class TransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableClassWhitelist(Collections.synchronizedSet(mutableSetOf()), delegate)
|
class TransientClassWhiteList(delegate: ClassWhitelist) : AbstractMutableClassWhitelist(Collections.synchronizedSet(mutableSetOf()), delegate)
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ object DefaultWhitelist : SerializationWhitelist {
|
|||||||
java.time.YearMonth::class.java,
|
java.time.YearMonth::class.java,
|
||||||
java.time.MonthDay::class.java,
|
java.time.MonthDay::class.java,
|
||||||
java.time.Period::class.java,
|
java.time.Period::class.java,
|
||||||
java.time.DayOfWeek::class.java, // No custom serialiser but it's an enum.
|
java.time.DayOfWeek::class.java, // No custom serializer but it's an enum.
|
||||||
java.time.Month::class.java, // No custom serialiser but it's an enum.
|
java.time.Month::class.java, // No custom serializer but it's an enum.
|
||||||
|
|
||||||
java.util.Collections.emptyMap<Any, Any>().javaClass,
|
java.util.Collections.emptyMap<Any, Any>().javaClass,
|
||||||
java.util.Collections.emptySet<Any>().javaClass,
|
java.util.Collections.emptySet<Any>().javaClass,
|
||||||
|
@ -13,7 +13,7 @@ import org.apache.qpid.proton.amqp.UnsignedLong
|
|||||||
const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl(32 + 16)
|
const val DESCRIPTOR_TOP_32BITS: Long = 0xc562L shl(32 + 16)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AMQP desriptor ID's for our custom types.
|
* AMQP descriptor ID's for our custom types.
|
||||||
*
|
*
|
||||||
* NEVER DELETE OR CHANGE THE ID ASSOCIATED WITH A TYPE
|
* NEVER DELETE OR CHANGE THE ID ASSOCIATED WITH A TYPE
|
||||||
*
|
*
|
||||||
|
@ -21,8 +21,8 @@ open class ArraySerializer(override val type: Type, factory: SerializerFactory)
|
|||||||
// id to generate it properly (it will always return [[[Ljava.lang.type -> type[][][]
|
// id to generate it properly (it will always return [[[Ljava.lang.type -> type[][][]
|
||||||
// for example).
|
// for example).
|
||||||
//
|
//
|
||||||
// We *need* to retain knowledge for AMQP deserialisation weather that lowest primitive
|
// We *need* to retain knowledge for AMQP deserialization weather that lowest primitive
|
||||||
// was boxed or unboxed so just infer it recursively
|
// was boxed or unboxed so just infer it recursively.
|
||||||
private fun calcTypeName(type: Type): String =
|
private fun calcTypeName(type: Type): String =
|
||||||
if (type.componentType().isArray()) {
|
if (type.componentType().isArray()) {
|
||||||
val typeName = calcTypeName(type.componentType()); "$typeName[]"
|
val typeName = calcTypeName(type.componentType()); "$typeName[]"
|
||||||
|
@ -147,8 +147,8 @@ abstract class CustomSerializer<T : Any> : AMQPSerializer<T> {
|
|||||||
*
|
*
|
||||||
* @param clazz The type to be marshalled
|
* @param clazz The type to be marshalled
|
||||||
* @param withInheritance Whether subclasses of the class can also be marshalled.
|
* @param withInheritance Whether subclasses of the class can also be marshalled.
|
||||||
* @param make A lambda for constructing an instance, that defaults to calling a constructor that expects a string.
|
* @param maker A lambda for constructing an instance, that defaults to calling a constructor that expects a string.
|
||||||
* @param unmake A lambda that extracts the string value for an instance, that defaults to the [toString] method.
|
* @param unmaker A lambda that extracts the string value for an instance, that defaults to the [toString] method.
|
||||||
*/
|
*/
|
||||||
abstract class ToString<T : Any>(clazz: Class<T>, withInheritance: Boolean = false,
|
abstract class ToString<T : Any>(clazz: Class<T>, withInheritance: Boolean = false,
|
||||||
private val maker: (String) -> T = clazz.getConstructor(String::class.java).let { `constructor` ->
|
private val maker: (String) -> T = clazz.getConstructor(String::class.java).let { `constructor` ->
|
||||||
|
@ -10,8 +10,8 @@ import kotlin.reflect.full.findAnnotation
|
|||||||
import kotlin.reflect.jvm.javaType
|
import kotlin.reflect.jvm.javaType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializer for deserialising objects whose definition has changed since they
|
* Serializer for deserializing objects whose definition has changed since they
|
||||||
* were serialised
|
* were serialised.
|
||||||
*/
|
*/
|
||||||
class EvolutionSerializer(
|
class EvolutionSerializer(
|
||||||
clazz: Type,
|
clazz: Type,
|
||||||
@ -38,16 +38,16 @@ class EvolutionSerializer(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* Unlike the generic deserialisation case where we need to locate the primary constructor
|
* Unlike the generic deserialization case where we need to locate the primary constructor
|
||||||
* for the object (or our best guess) in the case of an object whose structure has changed
|
* for the object (or our best guess) in the case of an object whose structure has changed
|
||||||
* since serialisation we need to attempt to locate a constructor that we can use. I.e.
|
* since serialisation we need to attempt to locate a constructor that we can use. For example,
|
||||||
* it's parameters match the serialised members and it will initialise any newly added
|
* its parameters match the serialised members and it will initialise any newly added
|
||||||
* elements
|
* elements.
|
||||||
*
|
*
|
||||||
* TODO: Type evolution
|
* TODO: Type evolution
|
||||||
* TODO: rename annotation
|
* TODO: rename annotation
|
||||||
*/
|
*/
|
||||||
internal fun getEvolverConstructor(type: Type, oldArgs: Map<String?, Type>): KFunction<Any>? {
|
private fun getEvolverConstructor(type: Type, oldArgs: Map<String?, Type>): KFunction<Any>? {
|
||||||
val clazz: Class<*> = type.asClass()!!
|
val clazz: Class<*> = type.asClass()!!
|
||||||
if (!isConcrete(clazz)) return null
|
if (!isConcrete(clazz)) return null
|
||||||
|
|
||||||
@ -70,13 +70,15 @@ class EvolutionSerializer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a serialization object for deserialisation only of objects serialised
|
* Build a serialization object for deserialization only of objects serialised
|
||||||
* as different versions of a class
|
* as different versions of a class.
|
||||||
*
|
*
|
||||||
* @param old is an object holding the schema that represents the object
|
* @param old is an object holding the schema that represents the object
|
||||||
* as it was serialised and the type descriptor of that type
|
* as it was serialised and the type descriptor of that type
|
||||||
* @param new is the Serializer built for the Class as it exists now, not
|
* @param new is the Serializer built for the Class as it exists now, not
|
||||||
* how it was serialised and persisted.
|
* how it was serialised and persisted.
|
||||||
|
* @param factory the [SerializerFactory] associated with the serialization
|
||||||
|
* context this serializer is being built for
|
||||||
*/
|
*/
|
||||||
fun make(old: CompositeType, new: ObjectSerializer,
|
fun make(old: CompositeType, new: ObjectSerializer,
|
||||||
factory: SerializerFactory): AMQPSerializer<Any> {
|
factory: SerializerFactory): AMQPSerializer<Any> {
|
||||||
@ -117,7 +119,7 @@ class EvolutionSerializer(
|
|||||||
* to the object list of values we need to map that list, which is ordered per the
|
* to the object list of values we need to map that list, which is ordered per the
|
||||||
* constructor of the original state of the object, we need to map the new parameter order
|
* constructor of the original state of the object, we need to map the new parameter order
|
||||||
* of the current constructor onto that list inserting nulls where new parameters are
|
* of the current constructor onto that list inserting nulls where new parameters are
|
||||||
* encountered
|
* encountered.
|
||||||
*
|
*
|
||||||
* TODO: Object references
|
* TODO: Object references
|
||||||
*/
|
*/
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.nodeapi.internal.serialization.amqp.CompositeType
|
|||||||
import net.corda.nodeapi.internal.serialization.amqp.RestrictedType
|
import net.corda.nodeapi.internal.serialization.amqp.RestrictedType
|
||||||
import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField
|
import net.corda.nodeapi.internal.serialization.amqp.Field as AMQPField
|
||||||
import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema
|
import net.corda.nodeapi.internal.serialization.amqp.Schema as AMQPSchema
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
|
||||||
fun AMQPSchema.carpenterSchema(classloader: ClassLoader): CarpenterMetaSchema {
|
fun AMQPSchema.carpenterSchema(classloader: ClassLoader): CarpenterMetaSchema {
|
||||||
val rtn = CarpenterMetaSchema.newInstance()
|
val rtn = CarpenterMetaSchema.newInstance()
|
||||||
@ -34,7 +35,7 @@ fun AMQPField.typeAsString() = if (type == "*") requires[0] else type
|
|||||||
* b) add the class to the dependency tree in [carpenterSchemas] if it cannot be instantiated
|
* b) add the class to the dependency tree in [carpenterSchemas] if it cannot be instantiated
|
||||||
* at this time
|
* at this time
|
||||||
*
|
*
|
||||||
* @param classloader the class loader provided dby the [SerializationContext]
|
* @param classloader the class loader provided by the [SerializationContext]
|
||||||
* @param carpenterSchemas structure that holds the dependency tree and list of classes that
|
* @param carpenterSchemas structure that holds the dependency tree and list of classes that
|
||||||
* need constructing
|
* need constructing
|
||||||
* @param force by default a schema is not added to [carpenterSchemas] if it already exists
|
* @param force by default a schema is not added to [carpenterSchemas] if it already exists
|
||||||
|
@ -9,7 +9,7 @@ enum class SchemaFlags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Schema is the representation of an object the Carpenter can contsruct
|
* A Schema is the representation of an object the Carpenter can construct
|
||||||
*
|
*
|
||||||
* Known Sub Classes
|
* Known Sub Classes
|
||||||
* - [ClassSchema]
|
* - [ClassSchema]
|
||||||
@ -62,7 +62,7 @@ fun EnumMap<SchemaFlags, Boolean>.simpleFieldAccess(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a concrete object
|
* Represents a concrete object.
|
||||||
*/
|
*/
|
||||||
class ClassSchema(
|
class ClassSchema(
|
||||||
name: String,
|
name: String,
|
||||||
@ -77,7 +77,7 @@ class ClassSchema(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an interface. Carpented interfaces can be used within [ClassSchema]s
|
* Represents an interface. Carpented interfaces can be used within [ClassSchema]s
|
||||||
* if that class should be implementing that interface
|
* if that class should be implementing that interface.
|
||||||
*/
|
*/
|
||||||
class InterfaceSchema(
|
class InterfaceSchema(
|
||||||
name: String,
|
name: String,
|
||||||
@ -91,7 +91,7 @@ class InterfaceSchema(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an enumerated type
|
* Represents an enumerated type.
|
||||||
*/
|
*/
|
||||||
class EnumSchema(
|
class EnumSchema(
|
||||||
name: String,
|
name: String,
|
||||||
@ -111,8 +111,8 @@ class EnumSchema(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory object used by the serialiser when building [Schema]s based
|
* Factory object used by the serializer when building [Schema]s based
|
||||||
* on an AMQP schema
|
* on an AMQP schema.
|
||||||
*/
|
*/
|
||||||
object CarpenterSchemaFactory {
|
object CarpenterSchemaFactory {
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
|
Loading…
Reference in New Issue
Block a user