From 337ccd47b5611a2ea99e32554ba6a06416864170 Mon Sep 17 00:00:00 2001
From: Katelyn Baker <katelyn.baker@r3.com>
Date: Thu, 27 Jul 2017 12:13:47 +0100
Subject: [PATCH] Don't blindly add SimpleFieldAccess as interface to carpented
 classes

This fix really only applies to the testing case where, to test the
carpenter as it integrates with the deserialzer we need classes not
found on the class path. To do this they can be created by a second
class carpenter

However, the original carpenter *always* added SimpleFieldAccess as an
interface to the class it would be creating. Under normal circumstances
that's fine as that interface wouldn't be in the list of interfaces
given to the carpenter for the class it's being asked to created.
However, if as described above the carpenter schema was synthesised from
a class that was carpented it will.

If this happens we get an error as understandably you can't have a
duplicate interface.

Fix is to simply check weather the list of interfaces the schema
describes and only add SimpleFieldAccess if it isn't on it
---
 .../core/serialization/carpenter/ClassCarpenter.kt    | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/core/src/main/kotlin/net/corda/core/serialization/carpenter/ClassCarpenter.kt b/core/src/main/kotlin/net/corda/core/serialization/carpenter/ClassCarpenter.kt
index 03361446d2..8a1b9896e1 100644
--- a/core/src/main/kotlin/net/corda/core/serialization/carpenter/ClassCarpenter.kt
+++ b/core/src/main/kotlin/net/corda/core/serialization/carpenter/ClassCarpenter.kt
@@ -129,10 +129,12 @@ class ClassCarpenter {
     private fun generateClass(classSchema: Schema): Class<*> {
         return generate(classSchema) { cw, schema ->
             val superName = schema.superclass?.jvmName ?: "java/lang/Object"
-            val interfaces = arrayOf(SimpleFieldAccess::class.java.name.jvm) + schema.interfaces.map { it.name.jvm }
+            var interfaces = schema.interfaces.map { it.name.jvm }.toMutableList()
+
+            if (SimpleFieldAccess::class.java !in schema.interfaces) interfaces.add(SimpleFieldAccess::class.java.name.jvm)
 
             with(cw) {
-                visit(V1_8, ACC_PUBLIC + ACC_SUPER, schema.jvmName, null, superName, interfaces)
+                visit(V1_8, ACC_PUBLIC + ACC_SUPER, schema.jvmName, null, superName, interfaces.toTypedArray())
 
                 generateFields(schema)
                 generateConstructor(schema)
@@ -304,6 +306,11 @@ class ClassCarpenter {
                             + "with 'get': ${itf.name}.${it.name}")
                 }
 
+                // if we're trying to carpent a class that prior to serialisation / deserialisation
+                // was made by a carpenter then we can ignore this (it will implement a plain get
+                // method from SimpleFieldAccess)
+                if (fieldNameFromItf.isEmpty() && SimpleFieldAccess::class.java in schema.interfaces) return@forEach
+
                 if ((schema is ClassSchema) and (fieldNameFromItf !in allFields))
                     throw InterfaceMismatchException(
                             "Interface ${itf.name} requires a field named $fieldNameFromItf but that "