From 0d0a6d7966da1247dd9698b6539ceb95445a60b4 Mon Sep 17 00:00:00 2001 From: Katelyn Baker Date: Wed, 12 Jul 2017 17:53:21 +0100 Subject: [PATCH] Fix toString generated method that breaks Introspection for BEANS Pass signature as null, not empty string, otherwise the class asm isn't correct. Using javap at the command line prior to the fix yields public class MyClass implements net.corda.core.serialization.carpenter.SimpleFieldAccess { protected final java.lang.Integer a; descriptor: Ljava/lang/Integer; public MyClass(java.lang.Integer); descriptor: (Ljava/lang/Integer;)V public java.lang.Integer getA(); descriptor: ()Ljava/lang/Integer; public java.lang.Object get(java.lang.String); descriptor: (Ljava/lang/String;)Ljava/lang/Object; Error: A serious internal error has occurred: java.lang.StringIndexOutOfBoundsException: String index out of range: 0 --- .../serialization/carpenter/ClassCarpenter.kt | 4 ++-- .../carpenter/ClassCarpenterTest.kt | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 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 5d774df240..5f0f1abd99 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 @@ -216,7 +216,7 @@ class ClassCarpenter { * Generate bytecode for the given schema and load into the JVM. The returned class object can be used to * construct instances of the generated class. * - * @throws DuplicateName if the schema's name is already taken in this namespace (you can create a new ClassCarpenter if you're OK with ambiguous names) + * @throws DuplicateNameException if the schema's name is already taken in this namespace (you can create a new ClassCarpenter if you're OK with ambiguous names) */ fun build(schema: Schema): Class<*> { validateSchema(schema) @@ -291,7 +291,7 @@ class ClassCarpenter { private fun ClassWriter.generateToString(schema: Schema) { val toStringHelper = "com/google/common/base/MoreObjects\$ToStringHelper" - with(visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", "", null)) { + with(visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null)) { visitCode() // com.google.common.base.MoreObjects.toStringHelper("TypeName") visitLdcInsn(schema.name.split('.').last()) diff --git a/core/src/test/kotlin/net/corda/core/serialization/carpenter/ClassCarpenterTest.kt b/core/src/test/kotlin/net/corda/core/serialization/carpenter/ClassCarpenterTest.kt index 6dc4f5b12a..020d907e5f 100644 --- a/core/src/test/kotlin/net/corda/core/serialization/carpenter/ClassCarpenterTest.kt +++ b/core/src/test/kotlin/net/corda/core/serialization/carpenter/ClassCarpenterTest.kt @@ -1,12 +1,11 @@ package net.corda.core.serialization.carpenter - import org.junit.Test import java.lang.reflect.Field import java.lang.reflect.Method import kotlin.test.assertEquals -import kotlin.test.assertTrue - +import java.beans.Introspector +import kotlin.test.assertNotEquals class ClassCarpenterTest { interface DummyInterface { @@ -491,4 +490,17 @@ class ClassCarpenterTest { assertEquals (javax.annotation.Nonnull::class.java, clazz.getMethod("getB").annotations[0].annotationClass.java) } + @Test + fun beanTest() { + val schema = ClassCarpenter.ClassSchema( + "pantsPantsPants", + mapOf("a" to ClassCarpenter.NonNullableField(Integer::class.java))) + val clazz = cc.build(schema) + val descriptors = Introspector.getBeanInfo(clazz).propertyDescriptors + + assertEquals(2, descriptors.size) + assertNotEquals(null, descriptors.find { it.name == "a" }) + assertNotEquals(null, descriptors.find { it.name == "class" }) + } + }