mirror of
https://github.com/corda/corda.git
synced 2025-06-14 13:18:18 +00:00
CORDA-1274: Migrated usage of FastClasspathScanner to ClassGraph (#4060)
FastClasspathScanner was renamed to ClassGraph for the version 4 release
This commit is contained in:
@ -68,7 +68,7 @@ buildscript {
|
|||||||
ext.commons_cli_version = '1.4'
|
ext.commons_cli_version = '1.4'
|
||||||
ext.protonj_version = '0.27.1' // This is now aligned with the Artemis version, but retaining in case we ever need to diverge again for a bug fix.
|
ext.protonj_version = '0.27.1' // This is now aligned with the Artemis version, but retaining in case we ever need to diverge again for a bug fix.
|
||||||
ext.snappy_version = '0.4'
|
ext.snappy_version = '0.4'
|
||||||
ext.fast_classpath_scanner_version = '2.12.3'
|
ext.class_graph_version = '4.2.12'
|
||||||
ext.jcabi_manifests_version = '1.1'
|
ext.jcabi_manifests_version = '1.1'
|
||||||
ext.picocli_version = '3.5.2'
|
ext.picocli_version = '3.5.2'
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ dependencies {
|
|||||||
compile "org.ow2.asm:asm-tree:$asm_version"
|
compile "org.ow2.asm:asm-tree:$asm_version"
|
||||||
compile "org.ow2.asm:asm-commons:$asm_version"
|
compile "org.ow2.asm:asm-commons:$asm_version"
|
||||||
|
|
||||||
// Classpath scanner
|
// ClassGraph: classpath scanning
|
||||||
shadow "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
|
shadow "io.github.classgraph:classgraph:$class_graph_version"
|
||||||
|
|
||||||
// Test utilities
|
// Test utilities
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
@file:JvmName("Utilities")
|
@file:JvmName("Utilities")
|
||||||
package net.corda.djvm.tools.cli
|
package net.corda.djvm.tools.cli
|
||||||
|
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier.isAbstract
|
||||||
|
import java.lang.reflect.Modifier.isStatic
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@ -92,13 +93,10 @@ val userClassPath: String = System.getProperty("java.class.path")
|
|||||||
* Get a reference of each concrete class that implements interface or class [T].
|
* Get a reference of each concrete class that implements interface or class [T].
|
||||||
*/
|
*/
|
||||||
inline fun <reified T> find(scanSpec: String = "net/corda/djvm"): List<Class<*>> {
|
inline fun <reified T> find(scanSpec: String = "net/corda/djvm"): List<Class<*>> {
|
||||||
val references = mutableListOf<Class<*>>()
|
return ClassGraph()
|
||||||
FastClasspathScanner(scanSpec)
|
.whitelistPaths(scanSpec)
|
||||||
.matchClassesImplementing(T::class.java) { clazz ->
|
.enableAllInfo()
|
||||||
if (!Modifier.isAbstract(clazz.modifiers) && !Modifier.isStatic(clazz.modifiers)) {
|
|
||||||
references.add(clazz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.scan()
|
.scan()
|
||||||
return references
|
.use { it.getClassesImplementing(T::class.java.name).loadClasses(T::class.java) }
|
||||||
|
.filter { !isAbstract(it.modifiers) && !isStatic(it.modifiers) }
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.djvm.utilities
|
package net.corda.djvm.utilities
|
||||||
|
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,19 +13,19 @@ object Discovery {
|
|||||||
* Get an instance of each concrete class that implements interface or class [T].
|
* Get an instance of each concrete class that implements interface or class [T].
|
||||||
*/
|
*/
|
||||||
inline fun <reified T> find(): List<T> {
|
inline fun <reified T> find(): List<T> {
|
||||||
val instances = mutableListOf<T>()
|
return ClassGraph()
|
||||||
FastClasspathScanner("net/corda/djvm")
|
.whitelistPaths("net/corda/djvm")
|
||||||
.matchClassesImplementing(T::class.java) { clazz ->
|
.enableAllInfo()
|
||||||
if (clazz.modifiers and FORBIDDEN_CLASS_MASK == 0) {
|
|
||||||
try {
|
|
||||||
instances.add(clazz.newInstance())
|
|
||||||
} catch (exception: Throwable) {
|
|
||||||
throw Exception("Unable to instantiate ${clazz.name}", exception)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.scan()
|
.scan()
|
||||||
return instances
|
.use { it.getClassesImplementing(T::class.java.name).loadClasses(T::class.java) }
|
||||||
|
.filter { it.modifiers and FORBIDDEN_CLASS_MASK == 0 }
|
||||||
|
.map {
|
||||||
|
try {
|
||||||
|
it.newInstance()
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
throw Exception("Unable to instantiate ${it.name}", exception)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ dependencies {
|
|||||||
// JOptSimple: command line option parsing
|
// JOptSimple: command line option parsing
|
||||||
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
|
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
|
||||||
|
|
||||||
// FastClasspathScanner: classpath scanning
|
// ClassGraph: classpath scanning
|
||||||
compile "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
|
compile "io.github.classgraph:classgraph:$class_graph_version"
|
||||||
|
|
||||||
compile "commons-io:commons-io:$commonsio_version"
|
compile "commons-io:commons-io:$commonsio_version"
|
||||||
compile "com.spotify:docker-client:$docker_client_version"
|
compile "com.spotify:docker-client:$docker_client_version"
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
package net.corda.behave.scenarios
|
package net.corda.behave.scenarios
|
||||||
|
|
||||||
import cucumber.api.java8.En
|
import cucumber.api.java8.En
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import net.corda.behave.scenarios.api.StepsBlock
|
import net.corda.behave.scenarios.api.StepsBlock
|
||||||
import net.corda.behave.scenarios.api.StepsProvider
|
import net.corda.behave.scenarios.api.StepsProvider
|
||||||
import net.corda.behave.scenarios.steps.*
|
import net.corda.behave.scenarios.steps.*
|
||||||
import net.corda.core.internal.objectOrNewInstance
|
import net.corda.core.internal.objectOrNewInstance
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.contextLogger
|
||||||
|
|
||||||
@Suppress("KDocMissingDocumentation")
|
@Suppress("KDocMissingDocumentation")
|
||||||
class StepsContainer(val state: ScenarioState) : En {
|
class StepsContainer(val state: ScenarioState) : En {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val log = contextLogger()
|
||||||
|
|
||||||
val stepsProviders: List<StepsProvider> by lazy {
|
val stepsProviders: List<StepsProvider> by lazy {
|
||||||
FastClasspathScanner().addClassLoader(this::class.java.classLoader).scan()
|
ClassGraph()
|
||||||
.getNamesOfClassesImplementing(StepsProvider::class.java)
|
.addClassLoader(this::class.java.classLoader)
|
||||||
.mapNotNull { this::class.java.classLoader.loadClass(it).asSubclass(StepsProvider::class.java) }
|
.enableAllInfo()
|
||||||
|
.scan()
|
||||||
|
.use { it.getClassesImplementing(StepsProvider::class.java.name).loadClasses(StepsProvider::class.java) }
|
||||||
.map { it.kotlin.objectOrNewInstance() }
|
.map { it.kotlin.objectOrNewInstance() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val log = loggerFor<StepsContainer>()
|
|
||||||
|
|
||||||
private val stepDefinitions: List<StepsBlock> = listOf(
|
private val stepDefinitions: List<StepsBlock> = listOf(
|
||||||
CashSteps(),
|
CashSteps(),
|
||||||
ConfigurationSteps(),
|
ConfigurationSteps(),
|
||||||
|
@ -27,8 +27,8 @@ dependencies {
|
|||||||
|
|
||||||
compile "org.apache.qpid:proton-j:$protonj_version"
|
compile "org.apache.qpid:proton-j:$protonj_version"
|
||||||
|
|
||||||
// FastClasspathScanner: classpath scanning - needed for the NetworkBootstrapper.
|
// ClassGraph: classpath scanning
|
||||||
compile "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
|
compile "io.github.classgraph:classgraph:$class_graph_version"
|
||||||
|
|
||||||
// For caches rather than guava
|
// For caches rather than guava
|
||||||
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
|
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.nodeapi.internal
|
package net.corda.nodeapi.internal
|
||||||
|
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import net.corda.core.contracts.Contract
|
import net.corda.core.contracts.Contract
|
||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
import net.corda.core.contracts.UpgradedContract
|
import net.corda.core.contracts.UpgradedContract
|
||||||
@ -28,15 +28,13 @@ class ContractsJarFile(private val file: Path) : ContractsJar {
|
|||||||
override val hash: SecureHash by lazy(LazyThreadSafetyMode.NONE, file::hash)
|
override val hash: SecureHash by lazy(LazyThreadSafetyMode.NONE, file::hash)
|
||||||
|
|
||||||
override fun scan(): List<ContractClassName> {
|
override fun scan(): List<ContractClassName> {
|
||||||
val scanResult = FastClasspathScanner()
|
val scanResult = ClassGraph().overrideClasspath(singleton(file)).enableAllInfo().scan()
|
||||||
// A set of a single element may look odd, but if this is removed "Path" which itself is an `Iterable`
|
|
||||||
// is getting broken into pieces to scan individually, which doesn't yield desired effect.
|
|
||||||
.overrideClasspath(singleton(file))
|
|
||||||
.scan()
|
|
||||||
|
|
||||||
val contractClassNames = coreContractClasses
|
val contractClassNames = scanResult.use {
|
||||||
.flatMap { scanResult.getNamesOfClassesImplementing(it.qualifiedName) }
|
coreContractClasses
|
||||||
|
.flatMap { scanResult.getClassesImplementing(it.qualifiedName).names }
|
||||||
.toSet()
|
.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
return URLClassLoader(arrayOf(file.toUri().toURL()), Contract::class.java.classLoader).use { cl ->
|
return URLClassLoader(arrayOf(file.toUri().toURL()), Contract::class.java.classLoader).use { cl ->
|
||||||
contractClassNames.mapNotNull {
|
contractClassNames.mapNotNull {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.corda.node.internal.cordapp
|
package net.corda.node.internal.cordapp
|
||||||
|
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult
|
import io.github.classgraph.ScanResult
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.sha256
|
import net.corda.core.crypto.sha256
|
||||||
@ -95,7 +95,7 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
}
|
}
|
||||||
private fun loadCordapps(): List<CordappImpl> {
|
private fun loadCordapps(): List<CordappImpl> {
|
||||||
val cordapps = cordappJarPaths
|
val cordapps = cordappJarPaths
|
||||||
.map { scanCordapp(it).toCordapp(it) }
|
.map { url -> scanCordapp(url).use { it.toCordapp(url) } }
|
||||||
.filter {
|
.filter {
|
||||||
if (it.info.minimumPlatformVersion > versionInfo.platformVersion) {
|
if (it.info.minimumPlatformVersion > versionInfo.platformVersion) {
|
||||||
logger.warn("Not loading CorDapp ${it.info.shortName} (${it.info.vendor}) as it requires minimum " +
|
logger.warn("Not loading CorDapp ${it.info.shortName} (${it.info.vendor}) as it requires minimum " +
|
||||||
@ -202,7 +202,8 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
private fun scanCordapp(cordappJarPath: RestrictedURL): RestrictedScanResult {
|
private fun scanCordapp(cordappJarPath: RestrictedURL): RestrictedScanResult {
|
||||||
logger.info("Scanning CorDapp in ${cordappJarPath.url}")
|
logger.info("Scanning CorDapp in ${cordappJarPath.url}")
|
||||||
return cachedScanResult.computeIfAbsent(cordappJarPath) {
|
return cachedScanResult.computeIfAbsent(cordappJarPath) {
|
||||||
RestrictedScanResult(FastClasspathScanner().addClassLoader(appClassLoader).overrideClasspath(cordappJarPath.url).scan(), cordappJarPath.qualifiedNamePrefix)
|
val scanResult = ClassGraph().addClassLoader(appClassLoader).overrideClasspath(cordappJarPath.url).enableAllInfo().scan()
|
||||||
|
RestrictedScanResult(scanResult, cordappJarPath.qualifiedNamePrefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,40 +240,49 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
return map { it.kotlin.objectOrNewInstance() }
|
return map { it.kotlin.objectOrNewInstance() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class RestrictedScanResult(private val scanResult: ScanResult, private val qualifiedNamePrefix: String) {
|
private inner class RestrictedScanResult(private val scanResult: ScanResult, private val qualifiedNamePrefix: String) : AutoCloseable {
|
||||||
fun getNamesOfClassesImplementing(type: KClass<*>): List<String> {
|
fun getNamesOfClassesImplementing(type: KClass<*>): List<String> {
|
||||||
return scanResult.getNamesOfClassesImplementing(type.java)
|
return scanResult.getClassesImplementing(type.java.name).names.filter { it.startsWith(qualifiedNamePrefix) }
|
||||||
.filter { it.startsWith(qualifiedNamePrefix) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> getClassesWithSuperclass(type: KClass<T>): List<Class<out T>> {
|
fun <T : Any> getClassesWithSuperclass(type: KClass<T>): List<Class<out T>> {
|
||||||
return scanResult.getNamesOfSubclassesOf(type.java)
|
return scanResult
|
||||||
|
.getSubclasses(type.java.name)
|
||||||
|
.names
|
||||||
.filter { it.startsWith(qualifiedNamePrefix) }
|
.filter { it.startsWith(qualifiedNamePrefix) }
|
||||||
.mapNotNull { loadClass(it, type) }
|
.mapNotNull { loadClass(it, type) }
|
||||||
.filterNot { Modifier.isAbstract(it.modifiers) }
|
.filterNot { it.isAbstractClass }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> getClassesImplementing(type: KClass<T>): List<T> {
|
fun <T : Any> getClassesImplementing(type: KClass<T>): List<T> {
|
||||||
return scanResult.getNamesOfClassesImplementing(type.java)
|
return scanResult
|
||||||
|
.getClassesImplementing(type.java.name)
|
||||||
|
.names
|
||||||
.filter { it.startsWith(qualifiedNamePrefix) }
|
.filter { it.startsWith(qualifiedNamePrefix) }
|
||||||
.mapNotNull { loadClass(it, type) }
|
.mapNotNull { loadClass(it, type) }
|
||||||
.filterNot { Modifier.isAbstract(it.modifiers) }
|
.filterNot { it.isAbstractClass }
|
||||||
.map { it.kotlin.objectOrNewInstance() }
|
.map { it.kotlin.objectOrNewInstance() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> getClassesWithAnnotation(type: KClass<T>, annotation: KClass<out Annotation>): List<Class<out T>> {
|
fun <T : Any> getClassesWithAnnotation(type: KClass<T>, annotation: KClass<out Annotation>): List<Class<out T>> {
|
||||||
return scanResult.getNamesOfClassesWithAnnotation(annotation.java)
|
return scanResult
|
||||||
|
.getClassesWithAnnotation(annotation.java.name)
|
||||||
|
.names
|
||||||
.filter { it.startsWith(qualifiedNamePrefix) }
|
.filter { it.startsWith(qualifiedNamePrefix) }
|
||||||
.mapNotNull { loadClass(it, type) }
|
.mapNotNull { loadClass(it, type) }
|
||||||
.filterNot { Modifier.isAbstract(it.modifiers) }
|
.filterNot { Modifier.isAbstract(it.modifiers) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> getConcreteClassesOfType(type: KClass<T>): List<Class<out T>> {
|
fun <T : Any> getConcreteClassesOfType(type: KClass<T>): List<Class<out T>> {
|
||||||
return scanResult.getNamesOfSubclassesOf(type.java)
|
return scanResult
|
||||||
|
.getSubclasses(type.java.name)
|
||||||
|
.names
|
||||||
.filter { it.startsWith(qualifiedNamePrefix) }
|
.filter { it.startsWith(qualifiedNamePrefix) }
|
||||||
.mapNotNull { loadClass(it, type) }
|
.mapNotNull { loadClass(it, type) }
|
||||||
.filterNot { Modifier.isAbstract(it.modifiers) }
|
.filterNot { it.isAbstractClass }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() = scanResult.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ dependencies {
|
|||||||
// For AMQP serialisation.
|
// For AMQP serialisation.
|
||||||
compile "org.apache.qpid:proton-j:$protonj_version"
|
compile "org.apache.qpid:proton-j:$protonj_version"
|
||||||
|
|
||||||
// FastClasspathScanner: classpath scanning
|
// ClassGraph: classpath scanning
|
||||||
compile "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
|
compile "io.github.classgraph:classgraph:$class_graph_version"
|
||||||
|
|
||||||
// Pure-Java Snappy compression
|
// Pure-Java Snappy compression
|
||||||
compile "org.iq80.snappy:snappy:$snappy_version"
|
compile "org.iq80.snappy:snappy:$snappy_version"
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
package net.corda.serialization.internal.amqp
|
package net.corda.serialization.internal.amqp
|
||||||
|
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import net.corda.core.DeleteForDJVM
|
import net.corda.core.DeleteForDJVM
|
||||||
import net.corda.core.KeepForDJVM
|
import net.corda.core.KeepForDJVM
|
||||||
import net.corda.core.StubOutForDJVM
|
import net.corda.core.StubOutForDJVM
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
|
import net.corda.core.internal.isAbstractClass
|
||||||
import net.corda.core.internal.objectOrNewInstance
|
import net.corda.core.internal.objectOrNewInstance
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.*
|
||||||
@ -16,7 +17,6 @@ import net.corda.serialization.internal.CordaSerializationMagic
|
|||||||
import net.corda.serialization.internal.DefaultWhitelist
|
import net.corda.serialization.internal.DefaultWhitelist
|
||||||
import net.corda.serialization.internal.MutableClassWhitelist
|
import net.corda.serialization.internal.MutableClassWhitelist
|
||||||
import net.corda.serialization.internal.SerializationScheme
|
import net.corda.serialization.internal.SerializationScheme
|
||||||
import java.lang.reflect.Modifier
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val AMQP_ENABLED get() = SerializationDefaults.P2P_CONTEXT.preferredSerializationVersion == amqpMagic
|
val AMQP_ENABLED get() = SerializationDefaults.P2P_CONTEXT.preferredSerializationVersion == amqpMagic
|
||||||
@ -72,10 +72,16 @@ abstract class AbstractAMQPSerializationScheme(
|
|||||||
@StubOutForDJVM
|
@StubOutForDJVM
|
||||||
private fun scanClasspathForSerializers(scanSpec: String): List<SerializationCustomSerializer<*, *>> =
|
private fun scanClasspathForSerializers(scanSpec: String): List<SerializationCustomSerializer<*, *>> =
|
||||||
this::class.java.classLoader.let { cl ->
|
this::class.java.classLoader.let { cl ->
|
||||||
FastClasspathScanner(scanSpec).addClassLoader(cl).scan()
|
ClassGraph()
|
||||||
.getNamesOfClassesImplementing(SerializationCustomSerializer::class.java)
|
.whitelistPackages(scanSpec)
|
||||||
.map { cl.loadClass(it).asSubclass(SerializationCustomSerializer::class.java) }
|
.addClassLoader(cl)
|
||||||
.filterNot { Modifier.isAbstract(it.modifiers) }
|
.enableAllInfo()
|
||||||
|
.scan()
|
||||||
|
.use {
|
||||||
|
val serializerClass = SerializationCustomSerializer::class.java
|
||||||
|
it.getClassesImplementing(serializerClass.name).loadClasses(serializerClass)
|
||||||
|
}
|
||||||
|
.filterNot { it.isAbstractClass }
|
||||||
.map { it.kotlin.objectOrNewInstance() }
|
.map { it.kotlin.objectOrNewInstance() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.testing.node.internal
|
package net.corda.testing.node.internal
|
||||||
|
|
||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.classgraph.ClassGraph
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.deleteIfExists
|
import net.corda.core.internal.deleteIfExists
|
||||||
import net.corda.core.internal.outputStream
|
import net.corda.core.internal.outputStream
|
||||||
@ -69,9 +69,12 @@ fun Iterable<TestCorDapp>.packageInDirectory(directory: Path) {
|
|||||||
* Returns all classes within the [targetPackage].
|
* Returns all classes within the [targetPackage].
|
||||||
*/
|
*/
|
||||||
fun allClassesForPackage(targetPackage: String): Set<Class<*>> {
|
fun allClassesForPackage(targetPackage: String): Set<Class<*>> {
|
||||||
|
return ClassGraph()
|
||||||
val scanResult = FastClasspathScanner(targetPackage).strictWhitelist().scan()
|
.whitelistPackages(targetPackage)
|
||||||
return scanResult.namesOfAllClasses.filter { className -> className.startsWith(targetPackage) }.map(scanResult::classNameToClassRef).toSet()
|
.enableAllInfo()
|
||||||
|
.scan()
|
||||||
|
.use { it.allClasses.loadClasses() }
|
||||||
|
.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user