summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-02-05 13:40:34 +0100
committerAntoine A <>2024-02-05 13:40:34 +0100
commit4bd9979b9ee64b7c5d91ea7f6cc1471364c5974d (patch)
treee95b6a4abbd8a423260514dd208cfc089e8cf196
parent54ff928887a5b5a96a262f35bf9e45e646184e07 (diff)
downloadlibeufin-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.kt35
-rw-r--r--common/src/main/kotlin/TalerConfig.kt44
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)
}