de.jodamob.kotlin.testrunner.NoMoreFinalsClassLoader.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-testrunner Show documentation
Show all versions of kotlin-testrunner Show documentation
Junit testrunner that removes final from classes and methods
The newest version!
package de.jodamob.kotlin.testrunner
import javassist.ClassPool
import javassist.CtClass
import javassist.LoaderClassPath
import javassist.Modifier
import java.lang.reflect.Modifier as ReflectModifier
class NoMoreFinalsClassLoader : ClassLoader {
val filter = arrayListOf("java.","javax.", "com.google.", "android.", "org.junit.", "org.mockito", "junit.", "kotlin.")
val pool = ClassPool(false)
constructor() {
pool.appendClassPath(LoaderClassPath(this))
pool.appendSystemPath()
}
@Throws(ClassNotFoundException::class)
override fun loadClass(name: String): Class<*> {
filter.forEach { if (name.startsWith(it)) return super.loadClass(name) }
return process>(name, this)
}
@Suppress("UNCHECKED_CAST")
@Throws(Exception::class)
fun process(className: String, classLoader: NoMoreFinalsClassLoader): Class {
println("Processing class: " + className)
val defaultClass = pool.get(className)
if (isPublicOrFinalOrIrrelvant(className, defaultClass)) {
return defaultClass.toClass(classLoader) as Class
}
return removeFinal(defaultClass, classLoader) as Class
}
private fun isPublicOrFinalOrIrrelvant(className: String, defaultClass: CtClass): Boolean {
return className.endsWith("Test") || className.endsWith("TestRunner") ||
ReflectModifier.isStatic(defaultClass.modifiers) ||
!ReflectModifier.isPublic(defaultClass.modifiers) ||
!ReflectModifier.isFinal(defaultClass.modifiers)
}
fun removeFinal(clazz: CtClass, classLoader: NoMoreFinalsClassLoader): Class<*>? {
removeFinalOnClass(clazz)
removeFinalOnMethods(clazz)
clazz.stopPruning(true)
return clazz.toClass(classLoader)
}
private fun removeFinalOnMethods(clazz: CtClass) {
clazz.declaredMethods.forEach {
if (ReflectModifier.isPublic(it.modifiers) && ReflectModifier.isFinal(it.modifiers)) {
it.modifiers = Modifier.clear(it.modifiers, java.lang.reflect.Modifier.FINAL)
}
}
}
private fun removeFinalOnClass(clazz: CtClass) {
val modifiers = clazz.modifiers
if (ReflectModifier.isFinal(modifiers)) {
clazz.modifiers = Modifier.clear(modifiers, java.lang.reflect.Modifier.FINAL)
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy