diff options
author | Antoine A <> | 2024-02-05 13:40:34 +0100 |
---|---|---|
committer | Antoine A <> | 2024-02-05 13:40:34 +0100 |
commit | 4bd9979b9ee64b7c5d91ea7f6cc1471364c5974d (patch) | |
tree | e95b6a4abbd8a423260514dd208cfc089e8cf196 | |
parent | 54ff928887a5b5a96a262f35bf9e45e646184e07 (diff) | |
download | libeufin-4bd9979b9ee64b7c5d91ea7f6cc1471364c5974d.tar.gz libeufin-4bd9979b9ee64b7c5d91ea7f6cc1471364c5974d.tar.bz2 libeufin-4bd9979b9ee64b7c5d91ea7f6cc1471364c5974d.zip |
Improve config error fmt
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/Config.kt | 35 | ||||
-rw-r--r-- | common/src/main/kotlin/TalerConfig.kt | 44 |
2 files changed, 40 insertions, 39 deletions
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt index 5d881461..9926672e 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt @@ -86,7 +86,7 @@ fun TalerConfig.loadServerConfig(): ServerConfig { return when (val method = requireString("libeufin-bank", "serve")) { "tcp" -> ServerConfig.Tcp(requireNumber("libeufin-bank", "port")) "unix" -> ServerConfig.Unix(requireString("libeufin-bank", "unixpath"), requireNumber("libeufin-bank", "unixpath_mode")) - else -> throw Exception(" Unknown server method '$method' expected 'tcp' or 'unix' got '$method'") + else -> throw TalerConfigError.invalid("server method", "libeufin-bank", "serve", "expected 'tcp' or 'unix' got '$method'") } } @@ -106,10 +106,10 @@ fun TalerConfig.loadBankConfig(): BankConfig { } } } - val method = when (val raw = lookupString("libeufin-bank", "wire_type")) { + val method = when (val type = lookupString("libeufin-bank", "wire_type")) { "iban" -> WireMethod.IBAN "x-taler-bank" -> WireMethod.X_TALER_BANK - else -> throw TalerConfigError("expected a payment target type for section libeufin-bank, option wire_type, but $raw is unknown") + else -> throw TalerConfigError.invalid("payment target type", "libeufin-bank", "wire_type", "expected 'iban' or 'x-taler-bank' got '$type'") } val payto = when (method) { WireMethod.IBAN -> BankPaytoCtx(bic = lookupString("libeufin-bank", "iban_payto_bic")) @@ -141,7 +141,7 @@ fun String.notEmptyOrNull(): String? = if (isEmpty()) null else this fun TalerConfig.currencySpecificationFor(currency: String): CurrencySpecification = sections.find { it.startsWith("CURRENCY-") && requireBoolean(it, "enabled") && requireString(it, "code") == currency - }?.let { loadCurrencySpecification(it) } ?: throw TalerConfigError("missing currency specification for $currency") + }?.let { loadCurrencySpecification(it) } ?: throw TalerConfigError.generic("missing currency specification for $currency") private fun TalerConfig.loadCurrencySpecification(section: String): CurrencySpecification { return CurrencySpecification( @@ -154,39 +154,30 @@ private fun TalerConfig.loadCurrencySpecification(section: String): CurrencySpec } private fun TalerConfig.amount(section: String, option: String, currency: String): TalerAmount? { - val amountStr = lookupString(section, option) ?: return null + val raw = lookupString(section, option) ?: return null val amount = try { - TalerAmount(amountStr) + TalerAmount(raw) } catch (e: Exception) { - throw TalerConfigError("amount", section, option, "but amount is malformed") + throw TalerConfigError.invalid("amount", section, option, "amount '$raw' is malformed") } if (amount.currency != currency) { - throw TalerConfigError("amount", section, option, "but currency is wrong : got ${amount.currency} expected $currency") + throw TalerConfigError.invalid("amount", section, option, "expected currency $currency got ${amount.currency}") } return amount } private fun TalerConfig.requireAmount(section: String, option: String, currency: String): TalerAmount = - amount(section, option, currency) ?: throw TalerConfigError("amount", section, option, "but config value is empty") + amount(section, option, currency) ?: throw TalerConfigError.missing("amount", section, option) private fun TalerConfig.decimalNumber(section: String, option: String): DecimalNumber? { - val numberStr = lookupString(section, option) ?: return null + val raw = lookupString(section, option) ?: return null try { - return DecimalNumber(numberStr) + return DecimalNumber(raw) } catch (e: Exception) { - throw TalerConfigError("decimal number", section, option, "but number is malformed") + throw TalerConfigError.invalid("decimal number", section, option, "number '$raw' is malformed") } } private fun TalerConfig.requireDecimalNumber(section: String, option: String): DecimalNumber - = decimalNumber(section, option) ?: throw TalerConfigError("decimal number", section, option, "but config value is empty") - -private fun TalerConfig.RoundingMode(section: String, option: String): RoundingMode? { - val str = lookupString(section, option) ?: return null; - try { - return RoundingMode.valueOf(str) - } catch (e: Exception) { - throw TalerConfigError("rouding mode", section, option, "but $str is unknown") - } -}
\ No newline at end of file + = decimalNumber(section, option) ?: throw TalerConfigError.missing("decimal number", section, option)
\ No newline at end of file diff --git a/common/src/main/kotlin/TalerConfig.kt b/common/src/main/kotlin/TalerConfig.kt index a22564f5..cf6dd5d3 100644 --- a/common/src/main/kotlin/TalerConfig.kt +++ b/common/src/main/kotlin/TalerConfig.kt @@ -36,9 +36,17 @@ private val reSection = Regex("^\\s*\\[\\s*([^]]*)\\s*]\\s*$") private val reParam = Regex("^\\s*([^=]+?)\\s*=\\s*(.*?)\\s*$") private val reDirective = Regex("^\\s*@([a-zA-Z-_]+)@\\s*(.*?)\\s*$") -class TalerConfigError(m: String) : Exception(m) { - constructor(type: String, section: String, option: String, err: String): this("expected $type in configuration section $section option $option $err") - constructor(type: String, section: String, option: String): this("expected $type in configuration section $section option $option") +class TalerConfigError private constructor (m: String) : Exception(m) { + companion object { + fun missing(type: String, option: String, section: String): TalerConfigError = + TalerConfigError("Missing $type option '$option' in section '$section'") + + fun invalid(type: String, option: String, section: String, err: String): TalerConfigError = + TalerConfigError("Expected $type option '$option' in section '$section': $err") + + fun generic(msg: String): TalerConfigError = + TalerConfigError(msg) + } } /** @@ -161,7 +169,7 @@ class TalerConfig internal constructor( val directiveMatch = reDirective.matchEntire(line) if (directiveMatch != null) { if (source == null) { - throw TalerConfigError("Directives are only supported when loading from file") + throw TalerConfigError.generic("Directives are only supported when loading from file") } val directiveName = directiveMatch.groups[1]!!.value.lowercase() val directiveArg = directiveMatch.groups[2]!!.value @@ -178,7 +186,7 @@ class TalerConfig internal constructor( val arg = directiveArg.trim() val sp = arg.split(" ") if (sp.size != 2) { - throw TalerConfigError("invalid configuration, @inline-secret@ directive requires exactly two arguments") + throw TalerConfigError.generic("invalid configuration, @inline-secret@ directive requires exactly two arguments") } val sectionName = sp[0] val secretFilename = source.resolveSibling(sp[1]) @@ -186,7 +194,7 @@ class TalerConfig internal constructor( } else -> { - throw TalerConfigError("unsupported directive '$directiveName'") + throw TalerConfigError.generic("unsupported directive '$directiveName'") } } continue @@ -198,7 +206,7 @@ class TalerConfig internal constructor( continue } if (currentSection == null) { - throw TalerConfigError("section expected") + throw TalerConfigError.generic("section expected") } val paramMatch = reParam.matchEntire(line) @@ -213,7 +221,7 @@ class TalerConfig internal constructor( section.entries[optName] = optVal continue } - throw TalerConfigError("expected section header, option assignment or directive in line $lineNum file ${source ?: "<input>"}") + throw TalerConfigError.generic("expected section header, option assignment or directive in line $lineNum file ${source ?: "<input>"}") } } @@ -281,7 +289,7 @@ class TalerConfig internal constructor( */ fun pathsub(x: String, recursionDepth: Int = 0): Path { if (recursionDepth > 128) { - throw TalerConfigError("recursion limit in path substitution exceeded") + throw TalerConfigError.generic("recursion limit in path substitution exceeded") } val result = StringBuilder() var l = 0 @@ -339,10 +347,10 @@ class TalerConfig internal constructor( l = p continue } else { - throw TalerConfigError("malformed variable expression can't resolve variable '$varName'") + throw TalerConfigError.generic("malformed variable expression can't resolve variable '$varName'") } } - throw TalerConfigError("malformed variable expression (unbalanced)") + throw TalerConfigError.generic("malformed variable expression (unbalanced)") } else { // $var var varEnd = l + 1 @@ -426,22 +434,24 @@ class TalerConfig internal constructor( } fun requireString(section: String, option: String): String = - lookupString(section, option) ?: throw TalerConfigError("string", section, option) + lookupString(section, option) ?: throw TalerConfigError.missing("string", section, option) - fun requireNumber(section: String, option: String): Int = - lookupString(section, option)?.toInt() ?: throw TalerConfigError("number", section, option) + fun requireNumber(section: String, option: String): Int { + val raw = lookupString(section, option) ?: throw TalerConfigError.missing("number", section, option) + return raw.toIntOrNull() ?: throw TalerConfigError.invalid("number", section, option, "'$raw' not a valid number") + } fun lookupBoolean(section: String, option: String): Boolean? { val entry = lookupString(section, option) ?: return null return when (val v = entry.lowercase()) { "yes" -> true "no" -> false - else -> throw TalerConfigError("yes/no", section, option, "but got '$v'") + else -> throw TalerConfigError.invalid("yes/no", section, option, "got '$v'") } } fun requireBoolean(section: String, option: String): Boolean = - lookupBoolean(section, option) ?: throw TalerConfigError("boolean", section, option) + lookupBoolean(section, option) ?: throw TalerConfigError.missing("boolean", section, option) fun lookupPath(section: String, option: String): Path? { val entry = lookupString(section, option) ?: return null @@ -449,5 +459,5 @@ class TalerConfig internal constructor( } fun requirePath(section: String, option: String): Path = - lookupPath(section, option) ?: throw TalerConfigError("path", section, option) + lookupPath(section, option) ?: throw TalerConfigError.missing("path", section, option) } |