dimanche 2 juillet 2023

Enumerate classes within packages and jars in Kotlin

I have a project in Kotlin with two modules (ProjectName.ModuleA and ProjectName.ModuleB). Within these modules I have a package (com.company.projectName.moduleA and com.company.projectName.moduleB). Module B references Module A.

In ModuleA I have a library that defines an interface (called Flag). This interfaces has implementations in ModuleA and ModuleB. I'm now writing tests for ModuleB.

The thing is that I'd like a function in ModuleA (the main library) that loads all the classes that implement the Flag interface. What I'm expecting is that, when I run the tests of ModuleA only the ModuleA implementations are loaded, but when I run the tests of ModuleB, both ModuleA and ModuleB implementations are loaded, because when I use this library in the "real world" I will like to load all the implementations that exist in the libraries referenced.

I have this code, but this code only loads the classes of the current package.

private fun findFlags(packageName: String) {
    // Translate the package name into an absolute path
    var name = packageName
    if (!name.startsWith("/")) {
        name = "/$name"
    }
    name = name.replace('.', '/')
    // Get a File object for the package
    val url: URL = SimplyTheFlag::class.java.getResource(name)
    val directory = File(url.file)

    if (directory.exists()) {
        // Get the list of the files contained in the package
        directory.walk()
            .filter { f -> f.isFile && !f.name.contains('$') && f.name.endsWith(".class") }
            .forEach { it ->
                val className = it.canonicalPath.removePrefix(directory.canonicalPath)
                    .dropLast(6) // remove .class
                    .drop(1) // drop initial .
                    .replace('/', '.')
                val fullyQualifiedClassName = "$packageName.$className"

                val isFlag = Class.forName(fullyQualifiedClassName).interfaces.any { i -> i.simpleName == Flag::class.java.simpleName }
                if (isFlag) {
                    availableFlags[className] = fullyQualifiedClassName
                }
            }
    }
}

How can I implement this?





Aucun commentaire:

Enregistrer un commentaire