Skip to content

Fix ReflectionCache to be serializable #634

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMember
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod
import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams
import com.fasterxml.jackson.databind.util.LRUMap
import java.io.Serializable
import java.lang.reflect.Constructor
import java.lang.reflect.Executable
import java.lang.reflect.Method
import kotlin.reflect.KFunction
import kotlin.reflect.jvm.kotlinFunction

internal class ReflectionCache(reflectionCacheSize: Int) {
internal class ReflectionCache(reflectionCacheSize: Int) : Serializable {
companion object {
// Increment is required when properties that use LRUMap are changed.
private const val serialVersionUID = 1L
}

sealed class BooleanTriState(val value: Boolean?) {
class True : BooleanTriState(true)
class False : BooleanTriState(false)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.fasterxml.jackson.module.kotlin

import junit.framework.TestCase
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream

fun jdkSerialize(o: Any): ByteArray {
val bytes = ByteArrayOutputStream(1000)
val obOut = ObjectOutputStream(bytes)
obOut.writeObject(o)
obOut.close()
return bytes.toByteArray()
}

fun <T> jdkDeserialize(raw: ByteArray): T? {
val objIn = ObjectInputStream(ByteArrayInputStream(raw))
return try {
@Suppress("UNCHECKED_CAST")
objIn.readObject() as T
} catch (e: ClassNotFoundException) {
TestCase.fail("Missing class: " + e.message)
null
} finally {
objIn.close()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import kotlin.test.assertNotNull

class KotlinModuleTest {
/**
Expand Down Expand Up @@ -103,4 +104,27 @@ class KotlinModuleTest {

assertTrue(module.strictNullChecks)
}

@Test
fun jdkSerializabilityTest() {
val module = KotlinModule.Builder().apply {
withReflectionCacheSize(123)
enable(NullToEmptyCollection)
enable(NullToEmptyMap)
enable(NullIsSameAsDefault)
enable(SingletonSupport)
enable(StrictNullChecks)
}.build()

val serialized = jdkSerialize(module)
val deserialized = jdkDeserialize<KotlinModule>(serialized)

assertNotNull(deserialized)
assertEquals(123, deserialized.reflectionCacheSize)
assertTrue(deserialized.nullToEmptyCollection)
assertTrue(deserialized.nullToEmptyMap)
assertTrue(deserialized.nullIsSameAsDefault)
assertEquals(CANONICALIZE, deserialized.singletonSupport)
assertTrue(deserialized.strictNullChecks)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.fasterxml.jackson.module.kotlin

import org.junit.Test
import kotlin.test.assertNotNull

class ReflectionCacheTest {
@Test
fun serializeEmptyCache() {
val cache = ReflectionCache(100)
val serialized = jdkSerialize(cache)
val deserialized = jdkDeserialize<ReflectionCache>(serialized)

assertNotNull(deserialized)
// Deserialized instance also do not raise exceptions
deserialized.kotlinFromJava(ReflectionCacheTest::class.java.getDeclaredMethod("serializeEmptyCache"))
}

@Test
fun serializeNotEmptyCache() {
val method = ReflectionCacheTest::class.java.getDeclaredMethod("serializeNotEmptyCache")

val cache = ReflectionCache(100).apply { kotlinFromJava(method) }
val serialized = jdkSerialize(cache)
val deserialized = jdkDeserialize<ReflectionCache>(serialized)

assertNotNull(deserialized)
// Deserialized instance also do not raise exceptions
deserialized.kotlinFromJava(method)
}
}