Skip to content

Commit

Permalink
Merge pull request #6 from fraunhofer-iem/feature/demo
Browse files Browse the repository at this point in the history
library update
  • Loading branch information
AnakinRaW authored Sep 5, 2024
2 parents ad52333 + e755b8b commit 7b119db
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 609 deletions.
441 changes: 22 additions & 419 deletions .editorconfig

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,7 @@ gradle-app.setting
# Java heap dump
*.hprof

# End of https://www.toptal.com/developers/gitignore/api/kotlin,gradle,intellij,intellij+iml,intellij+all
### MAC Stuff ###
.DS_Store

# End of https://www.toptal.com/developers/gitignore/api/kotlin,gradle,intellij,intellij+iml,intellij+all
26 changes: 11 additions & 15 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
plugins {
kotlin("jvm") version "2.0.10"
}
plugins { kotlin("jvm") version "2.0.10" }

group = "de.fraunhofer.iem"

version = "1.0-SNAPSHOT"

repositories {
mavenCentral()
}
repositories { mavenCentral() }

dependencies { testImplementation(kotlin("test")) }

tasks.register("ktfmtCheck") { dependsOn(gradle.includedBuild("spha-cli").task(":ktfmtCheck")) }

tasks.register("ktfmtFormat") { dependsOn(gradle.includedBuild("spha-cli").task(":ktfmtFormat")) }

dependencies {
testImplementation(kotlin("test"))
}
tasks.test { useJUnitPlatform() }

tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(21)
}
kotlin { jvmToolchain(21) }
2 changes: 1 addition & 1 deletion library
20 changes: 10 additions & 10 deletions spha-cli/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
plugins {
alias(libs.plugins.kotlin)
alias(libs.plugins.serialization)
alias(libs.plugins.ktfmt)
application
}

group = "de.fraunhofer.iem.spha"

version = "0.0.2-SNAPSHOT"

repositories {
mavenCentral()
}
repositories { mavenCentral() }

