Skip to content

Commit

Permalink
feat(scanner)!: Migrate to new plugin API
Browse files Browse the repository at this point in the history
Migrate the `ScannerWrapper` plugins to the new plugin API.

Signed-off-by: Martin Nonnenmacher <[email protected]>
  • Loading branch information
mnonnenmacher committed Feb 1, 2025
1 parent 86ee353 commit 481b5d0
Show file tree
Hide file tree
Showing 47 changed files with 630 additions and 777 deletions.
17 changes: 9 additions & 8 deletions plugins/commands/scanner/src/main/kotlin/ScannerCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import org.ossreviewtoolkit.model.config.OrtConfiguration
import org.ossreviewtoolkit.model.utils.DefaultResolutionProvider
import org.ossreviewtoolkit.model.utils.mergeLabels
import org.ossreviewtoolkit.plugins.api.OrtPlugin
import org.ossreviewtoolkit.plugins.api.PluginConfig
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
import org.ossreviewtoolkit.plugins.commands.api.OrtCommand
import org.ossreviewtoolkit.plugins.commands.api.OrtCommandFactory
Expand Down Expand Up @@ -167,34 +168,34 @@ class ScannerCommand(descriptor: PluginDescriptor = ScannerCommandFactory.descri

@Suppress("ForbiddenMethodCall")
private fun runScanners(
scannerWrapperFactories: List<ScannerWrapperFactory<*>>,
projectScannerWrapperFactories: List<ScannerWrapperFactory<*>>,
scannerWrapperFactories: List<ScannerWrapperFactory>,
projectScannerWrapperFactories: List<ScannerWrapperFactory>,
ortConfig: OrtConfiguration
): OrtResult {
val packageScannerWrappers = scannerWrapperFactories
.takeIf { PackageType.PACKAGE in packageTypes }.orEmpty()
.map {
val config = ortConfig.scanner.config?.get(it.type)
it.create(config?.options.orEmpty(), config?.secrets.orEmpty())
val config = ortConfig.scanner.config?.get(it.descriptor.id)
it.create(PluginConfig(config?.options.orEmpty(), config?.secrets.orEmpty()))
}

val projectScannerWrappers = projectScannerWrapperFactories
.takeIf { PackageType.PROJECT in packageTypes }.orEmpty()
.map {
val config = ortConfig.scanner.config?.get(it.type)
it.create(config?.options.orEmpty(), config?.secrets.orEmpty())
val config = ortConfig.scanner.config?.get(it.descriptor.id)
it.create(PluginConfig(config?.options.orEmpty(), config?.secrets.orEmpty()))
}

if (projectScannerWrappers.isNotEmpty()) {
echo("Scanning projects with:")
echo(projectScannerWrappers.joinToString { "\t${it.name} (version ${it.version})" })
echo(projectScannerWrappers.joinToString { "\t${it.descriptor.displayName} (version ${it.version})" })
} else {
echo("Projects will not be scanned.")
}

if (packageScannerWrappers.isNotEmpty()) {
echo("Scanning packages with:")
echo(packageScannerWrappers.joinToString { "\t${it.name} (version ${it.version})" })
echo(packageScannerWrappers.joinToString { "\t${it.descriptor.displayName} (version ${it.version})" })
} else {
echo("Packages will not be scanned.")
}
Expand Down
4 changes: 3 additions & 1 deletion plugins/scanners/askalono/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

plugins {
// Apply precompiled plugins.
id("ort-library-conventions")
id("ort-plugin-conventions")

// Apply third-party plugins.
alias(libs.plugins.kotlinSerialization)
Expand All @@ -32,5 +32,7 @@ dependencies {
implementation(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.serialization.json)

ksp(projects.scanner)

funTestApi(testFixtures(projects.scanner))
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ package org.ossreviewtoolkit.plugins.scanners.askalono
import org.ossreviewtoolkit.model.LicenseFinding
import org.ossreviewtoolkit.model.TextLocation
import org.ossreviewtoolkit.scanner.AbstractPathScannerWrapperFunTest
import org.ossreviewtoolkit.scanner.ScannerWrapperConfig

class AskalonoFunTest : AbstractPathScannerWrapperFunTest() {
override val scanner = Askalono("Askalono", ScannerWrapperConfig.EMPTY)
override val scanner = AskalonoFactory.create()

override val expectedFileLicenses = listOf(
LicenseFinding("Apache-2.0", TextLocation("LICENSE", TextLocation.UNKNOWN_LINE), 1.0f)
Expand Down
81 changes: 65 additions & 16 deletions plugins/scanners/askalono/src/main/kotlin/Askalono.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ import org.ossreviewtoolkit.model.LicenseFinding
import org.ossreviewtoolkit.model.ScanSummary
import org.ossreviewtoolkit.model.Severity
import org.ossreviewtoolkit.model.TextLocation
import org.ossreviewtoolkit.plugins.api.OrtPlugin
import org.ossreviewtoolkit.plugins.api.OrtPluginOption
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
import org.ossreviewtoolkit.scanner.LocalPathScannerWrapper
import org.ossreviewtoolkit.scanner.ScanContext
import org.ossreviewtoolkit.scanner.ScanException
import org.ossreviewtoolkit.scanner.ScannerMatcher
import org.ossreviewtoolkit.scanner.ScannerWrapperConfig
import org.ossreviewtoolkit.scanner.ScannerMatcherConfig
import org.ossreviewtoolkit.scanner.ScannerWrapperFactory
import org.ossreviewtoolkit.utils.common.CommandLineTool
import org.ossreviewtoolkit.utils.common.Options
import org.ossreviewtoolkit.utils.common.Os

private const val CONFIDENCE_NOTICE = "Confidence threshold not high enough for any known license"
Expand All @@ -58,23 +60,70 @@ object AskalonoCommand : CommandLineTool {
override fun displayName() = "Askalono"
}

class Askalono internal constructor(name: String, private val wrapperConfig: ScannerWrapperConfig) :
LocalPathScannerWrapper(name) {
class Factory : ScannerWrapperFactory<Unit>("Askalono") {
override fun create(config: Unit, wrapperConfig: ScannerWrapperConfig) = Askalono(type, wrapperConfig)

override fun parseConfig(options: Options, secrets: Options) = Unit
}

data class AskalonoConfig(
/**
* A regular expression to match the scanner name when looking up scan results in the storage.
*/
val regScannerName: String?,

/**
* The minimum version of stored scan results to use.
*/
val minVersion: String?,

/**
* The maximum version of stored scan results to use.
*/
val maxVersion: String?,

/**
* The configuration to use for the scanner. Only scan results with the same configuration are used when looking up
* scan results in the storage.
*/
val configuration: String?,

/**
* Whether to read scan results from the storage.
*/
@OrtPluginOption(defaultValue = "true")
val readFromStorage: Boolean,

/**
* Whether to write scan results to the storage.
*/
@OrtPluginOption(defaultValue = "true")
val writeToStorage: Boolean
)

@OrtPlugin(
id = "askalono",
displayName = "askalono",
description = "askalono is a library and command-line tool to help detect license texts. It's designed to be " +
"fast, accurate, and to support a wide variety of license texts.",
factory = ScannerWrapperFactory::class
)
class Askalono(

Check warning on line 105 in plugins/scanners/askalono/src/main/kotlin/Askalono.kt

View workflow job for this annotation

GitHub Actions / qodana-scan

Unused symbol

Class "Askalono" is never used

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Class "Askalono" is never used
override val descriptor: PluginDescriptor = AskalonoFactory.descriptor,
config: AskalonoConfig
) : LocalPathScannerWrapper() {
override val configuration = ""

override val matcher by lazy { ScannerMatcher.create(details, wrapperConfig.matcherConfig) }
override val matcher by lazy {
ScannerMatcher.create(
details,
ScannerMatcherConfig(
config.regScannerName,
config.minVersion,
config.maxVersion,
config.configuration
)
)
}

override val version by lazy { AskalonoCommand.getVersion() }

override val readFromStorage by lazy { wrapperConfig.readFromStorageWithDefault(matcher) }

override val writeToStorage by lazy { wrapperConfig.writeToStorageWithDefault(matcher) }
override val readFromStorage = config.readFromStorage
override val writeToStorage = config.writeToStorage

override fun runScanner(path: File, context: ScanContext): String {
val process = AskalonoCommand.run(
Expand All @@ -97,7 +146,7 @@ class Askalono internal constructor(name: String, private val wrapperConfig: Sca

val issues = mutableListOf(
Issue(
source = name,
source = descriptor.id,
message = "This scanner is not capable of detecting copyright statements.",
severity = Severity.HINT
)
Expand All @@ -114,7 +163,7 @@ class Askalono internal constructor(name: String, private val wrapperConfig: Sca

if (it.error != null) {
issues += Issue(
source = name,
source = descriptor.id,
message = it.error,
severity = if (it.error == CONFIDENCE_NOTICE) Severity.HINT else Severity.ERROR
)
Expand Down

This file was deleted.

4 changes: 3 additions & 1 deletion plugins/scanners/boyterlc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

plugins {
// Apply precompiled plugins.
id("ort-library-conventions")
id("ort-plugin-conventions")

// Apply third-party plugins.
alias(libs.plugins.kotlinSerialization)
Expand All @@ -32,5 +32,7 @@ dependencies {
implementation(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.serialization.json)

ksp(projects.scanner)

funTestApi(testFixtures(projects.scanner))
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ package org.ossreviewtoolkit.plugins.scanners.boyterlc
import org.ossreviewtoolkit.model.LicenseFinding
import org.ossreviewtoolkit.model.TextLocation
import org.ossreviewtoolkit.scanner.AbstractPathScannerWrapperFunTest
import org.ossreviewtoolkit.scanner.ScannerWrapperConfig

class BoyterLcFunTest : AbstractPathScannerWrapperFunTest() {
override val scanner = BoyterLc("BoyterLc", ScannerWrapperConfig.EMPTY)
override val scanner = BoyterLcFactory.create()

override val expectedFileLicenses = listOf(
LicenseFinding("Apache-2.0", TextLocation("LICENSE", TextLocation.UNKNOWN_LINE), 0.98388565f),
Expand Down
79 changes: 64 additions & 15 deletions plugins/scanners/boyterlc/src/main/kotlin/BoyterLc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ import org.ossreviewtoolkit.model.LicenseFinding
import org.ossreviewtoolkit.model.ScanSummary
import org.ossreviewtoolkit.model.Severity
import org.ossreviewtoolkit.model.TextLocation
import org.ossreviewtoolkit.plugins.api.OrtPlugin
import org.ossreviewtoolkit.plugins.api.OrtPluginOption
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
import org.ossreviewtoolkit.scanner.LocalPathScannerWrapper
import org.ossreviewtoolkit.scanner.ScanContext
import org.ossreviewtoolkit.scanner.ScanException
import org.ossreviewtoolkit.scanner.ScannerMatcher
import org.ossreviewtoolkit.scanner.ScannerWrapperConfig
import org.ossreviewtoolkit.scanner.ScannerMatcherConfig
import org.ossreviewtoolkit.scanner.ScannerWrapperFactory
import org.ossreviewtoolkit.utils.common.CommandLineTool
import org.ossreviewtoolkit.utils.common.Options
import org.ossreviewtoolkit.utils.common.Os
import org.ossreviewtoolkit.utils.common.safeDeleteRecursively
import org.ossreviewtoolkit.utils.ort.createOrtTempDir
Expand All @@ -57,30 +59,77 @@ object BoyterLcCommand : CommandLineTool {
override fun displayName() = "BoyterLc"
}

class BoyterLc internal constructor(name: String, private val wrapperConfig: ScannerWrapperConfig) :
LocalPathScannerWrapper(name) {
data class BoyterLcConfig(
/**
* A regular expression to match the scanner name when looking up scan results in the storage.
*/
val regScannerName: String?,

/**
* The minimum version of stored scan results to use.
*/
val minVersion: String?,

/**
* The maximum version of stored scan results to use.
*/
val maxVersion: String?,

/**
* The configuration to use for the scanner. Only scan results with the same configuration are used when looking up
* scan results in the storage.
*/
val configuration: String?,

/**
* Whether to read scan results from the storage.
*/
@OrtPluginOption(defaultValue = "true")
val readFromStorage: Boolean,

/**
* Whether to write scan results to the storage.
*/
@OrtPluginOption(defaultValue = "true")
val writeToStorage: Boolean
)

@OrtPlugin(
id = "BoyterLc",
displayName = "BoyterLc",
description = "A command line application which scans directories and identifies what software license things " +
"are under.",
factory = ScannerWrapperFactory::class
)
class BoyterLc(

Check warning on line 104 in plugins/scanners/boyterlc/src/main/kotlin/BoyterLc.kt

View workflow job for this annotation

GitHub Actions / qodana-scan

Unused symbol

Class "BoyterLc" is never used

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Class "BoyterLc" is never used
override val descriptor: PluginDescriptor = BoyterLcFactory.descriptor,
config: BoyterLcConfig
) : LocalPathScannerWrapper() {
companion object {
val CONFIGURATION_OPTIONS = listOf(
"--confidence", "0.95", // Cut-off value to only get most relevant matches.
"--format", "json"
)
}

class Factory : ScannerWrapperFactory<Unit>("BoyterLc") {
override fun create(config: Unit, wrapperConfig: ScannerWrapperConfig) = BoyterLc(type, wrapperConfig)

override fun parseConfig(options: Options, secrets: Options) = Unit
}

override val configuration = CONFIGURATION_OPTIONS.joinToString(" ")

override val matcher by lazy { ScannerMatcher.create(details, wrapperConfig.matcherConfig) }
override val matcher by lazy {
ScannerMatcher.create(
details,
ScannerMatcherConfig(
config.regScannerName,
config.minVersion,
config.maxVersion,
config.configuration
)
)
}

override val version by lazy { BoyterLcCommand.getVersion() }

override val readFromStorage by lazy { wrapperConfig.readFromStorageWithDefault(matcher) }

override val writeToStorage by lazy { wrapperConfig.writeToStorageWithDefault(matcher) }
override val readFromStorage = config.readFromStorage
override val writeToStorage = config.writeToStorage

override fun runScanner(path: File, context: ScanContext): String {
val resultFile = createOrtTempDir().resolve("result.json")
Expand Down Expand Up @@ -118,7 +167,7 @@ class BoyterLc internal constructor(name: String, private val wrapperConfig: Sca
licenseFindings = licenseFindings,
issues = listOf(
Issue(
source = name,
source = descriptor.id,
message = "This scanner is not capable of detecting copyright statements.",
severity = Severity.HINT
)
Expand Down

This file was deleted.

4 changes: 3 additions & 1 deletion plugins/scanners/dos/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

plugins {
// Apply precompiled plugins.
id("ort-library-conventions")
id("ort-plugin-conventions")

// Apply third-party plugins.
alias(libs.plugins.kotlinSerialization)
Expand All @@ -40,6 +40,8 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(libs.log4j.api)

ksp(projects.scanner)

testImplementation(libs.mockk)
testImplementation(libs.wiremock)
}
Loading

0 comments on commit 481b5d0

Please sign in to comment.