forked from mockk/mockk
/
OnjenesisInstantiator.kt
48 lines (40 loc) · 1.55 KB
/
OnjenesisInstantiator.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@file:Suppress("UNCHECKED_CAST")
package io.mockk.proxy.android
import com.android.dx.stock.ProxyBuilder
import io.mockk.proxy.MockKAgentLogger
import io.mockk.proxy.MockKInstantiatior
import org.objenesis.ObjenesisStd
import org.objenesis.instantiator.ObjectInstantiator
import java.lang.reflect.Modifier
import java.util.*
internal class OnjenesisInstantiator(val log: MockKAgentLogger) : MockKInstantiatior {
private val objenesis = ObjenesisStd(false)
private val instantiators = Collections.synchronizedMap(WeakHashMap<Class<*>, ObjectInstantiator<*>>())
override fun <T : Any> instance(cls: Class<T>): T {
val clazz = proxyInterface(cls)
log.trace("Creating new empty instance of $clazz")
val inst = synchronized(instantiators) {
instantiators.getOrPut(clazz) {
objenesis.getInstantiatorOf(clazz)
}
}
val newInstance = inst.newInstance()
return clazz.cast(newInstance) as T
}
@Suppress("UNCHECKED_CAST")
private fun <T> proxyInterface(clazz: Class<T>) =
if (Modifier.isAbstract(clazz.modifiers)) {
if (clazz.isInterface) {
ProxyBuilder.forClass(Any::class.java)
.parentClassLoader(clazz.classLoader)
.implementing(clazz)
.buildProxyClass()
} else {
ProxyBuilder.forClass(clazz)
.parentClassLoader(clazz.classLoader)
.buildProxyClass()
}
} else {
clazz
}
}