117 lines
4.1 KiB
Kotlin
117 lines
4.1 KiB
Kotlin
package dorkbox.gradleVaadin
|
|
|
|
import java.io.File
|
|
import java.net.URL
|
|
|
|
class CustomClassFinder(classPath: List<File>, projectDependencies: List<File>) : com.vaadin.flow.server.frontend.scanner.ClassFinder {
|
|
// Find everything annotated with the following
|
|
// Route.class, NpmPackage.class, NpmPackage.Container.class, WebComponentExporter.class, UIInitListener.class, VaadinServiceInitListener.class
|
|
|
|
// scans compiled files (NOT SOURCE FILES!)
|
|
// make sure to close this!
|
|
private val classPathScanResult = io.github.classgraph.ClassGraph()
|
|
.overrideClasspath(classPath)
|
|
.enableSystemJarsAndModules()
|
|
.enableInterClassDependencies()
|
|
.enableExternalClasses()
|
|
.enableAllInfo()
|
|
.scan()
|
|
|
|
private val dependencyScanResult = io.github.classgraph.ClassGraph()
|
|
.overrideClasspath(projectDependencies)
|
|
.enableSystemJarsAndModules()
|
|
.enableInterClassDependencies()
|
|
.enableExternalClasses()
|
|
.enableAllInfo()
|
|
.scan()
|
|
|
|
override fun <T : Any?> loadClass(name: String): Class<T>? {
|
|
// println("load class: $name")
|
|
var clazz: Class<T>? = loadClass(name, classPathScanResult)
|
|
|
|
if (clazz == null) {
|
|
clazz = loadClass(name, dependencyScanResult)
|
|
}
|
|
|
|
return clazz
|
|
}
|
|
|
|
private fun <T : Any?> loadClass(name: String, scanResult: io.github.classgraph.ScanResult): Class<T>? {
|
|
@Suppress("UNCHECKED_CAST")
|
|
return scanResult.loadClass(name, true) as Class<T>?
|
|
}
|
|
|
|
override fun <T : Any?> getSubTypesOf(type: Class<T>): MutableSet<Class<out T>> {
|
|
// println("get subtype of: $type")
|
|
|
|
val classes = mutableSetOf<Class<out T>>()
|
|
getSubTypesOf(type, classPathScanResult, classes)
|
|
|
|
return classes
|
|
}
|
|
|
|
fun <T : Any?> getSubTypesOf(type: Class<T>, scanResult: io.github.classgraph.ScanResult, classes: MutableSet<Class<out T>>) {
|
|
// only those in direct relationship, not subclasses of THOSE subclasses
|
|
scanResult.getSubclasses(type.canonicalName).forEach {
|
|
// load this class into the current classloader
|
|
@Suppress("UNCHECKED_CAST")
|
|
classes.add(it.loadClass() as Class<out T>)
|
|
|
|
// we have to load all of the class dependencies for this class into the current classloader
|
|
it.classDependencies.forEach { dep ->
|
|
dep.loadClass()
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun getResource(name: String): URL? {
|
|
// println("Get resource $name")
|
|
|
|
val results = getResource(name, classPathScanResult)
|
|
|
|
return if (results.isEmpty()) {
|
|
Thread.currentThread().contextClassLoader.getResource(name)
|
|
} else {
|
|
results.firstOrNull()?.url
|
|
}
|
|
}
|
|
|
|
private fun getResource(name: String, scanResult: io.github.classgraph.ScanResult): io.github.classgraph.ResourceList {
|
|
var results = scanResult.getResourcesWithPath(name)
|
|
if (results == null || results.isEmpty()) {
|
|
results = scanResult.getResourcesWithLeafName(name)
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
override fun getAnnotatedClasses(clazz: Class<out Annotation>): MutableSet<Class<*>> {
|
|
// println("getting classes for annotation: '$clazz'")
|
|
|
|
val classes = mutableSetOf<Class<*>>()
|
|
getAnnotatedClasses(clazz, classPathScanResult, classes)
|
|
|
|
return classes
|
|
}
|
|
|
|
private fun getAnnotatedClasses(clazz: Class<out Annotation>, scanResult: io.github.classgraph.ScanResult, classes: MutableSet<Class<*>>) {
|
|
scanResult.getClassesWithAnnotation(clazz.name).forEach {
|
|
// load this class into the current classloader
|
|
classes.add(it.loadClass())
|
|
|
|
// we have to load all of the class dependencies for this class into the current classloader
|
|
it.classDependencies.forEach { dep ->
|
|
dep.loadClass()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call this when done!
|
|
*/
|
|
fun finish() {
|
|
classPathScanResult.close()
|
|
dependencyScanResult.close()
|
|
}
|
|
}
|