Log unmatched arguments and unknown properties
This PR adds logging of all unmatched arguments and unknown properties which are currently just ignored. A custom Jackson Module and ProblemHandler are used to collect and log the unknown properties.
MODIFY
src/main/java/de/fraunhofer/aisec/codyze/Main.java
src/main/java/de/fraunhofer/aisec/codyze/Main.java
@@ -67,7 +67,7 @@ public class Main {
int returnCode = 0;
try {
- Configuration config = Configuration.initConfig(firstPass.configFile, args);
+ Configuration config = Configuration.initConfig(firstPass.configFile, firstPass.remainder.toArray(new String[0]));
// Start analysis setup
returnCode = start(config);
}

MODIFY
src/main/java/de/fraunhofer/aisec/codyze/config/Configuration.kt
src/main/java/de/fraunhofer/aisec/codyze/config/Configuration.kt
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier
+import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper
import de.fraunhofer.aisec.codyze.analysis.ServerConfiguration
@@ -19,6 +20,7 @@ import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.passes.Pass
import java.io.File
import java.io.IOException
+import org.slf4j.Logger
import org.slf4j.LoggerFactory
import picocli.CommandLine
@@ -293,6 +295,7 @@ class Configuration {
// Parse CLI arguments into config class
private fun parseCLI(vararg args: String?) {
+ val cl =
CommandLine(this)
// Added as Mixin so the already initialized objects are used instead of new ones
// created
@@ -302,11 +305,20 @@ class Configuration {
.addMixin("translation", cpg.translation)
.registerConverter(Pass::class.java, PassTypeConverter())
.setCaseInsensitiveEnumValuesAllowed(true)
- // setUnmatchedArgumentsAllowed is true because both classes don't have the config path
- // option which would result in exceptions, side effect is that all unknown options are
- // ignored
+ // setUnmatchedArgumentsAllowed is true because both classes don't have the config
+ // path option which would result in exceptions, side effect is that all unknown
+ // options are ignored
.setUnmatchedArgumentsAllowed(true)
.parseArgs(*args)
+
+ // log any unmatched arguments
+ if (cl.unmatched() != null && cl.unmatched().isNotEmpty()) {
+ log.warn(
+ "{} argument(s) could not be matched: {}",
+ cl.unmatched().size,
+ cl.unmatched().toString()
+ )
+ }
}
companion object {
@@ -350,6 +362,8 @@ class Configuration {
}
}
)
+ val logProblemHandler = LogDeserializationProblemHandler(log)
+
val mapper =
YAMLMapper.builder().enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS).build()
mapper
@@ -357,16 +371,21 @@ class Configuration {
.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(module)
+ .registerModule(LogModule(logProblemHandler))
mapper.injectableValues =
InjectableValues.Std()
.addValue("configFileBasePath", configFile.absoluteFile.parentFile.absolutePath)
mapper.propertyNamingStrategy = PropertyNamingStrategies.KebabCaseStrategy()
+
var config: Configuration? = null
try {
config = mapper.readValue(configFile, Configuration::class.java)
} catch (e: IOException) {
printErrorMessage(configFile.absolutePath, e.toString())
}
+
+ logProblemHandler.printToLog()
+
return config ?: Configuration()
}
@@ -420,3 +439,35 @@ class ExecutionMode {
)
var isTui = false
}
+
+// Taken from:
+// https://stackoverflow.com/questions/46644099/cant-set-problemhandler-to-objectmapper-in-spring-boot
+class LogModule(private val problemHandler: LogDeserializationProblemHandler) : SimpleModule() {
+ override fun setupModule(context: SetupContext) {
+ super.setupModule(context)
+ context.addDeserializationProblemHandler(problemHandler)
+ }
+}
+
+class LogDeserializationProblemHandler(val log: Logger) : DeserializationProblemHandler() {
+ private val unknownPropNames = mutableListOf<String>()
+
+ fun printToLog() {
+ if (unknownPropNames.isNotEmpty()) {
+ log.warn(
+ "${if(unknownPropNames.size == 1) "1 property is" else "${unknownPropNames.size} properties are"} unknown: $unknownPropNames"
+ )
+ }
+ }
+
+ override fun handleUnknownProperty(
+ ctxt: DeserializationContext,
+ p: JsonParser,
+ deserializer: JsonDeserializer<*>,
+ beanOrClass: Any,
+ propertyName: String
+ ): Boolean {
+ unknownPropNames.add(propertyName)
+ return false
+ }
+}

Log unmatched arguments and unknown properties (#465)

This PR adds logging of all unmatched arguments and unknown properties which are currently just ignored. A custom Jackson Module and ProblemHandler are used to collect and log the unknown properties.

Co-authored-by: Florian Wendland <florian.wendland@aisec.fraunhofer.de>