dependencies{
dependencies {
implementation(libs.bundles.kpiCalculator)

implementation(libs.kotlin.cli)
Expand All @@ -30,18 +30,18 @@ dependencies{
testImplementation(libs.test.junit5.params)
}

tasks.test {
useJUnitPlatform()
ktfmt {
// KotlinLang style - 4 space indentation - From kotlinlang.org/docs/coding-conventions.html
kotlinLangStyle()
}

application{
mainClass = "de.fraunhofer.iem.spha.cli.MainKt"
}
tasks.test { useJUnitPlatform() }

application { mainClass = "de.fraunhofer.iem.spha.cli.MainKt" }

kotlin {
compilerOptions {
jvmToolchain(21)
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
}
}

2 changes: 2 additions & 0 deletions spha-cli/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mockk = "1.13.12"
jimfs = "1.3.0"
apache-commoms = "3.16.0"
junit = "5.11.0"
ktfmt = "0.20.1"

[libraries]
# KPI calculator
Expand Down Expand Up @@ -36,6 +37,7 @@ test-junit5-params = { module = "org.junit.jupiter:junit-jupiter-params", versio
[plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ktfmt = { id = "com.ncorti.ktfmt.gradle", version.ref = "ktfmt" }

[bundles]
kpiCalculator = ["kpi-calculator-adapter", "kpi-calculator-core", "kpi-calculator-model"]
Expand Down
78 changes: 43 additions & 35 deletions spha-cli/src/main/kotlin/de/fraunhofer/iem/spha/cli/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,73 +9,81 @@ import de.fraunhofer.iem.spha.cli.commands.TransformToolResultCommand
import de.fraunhofer.iem.spha.cli.transformer.RawKpiTransformer
import de.fraunhofer.iem.spha.cli.transformer.Tool2RawKpiTransformer
import io.github.oshai.kotlinlogging.KotlinLogging
import java.nio.file.FileSystem
import java.nio.file.FileSystems
import kotlin.system.exitProcess
import org.koin.core.component.KoinComponent
import org.koin.core.context.GlobalContext.startKoin
import org.koin.dsl.module
import org.slf4j.simple.SimpleLogger
import java.nio.file.FileSystem
import java.nio.file.FileSystems
import kotlin.system.exitProcess

internal val appModules = module {
single<RawKpiTransformer>{ Tool2RawKpiTransformer() }
single<FileSystem>{ FileSystems.getDefault() }
single<RawKpiTransformer> { Tool2RawKpiTransformer() }
single<FileSystem> { FileSystems.getDefault() }
}

fun main(args: Array<String>) {
startKoin{
modules(appModules)
}
startKoin { modules(appModules) }

try {
MainSphaToolCommand()
.subcommands(TransformToolResultCommand())
.main(args)
} catch (e : Exception){
val logger = KotlinLogging.logger{}
logger.error(e, {e.message})
MainSphaToolCommand().subcommands(TransformToolResultCommand()).main(args)
} catch (e: Exception) {
val logger = KotlinLogging.logger {}
logger.error(e, { e.message })
exitProcess(1)
}
}

/**
* The Main command of this application. Supports a global switch to enable verbose logging mode.
*/
private class MainSphaToolCommand : NoOpCliktCommand(){
private class MainSphaToolCommand : NoOpCliktCommand() {

val verbose by option("--verbose", "-v",
help="When set, the application provides detailed logging. Default is unset.")
.flag()
val verbose by
option(
"--verbose",
"-v",
help = "When set, the application provides detailed logging. Default is unset.",
)
.flag()

override fun run() {
configureLogging()
}

private fun configureLogging(){
if (verbose)
System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "TRACE")
private fun configureLogging() {
if (verbose) System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "TRACE")
}
}

/**
* Base class for all commands of this application, except for the main command.
* @implNote Due to the design of clikt, the main command should be separate
* and this base class should not introduce the --verbose switch. Otherwise, the following cli input would be legal:
* './spha -v transform -t abc -v'. The first -v switch actually triggers the logging configuration,
* where the second -v switch is independent to the first switch. This will cause confusion for users, which switch to use.
* Base class for all commands of this application, except for the main command. @implNote Due to
* the design of clikt, the main command should be separate and this base class should not introduce
* the --verbose switch. Otherwise, the following cli input would be legal: './spha -v transform -t
* abc -v'. The first -v switch actually triggers the logging configuration, where the second -v
* switch is independent to the first switch. This will cause confusion for users, which switch to
* use.
*/
internal abstract class SphaToolCommandBase(name: String? = null, help: String = "")
: CliktCommand(name = name, help = help), KoinComponent {
// NB: Needs to be lazy, as otherwise we initialize this variable before setting the logger configuration.
private val _lazyLogger = lazy { KotlinLogging.logger{} }
protected val Logger get() = _lazyLogger.value
internal abstract class SphaToolCommandBase(name: String? = null, help: String = "") :
CliktCommand(name = name, help = help), KoinComponent {
// NB: Needs to be lazy, as otherwise we initialize this variable before setting the logger
// configuration.
private val _lazyLogger = lazy { KotlinLogging.logger {} }
protected val Logger
get() = _lazyLogger.value

val strict by option("--strict",
help="When set, the application is less tolerant to unknown input formats. Default is unset.")
.flag()
val strict by
option(
"--strict",
help =
"When set, the application is less tolerant to unknown input formats. Default is unset.",
)
.flag()

override fun run() {
Logger.trace { "Original command arguments: '${currentContext.originalArgv.joinToString()}}'" }
Logger.trace {
"Original command arguments: '${currentContext.originalArgv.joinToString()}}'"
}
Logger.debug { "Running command: $commandName" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,65 @@ package de.fraunhofer.iem.spha.cli.commands
import com.github.ajalt.clikt.parameters.options.multiple
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.required
import de.fraunhofer.iem.kpiCalculator.adapter.tools.SupportedTool
import de.fraunhofer.iem.spha.cli.SphaToolCommandBase
import de.fraunhofer.iem.spha.cli.transformer.RawKpiTransformer
import de.fraunhofer.iem.spha.cli.transformer.TransformerOptions
import java.nio.file.FileSystem
import java.nio.file.Path
import kotlin.io.path.createDirectories
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToStream
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.nio.file.FileSystem
import java.nio.file.Path
import kotlin.io.path.createDirectories

internal class TransformToolResultCommand : SphaToolCommandBase(name = "transform",
help = "transforms a specified KPI-provider (such as a SAST tool) result into a uniform data format, " +
"so that it can be used for the 'calculate' command."), KoinComponent {
internal class TransformToolResultCommand :
SphaToolCommandBase(
name = "transform",
help =
"transforms a specified KPI-provider (such as a SAST tool) result into a uniform data format, " +
"so that it can be used for the 'calculate' command.",
),
KoinComponent {

private val transformer by inject<RawKpiTransformer>()
private val fileSystem by inject<FileSystem>()

private val toolName by option("-t", "--tool",
help = "The identifier of the KPI-provider tool that produced the input. " +
"Use the command --list-tools to get a list of available identifiers.")
.required()

private val inputFiles by option("-i", "--inputFile",
help = "List of input files. Usually these are result files produced by the tool as specified by --tool." +
"To specify multiple input files (if supported by --tool), the option can be used multiple times.")
.multiple()
private val toolName by
option(
"-t",
"--tool",
help =
"The identifier of the KPI-provider tool that produced the input. " +
"Use the command --list-tools to get a list of available identifiers.",
)
.required()

private val output by option("-o", "--output",
help = "The output directory where the result of the operation is stored. Default is the current working directory.")
private val inputFiles by
option(
"-i",
"--inputFile",
help =
"List of input files. Usually these are result files produced by the tool as specified by --tool." +
"To specify multiple input files (if supported by --tool), the option can be used multiple times.",
)
.multiple()

private val output by
option(
"-o",
"--output",
help =
"The output directory where the result of the operation is stored. Default is the current working directory.",
)

@OptIn(ExperimentalSerializationApi::class)
override fun run() {
super.run()
val result = transformer.getRawKpis(TransformerOptions(toolName, inputFiles), strict)
val resultPath = getResultFilePath()
fileSystem.provider().newOutputStream(resultPath).use {
Logger.trace{ "Storing result to '$resultPath'" }
Logger.trace { "Storing result to '$resultPath'" }
Json.encodeToStream(result, it)
}
}
Expand All @@ -58,7 +76,7 @@ internal class TransformToolResultCommand : SphaToolCommandBase(name = "transfor
return location.resolve(fileName).toAbsolutePath()
}

companion object{
companion object {
internal const val RESULT_FILE_SUFFIX = "-result.json"
}
}
Loading

0 comments on commit 7b119db

Please sign in to comment.