ENT-5109 Harmonize config-common, make everything compile again and harmonize NetworkParameterOverridesSpec. (#6082)

This commit is contained in:
Christian Sailer 2020-03-19 15:43:08 +00:00 committed by GitHub
parent dd7852f2b8
commit 82d9995717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 326 additions and 302 deletions

View File

@ -21,7 +21,7 @@ object Configuration {
/** /**
* Describes a [Config] hiding sensitive data. * Describes a [Config] hiding sensitive data.
*/ */
fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue = { value -> ConfigValueFactory.fromAnyRef(value.toString()) }): ConfigValue? fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue = { value -> ConfigValueFactory.fromAnyRef(value.toString()) }, options: Options): ConfigValue?
} }
object Value { object Value {
@ -36,10 +36,11 @@ object Configuration {
* *
* @throws ConfigException.Missing if the [Config] does not specify the value. * @throws ConfigException.Missing if the [Config] does not specify the value.
* @throws ConfigException.WrongType if the [Config] specifies a value of the wrong type. * @throws ConfigException.WrongType if the [Config] specifies a value of the wrong type.
* @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to application-level validation rules.. * @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to
* application-level validation rules.
*/ */
@Throws(ConfigException.Missing::class, ConfigException.WrongType::class, ConfigException.BadValue::class) @Throws(ConfigException.Missing::class, ConfigException.WrongType::class, ConfigException.BadValue::class)
fun valueIn(configuration: Config): TYPE fun valueIn(configuration: Config, options: Options): TYPE
/** /**
* Returns whether the value is specified by the [Config]. * Returns whether the value is specified by the [Config].
@ -50,27 +51,28 @@ object Configuration {
* Returns a value out of a [Config] if all is good, or null if no value is present. Otherwise, it throws an exception. * Returns a value out of a [Config] if all is good, or null if no value is present. Otherwise, it throws an exception.
* *
* @throws ConfigException.WrongType if the [Config] specifies a value of the wrong type. * @throws ConfigException.WrongType if the [Config] specifies a value of the wrong type.
* @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to application-level validation rules.. * @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to
* application-level validation rules.
*/ */
@Throws(ConfigException.WrongType::class, ConfigException.BadValue::class) @Throws(ConfigException.WrongType::class, ConfigException.BadValue::class)
fun valueInOrNull(configuration: Config): TYPE? { fun valueInOrNull(configuration: Config, options: Options): TYPE? {
return when { return when {
isSpecifiedBy(configuration) -> valueIn(configuration) isSpecifiedBy(configuration) -> valueIn(configuration, options)
else -> null else -> null
} }
} }
} }
/** /**
* Able to parse a value from a [Config] and [Configuration.Validation.Options], returning a [Valid] result containing either the value itself, or some [Configuration.Validation.Error]s. * Able to parse a value from a [Config] and [Configuration.Options], returning a [Valid] result containing either the value itself, or some [Configuration.Validation.Error]s.
*/ */
interface Parser<VALUE> { interface Parser<VALUE> {
/** /**
* Returns a [Valid] wrapper either around a valid value extracted from the [Config], or around a set of [Configuration.Validation.Error] with details about what went wrong. * Returns a [Valid] wrapper either around a valid value extracted from the [Config], or around a set of [Configuration.Validation.Error] with details about what went wrong.
*/ */
fun parse(configuration: Config, options: Configuration.Validation.Options = Configuration.Validation.Options.defaults): Valid<VALUE> fun parse(configuration: Config, options: Options = Options.defaults): Valid<VALUE>
} }
} }
@ -109,11 +111,6 @@ object Configuration {
*/ */
interface Definition<TYPE> : Configuration.Property.Metadata, Configuration.Validator, Configuration.Value.Extractor<TYPE>, Configuration.Describer, Configuration.Value.Parser<TYPE> { interface Definition<TYPE> : Configuration.Property.Metadata, Configuration.Validator, Configuration.Value.Extractor<TYPE>, Configuration.Describer, Configuration.Value.Parser<TYPE> {
/**
* Validates target [Config] with default [Configuration.Validation.Options].
*/
fun validate(target: Config): Valid<Config> = validate(target, Configuration.Validation.Options.defaults)
override fun isSpecifiedBy(configuration: Config): Boolean = configuration.hasPath(key) override fun isSpecifiedBy(configuration: Config): Boolean = configuration.hasPath(key)
/** /**
@ -181,9 +178,8 @@ object Configuration {
fun <MAPPED> map(mappedTypeName: String, convert: (TYPE) -> MAPPED): Standard<MAPPED> = mapValid(mappedTypeName) { value -> valid(convert.invoke(value)) } fun <MAPPED> map(mappedTypeName: String, convert: (TYPE) -> MAPPED): Standard<MAPPED> = mapValid(mappedTypeName) { value -> valid(convert.invoke(value)) }
} }
override fun parse(configuration: Config, options: Configuration.Validation.Options): Validated<TYPE, Validation.Error> { override fun parse(configuration: Config, options: Configuration.Options): Validated<TYPE, Validation.Error> {
return validate(configuration, options).mapValid { config -> valid(valueIn(config, options)) }
return validate(configuration, options).mapValid { config -> valid(valueIn(config)) }
} }
companion object { companion object {
@ -199,7 +195,6 @@ object Configuration {
* Returns a [Configuration.Property.Definition.Standard] with value of type [Int]. * Returns a [Configuration.Property.Definition.Standard] with value of type [Int].
*/ */
fun int(key: String, sensitive: Boolean = false): Standard<Int> = long(key, sensitive).mapValid { value -> fun int(key: String, sensitive: Boolean = false): Standard<Int> = long(key, sensitive).mapValid { value ->
try { try {
valid(Math.toIntExact(value)) valid(Math.toIntExact(value))
} catch (e: ArithmeticException) { } catch (e: ArithmeticException) {
@ -210,18 +205,17 @@ object Configuration {
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [Boolean]. * Returns a [Configuration.Property.Definition.Standard] with value of type [Boolean].
*/ */
fun boolean(key: String, sensitive: Boolean = false): Standard<Boolean> = StandardProperty(key, Boolean::class.javaObjectType.simpleName, Config::getBoolean, Config::getBooleanList, sensitive) fun boolean(key: String, sensitive: Boolean = false): Standard<Boolean> = StandardProperty(key, Boolean::class.javaObjectType.simpleName, { config, path, _ -> config.getBoolean(path) }, { config, path, _ -> config.getBooleanList(path) }, sensitive)
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [Double]. * Returns a [Configuration.Property.Definition.Standard] with value of type [Double].
*/ */
fun double(key: String, sensitive: Boolean = false): Standard<Double> = StandardProperty(key, Double::class.javaObjectType.simpleName, Config::getDouble, Config::getDoubleList, sensitive) fun double(key: String, sensitive: Boolean = false): Standard<Double> = StandardProperty(key, Double::class.javaObjectType.simpleName, { config, path, _ -> config.getDouble(path) }, { config, path, _ -> config.getDoubleList(path) }, sensitive)
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [Float]. * Returns a [Configuration.Property.Definition.Standard] with value of type [Float].
*/ */
fun float(key: String, sensitive: Boolean = false): Standard<Float> = double(key, sensitive).mapValid { value -> fun float(key: String, sensitive: Boolean = false): Standard<Float> = double(key, sensitive).mapValid { value ->
val floatValue = value.toFloat() val floatValue = value.toFloat()
if (floatValue.isInfinite() || floatValue.isNaN()) { if (floatValue.isInfinite() || floatValue.isNaN()) {
invalid<Float, Configuration.Validation.Error>(Configuration.Validation.Error.BadValue.of(key, Float::class.javaObjectType.simpleName, "Provided value exceeds Float range.")) invalid<Float, Configuration.Validation.Error>(Configuration.Validation.Error.BadValue.of(key, Float::class.javaObjectType.simpleName, "Provided value exceeds Float range."))
@ -233,24 +227,43 @@ object Configuration {
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [String]. * Returns a [Configuration.Property.Definition.Standard] with value of type [String].
*/ */
fun string(key: String, sensitive: Boolean = false): Standard<String> = StandardProperty(key, String::class.java.simpleName, Config::getString, Config::getStringList, sensitive) fun string(key: String, sensitive: Boolean = false): Standard<String> = StandardProperty(
key,
String::class.java.simpleName,
{ config, path, _ -> config.getString(path) },
{ config, path, _ -> config.getStringList(path) },
sensitive
)
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [Duration]. * Returns a [Configuration.Property.Definition.Standard] with value of type [Duration].
*/ */
fun duration(key: String, sensitive: Boolean = false): Standard<Duration> = StandardProperty(key, Duration::class.java.simpleName, Config::getDuration, Config::getDurationList, sensitive) fun duration(key: String, sensitive: Boolean = false): Standard<Duration> = StandardProperty(key, Duration::class.java.simpleName, { config, path, _ -> config.getDuration(path) }, { config, path, _ -> config.getDurationList(path) }, sensitive)
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [ConfigObject]. * Returns a [Configuration.Property.Definition.Standard] with value of type [ConfigObject].
* It supports an optional [Configuration.Schema], which is used for validation and more when provided. * It supports an optional [Configuration.Schema], which is used for validation and more when provided.
*/ */
fun nestedObject(key: String, schema: Schema? = null, sensitive: Boolean = false): Standard<ConfigObject> = StandardProperty(key, ConfigObject::class.java.simpleName, Config::getObject, Config::getObjectList, sensitive, schema) fun nestedObject(key: String, schema: Schema? = null, sensitive: Boolean = false): Standard<ConfigObject> = StandardProperty(
key,
ConfigObject::class.java.simpleName,
{ config, path, _ -> config.getObject(path) },
{ config, path, _ -> config.getObjectList(path) },
sensitive,
schema
)
/** /**
* Returns a [Configuration.Property.Definition.Standard] with value of type [ENUM]. * Returns a [Configuration.Property.Definition.Standard] with value of type [ENUM].
* This property expects a value in the configuration matching one of the cases of [ENUM], as text, in uppercase. * This property expects a value in the configuration matching one of the cases of [ENUM], as text, in uppercase.
*/ */
fun <ENUM : Enum<ENUM>> enum(key: String, enumClass: KClass<ENUM>, sensitive: Boolean = false): Standard<ENUM> = StandardProperty(key, enumClass.java.simpleName, { conf: Config, propertyKey: String -> conf.getEnum(enumClass.java, propertyKey) }, { conf: Config, propertyKey: String -> conf.getEnumList(enumClass.java, propertyKey) }, sensitive) fun <ENUM : Enum<ENUM>> enum(key: String, enumClass: KClass<ENUM>, sensitive: Boolean = false): Standard<ENUM> = StandardProperty(
key,
enumClass.java.simpleName,
{ conf: Config, propertyKey: String, _ -> conf.getEnum(enumClass.java, propertyKey) },
{ conf: Config, propertyKey: String, _ -> conf.getEnumList(enumClass.java, propertyKey) },
sensitive
)
} }
} }
} }
@ -275,12 +288,7 @@ object Configuration {
*/ */
val properties: Set<Property.Definition<*>> val properties: Set<Property.Definition<*>>
/** override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue
* Validates target [Config] with default [Configuration.Validation.Options].
*/
fun validate(target: Config): Valid<Config> = validate(target, Configuration.Validation.Options.defaults)
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue
companion object { companion object {
@ -368,35 +376,35 @@ object Configuration {
override fun description() = schema.description() override fun description() = schema.description()
override fun validate(target: Config, options: Validation.Options) = schema.validate(target, options) override fun validate(target: Config, options: Options) = schema.validate(target, options)
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue) = schema.describe(configuration, serialiseValue) override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options) = schema.describe(configuration, serialiseValue, options)
final override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid<VALUE> = validate(configuration, options).mapValid(::parseValid) final override fun parse(configuration: Config, options: Options): Valid<VALUE> = validate(configuration, options).mapValid { parseValid(it, options) }
/** /**
* Implement to define further mapping and validation logic, assuming the underlying raw [Config] is correct in terms of this [Configuration.Specification]. * Implement to define further mapping and validation logic, assuming the underlying raw [Config] is correct in terms of this [Configuration.Specification].
*/ */
protected abstract fun parseValid(configuration: Config): Valid<VALUE> protected abstract fun parseValid(configuration: Config, options: Options): Valid<VALUE>
} }
object Validation {
/** /**
* [Config] validation options. * Validation and processing options.
* @property strict whether to raise unknown property keys as errors. * @property strict whether to raise unknown property keys as errors.
*/ */
data class Options(val strict: Boolean) { class Options(val strict: Boolean = false) {
companion object { companion object {
/** /**
* Default [Config] validation options, without [strict] parsing enabled. * Default [Config] options, without [strict] parsing enabled.
*/ */
val defaults: Configuration.Validation.Options = Options(strict = false) val defaults: Configuration.Options = Options()
} }
} }
object Validation {
/** /**
* Super-type for the errors raised by the parsing and validation of a [Config] object. * Super-type for the errors raised by the parsing and validation of a [Config] object.
* *
@ -531,7 +539,7 @@ object Configuration {
} }
/** /**
* Raised when a key-value pair appeared in the [Config] object without a matching property in the [Configuration.Schema], and [Configuration.Validation.Options.strict] was enabled. * Raised when a key-value pair appeared in the [Config] object without a matching property in the [Configuration.Schema], and [Configuration.Options.strict] was enabled.
*/ */
class Unknown private constructor(override val keyName: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, null, message(keyName), containingPath) { class Unknown private constructor(override val keyName: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, null, message(keyName), containingPath) {
@ -586,5 +594,5 @@ object Configuration {
/** /**
* Defines the ability to validate a [Config] object, producing a valid [Config] or a set of [Configuration.Validation.Error]. * Defines the ability to validate a [Config] object, producing a valid [Config] or a set of [Configuration.Validation.Error].
*/ */
interface Validator : net.corda.common.validation.internal.Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> interface Validator : net.corda.common.validation.internal.Validator<Config, Configuration.Validation.Error, Configuration.Options>
} }

View File

@ -5,10 +5,9 @@ import net.corda.common.validation.internal.Validated
import net.corda.common.validation.internal.Validated.Companion.invalid import net.corda.common.validation.internal.Validated.Companion.invalid
import net.corda.common.validation.internal.Validated.Companion.valid import net.corda.common.validation.internal.Validated.Companion.valid
internal class LongProperty(key: String, sensitive: Boolean = false) : StandardProperty<Long>(key, Long::class.javaObjectType.simpleName, Config::getLong, Config::getLongList, sensitive) { internal class LongProperty(key: String, sensitive: Boolean = false) : StandardProperty<Long>(key, Long::class.javaObjectType.simpleName, { config, path, _ -> config.getLong(path) }, { config, path, _ -> config.getLongList(path) }, sensitive) {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val validated = super.validate(target, options) val validated = super.validate(target, options)
if (validated.isValid && target.getValue(key).unwrapped().toString().contains(".")) { if (validated.isValid && target.getValue(key).unwrapped().toString().contains(".")) {
return invalid(ConfigException.WrongType(target.origin(), key, Long::class.javaObjectType.simpleName, Double::class.javaObjectType.simpleName).toValidationError(key, typeName)) return invalid(ConfigException.WrongType(target.origin(), key, Long::class.javaObjectType.simpleName, Double::class.javaObjectType.simpleName).toValidationError(key, typeName))
@ -17,9 +16,11 @@ internal class LongProperty(key: String, sensitive: Boolean = false) : StandardP
} }
} }
internal open class StandardProperty<TYPE : Any>(override val key: String, typeNameArg: String, private val extractSingleValue: (Config, String) -> TYPE, internal val extractListValue: (Config, String) -> List<TYPE>, override val isSensitive: Boolean = false, final override val schema: Configuration.Schema? = null) : Configuration.Property.Definition.Standard<TYPE> { typealias ValueSelector<T> = (Config, String, Configuration.Options) -> T
override fun valueIn(configuration: Config) = extractSingleValue.invoke(configuration, key) internal open class StandardProperty<TYPE : Any>(override val key: String, typeNameArg: String, private val extractSingleValue: ValueSelector<TYPE>, internal val extractListValue: ValueSelector<List<TYPE>>, override val isSensitive: Boolean = false, final override val schema: Configuration.Schema? = null) : Configuration.Property.Definition.Standard<TYPE> {
override fun valueIn(configuration: Config, options: Configuration.Options) = extractSingleValue.invoke(configuration, key, options)
override val typeName: String = schema?.let { "#${it.name ?: "Object@$key"}" } ?: typeNameArg override val typeName: String = schema?.let { "#${it.name ?: "Object@$key"}" } ?: typeNameArg
@ -29,20 +30,18 @@ internal open class StandardProperty<TYPE : Any>(override val key: String, typeN
override fun list(): Configuration.Property.Definition.RequiredList<TYPE> = ListProperty(this) override fun list(): Configuration.Property.Definition.RequiredList<TYPE> = ListProperty(this)
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue {
if (isSensitive) { if (isSensitive) {
return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue) return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue)
} }
return schema?.describe(configuration.getConfig(key), serialiseValue) ?: valueDescription(valueIn(configuration), serialiseValue) return schema?.describe(configuration.getConfig(key), serialiseValue, options) ?: valueDescription(valueIn(configuration, options), serialiseValue)
} }
override val isMandatory = true override val isMandatory = true
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> { override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val errors = mutableSetOf<Configuration.Validation.Error>() val errors = mutableSetOf<Configuration.Validation.Error>()
errors += errorsWhenExtractingValue(target) errors += errorsWhenExtractingValue(target, options)
if (errors.isEmpty()) { if (errors.isEmpty()) {
schema?.let { nestedSchema -> schema?.let { nestedSchema ->
val nestedConfig: Config? = target.getConfig(key) val nestedConfig: Config? = target.getConfig(key)
@ -61,15 +60,19 @@ private class ListProperty<TYPE : Any>(delegate: StandardProperty<TYPE>) : Requi
override val typeName: String = "List<${delegate.typeName}>" override val typeName: String = "List<${delegate.typeName}>"
override fun valueIn(configuration: Config): List<TYPE> = delegate.extractListValue.invoke(configuration, key) override fun valueIn(configuration: Config, options: Configuration.Options): List<TYPE> = delegate.extractListValue.invoke(configuration, key, options)
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val errors = mutableSetOf<Configuration.Validation.Error>() val errors = mutableSetOf<Configuration.Validation.Error>()
errors += errorsWhenExtractingValue(target) errors += errorsWhenExtractingValue(target, options)
if (errors.isEmpty()) { if (errors.isEmpty()) {
delegate.schema?.let { schema -> delegate.schema?.let { schema ->
errors += valueIn(target).asSequence().map { element -> element as ConfigObject }.map(ConfigObject::toConfig).mapIndexed { index, targetConfig -> schema.validate(targetConfig, options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }.fold(emptyList<Configuration.Validation.Error>()) { one, other -> one + other }.toSet() errors += valueIn(target, options).asSequence()
.map { element -> element as ConfigObject }
.map(ConfigObject::toConfig)
.mapIndexed { index, targetConfig -> schema.validate(targetConfig, options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }
.fold(emptyList<Configuration.Validation.Error>()) { one, other -> one + other }
.toSet()
} }
} }
return Validated.withResult(target, errors) return Validated.withResult(target, errors)
@ -77,17 +80,16 @@ private class ListProperty<TYPE : Any>(delegate: StandardProperty<TYPE>) : Requi
override fun <MAPPED> mapValid(mappedTypeName: String, convert: (List<TYPE>) -> Validated<MAPPED, Configuration.Validation.Error>): Configuration.Property.Definition.Required<MAPPED> = ListMappingProperty(this, mappedTypeName, convert) override fun <MAPPED> mapValid(mappedTypeName: String, convert: (List<TYPE>) -> Validated<MAPPED, Configuration.Validation.Error>): Configuration.Property.Definition.Required<MAPPED> = ListMappingProperty(this, mappedTypeName, convert)
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue {
if (isSensitive) { if (isSensitive) {
return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue) return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue)
} }
return when { return when {
delegate.schema != null -> { delegate.schema != null -> {
val elementsDescription = valueIn(configuration).asSequence().map { it as ConfigObject }.map(ConfigObject::toConfig).map { delegate.schema.describe(it, serialiseValue) }.toList() val elementsDescription = valueIn(configuration, options).asSequence().map { it as ConfigObject }.map(ConfigObject::toConfig).map { delegate.schema.describe(it, serialiseValue, options) }.toList()
ConfigValueFactory.fromIterable(elementsDescription) ConfigValueFactory.fromIterable(elementsDescription)
} }
else -> valueDescription(valueIn(configuration), serialiseValue) else -> valueDescription(valueIn(configuration, options), serialiseValue)
} }
} }
@ -106,16 +108,17 @@ private class OptionalPropertyWithDefault<TYPE>(delegate: Configuration.Property
override val typeName: String = delegate.typeName.removeSuffix("?") override val typeName: String = delegate.typeName.removeSuffix("?")
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue? = delegate.describe(configuration, serialiseValue) ?: valueDescription(if (isSensitive) Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER else defaultValue, serialiseValue) override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue? = delegate.describe(configuration, serialiseValue, options) ?: valueDescription(if (isSensitive) Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER else defaultValue, serialiseValue)
override fun valueIn(configuration: Config): TYPE = delegate.valueIn(configuration) ?: defaultValue override fun valueIn(configuration: Config, options: Configuration.Options): TYPE = delegate.valueIn(configuration, options) ?: defaultValue
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> = delegate.validate(target, options) override fun validate(target: Config, options: Configuration.Options): Valid<Config> = delegate.validate(target, options)
} }
private class FunctionalProperty<TYPE, MAPPED>(delegate: Configuration.Property.Definition.Standard<TYPE>, private val mappedTypeName: String, internal val extractListValue: (Config, String) -> List<TYPE>, private val convert: (TYPE) -> Valid<MAPPED>) : RequiredDelegatedProperty<MAPPED, Configuration.Property.Definition.Standard<TYPE>>(delegate), Configuration.Property.Definition.Standard<MAPPED> { private class FunctionalProperty<TYPE, MAPPED>(delegate: Configuration.Property.Definition.Standard<TYPE>, private val mappedTypeName: String, internal val extractListValue: ValueSelector<List<TYPE>>, private val convert: (TYPE) -> Valid<MAPPED>)
: RequiredDelegatedProperty<MAPPED, Configuration.Property.Definition.Standard<TYPE>>(delegate), Configuration.Property.Definition.Standard<MAPPED> {
override fun valueIn(configuration: Config) = convert.invoke(delegate.valueIn(configuration)).value() override fun valueIn(configuration: Config, options: Configuration.Options) = convert.invoke(delegate.valueIn(configuration, options)).value()
override val typeName: String = if (super.typeName == "#$mappedTypeName") super.typeName else "$mappedTypeName(${super.typeName})" override val typeName: String = if (super.typeName == "#$mappedTypeName") super.typeName else "$mappedTypeName(${super.typeName})"
@ -123,29 +126,31 @@ private class FunctionalProperty<TYPE, MAPPED>(delegate: Configuration.Property.
override fun list(): Configuration.Property.Definition.RequiredList<MAPPED> = FunctionalListProperty(this) override fun list(): Configuration.Property.Definition.RequiredList<MAPPED> = FunctionalListProperty(this)
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> { override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val errors = mutableSetOf<Configuration.Validation.Error>() val errors = mutableSetOf<Configuration.Validation.Error>()
errors += delegate.validate(target, options).errors errors += delegate.validate(target, options).errors
if (errors.isEmpty()) { if (errors.isEmpty()) {
errors += convert.invoke(delegate.valueIn(target)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors errors += convert.invoke(delegate.valueIn(target, options)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors
} }
return Validated.withResult(target, errors) return Validated.withResult(target, errors)
} }
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue) = delegate.describe(configuration, serialiseValue) override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options) = delegate.describe(configuration, serialiseValue, options)
} }
private class FunctionalListProperty<RAW, TYPE>(delegate: FunctionalProperty<RAW, TYPE>) : RequiredDelegatedProperty<List<TYPE>, FunctionalProperty<RAW, TYPE>>(delegate), Configuration.Property.Definition.RequiredList<TYPE> { private class FunctionalListProperty<RAW, TYPE>(delegate: FunctionalProperty<RAW, TYPE>) : RequiredDelegatedProperty<List<TYPE>, FunctionalProperty<RAW, TYPE>>(delegate), Configuration.Property.Definition.RequiredList<TYPE> {
override val typeName: String = "List<${super.typeName}>" override val typeName: String = "List<${super.typeName}>"
override fun valueIn(configuration: Config): List<TYPE> = delegate.extractListValue.invoke(configuration, key).asSequence().map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }.map(ConfigObject::toConfig).map(delegate::valueIn).toList() override fun valueIn(configuration: Config, options: Configuration.Options): List<TYPE> = delegate.extractListValue.invoke(configuration, key, options).asSequence()
.map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> { .map(ConfigObject::toConfig)
.map { delegate.valueIn(it, options) }
.toList()
override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val list = try { val list = try {
delegate.extractListValue.invoke(target, key) delegate.extractListValue.invoke(target, key, options)
} catch (e: ConfigException) { } catch (e: ConfigException) {
if (isErrorExpected(e)) { if (isErrorExpected(e)) {
return invalid(e.toValidationError(key, typeName)) return invalid(e.toValidationError(key, typeName))
@ -153,7 +158,11 @@ private class FunctionalListProperty<RAW, TYPE>(delegate: FunctionalProperty<RAW
throw e throw e
} }
} }
val errors = list.asSequence().map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }.mapIndexed { index, value -> delegate.validate(value.toConfig(), options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }.fold(emptyList<Configuration.Validation.Error>()) { one, other -> one + other }.toSet() val errors = list.asSequence()
.map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }
.mapIndexed { index, value -> delegate.validate(value.toConfig(), options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }
.fold(emptyList<Configuration.Validation.Error>()) { one, other -> one + other }
.toSet()
return Validated.withResult(target, errors) return Validated.withResult(target, errors)
} }
@ -165,12 +174,11 @@ private class FunctionalListProperty<RAW, TYPE>(delegate: FunctionalProperty<RAW
} }
} }
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue {
if (isSensitive) { if (isSensitive) {
return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue) return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue)
} }
return delegate.schema?.let { schema -> valueDescription(valueIn(configuration).asSequence().map { element -> valueDescription(element, serialiseValue) }.map { it as ConfigObject }.map(ConfigObject::toConfig).map { schema.describe(it, serialiseValue) }.toList(), serialiseValue) } ?: valueDescription(valueIn(configuration), serialiseValue) return delegate.schema?.let { schema -> valueDescription(valueIn(configuration, options).asSequence() .map { element -> valueDescription(element, serialiseValue) } .map { it as ConfigObject } .map(ConfigObject::toConfig) .map { schema.describe(it, serialiseValue, options) } .toList(), serialiseValue) } ?: valueDescription(valueIn(configuration, options), serialiseValue)
} }
override fun <MAPPED> mapValid(mappedTypeName: String, convert: (List<TYPE>) -> Validated<MAPPED, Configuration.Validation.Error>): Configuration.Property.Definition.Required<MAPPED> = ListMappingProperty(this, mappedTypeName, convert) override fun <MAPPED> mapValid(mappedTypeName: String, convert: (List<TYPE>) -> Validated<MAPPED, Configuration.Validation.Error>): Configuration.Property.Definition.Required<MAPPED> = ListMappingProperty(this, mappedTypeName, convert)
@ -187,18 +195,16 @@ private class OptionalDelegatedProperty<TYPE>(private val delegate: Configuratio
override val typeName: String = "${delegate.typeName}?" override val typeName: String = "${delegate.typeName}?"
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue) = if (isSpecifiedBy(configuration)) delegate.describe(configuration, serialiseValue) else null override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options) = if (isSpecifiedBy(configuration)) delegate.describe(configuration, serialiseValue, options) else null
override fun valueIn(configuration: Config): TYPE? {
override fun valueIn(configuration: Config, options: Configuration.Options): TYPE? {
return when { return when {
isSpecifiedBy(configuration) -> delegate.valueIn(configuration) isSpecifiedBy(configuration) -> delegate.valueIn(configuration, options)
else -> null else -> null
} }
} }
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> { override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val result = delegate.validate(target, options) val result = delegate.validate(target, options)
val errors = result.errors val errors = result.errors
val missingValueError = errors.asSequence().filterIsInstance<Configuration.Validation.Error.MissingValue>().filter { it.pathAsString == key }.singleOrNull() val missingValueError = errors.asSequence().filterIsInstance<Configuration.Validation.Error.MissingValue>().filter { it.pathAsString == key }.singleOrNull()
@ -221,18 +227,17 @@ private abstract class RequiredDelegatedProperty<TYPE, DELEGATE : Configuration.
private class ListMappingProperty<TYPE, MAPPED>(private val delegate: Configuration.Property.Definition.RequiredList<TYPE>, private val mappedTypeName: String, private val convert: (List<TYPE>) -> Validated<MAPPED, Configuration.Validation.Error>) : Configuration.Property.Definition.Required<MAPPED> { private class ListMappingProperty<TYPE, MAPPED>(private val delegate: Configuration.Property.Definition.RequiredList<TYPE>, private val mappedTypeName: String, private val convert: (List<TYPE>) -> Validated<MAPPED, Configuration.Validation.Error>) : Configuration.Property.Definition.Required<MAPPED> {
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue? = delegate.describe(configuration, serialiseValue) override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue? = delegate.describe(configuration, serialiseValue, options)
override fun valueIn(configuration: Config) = convert.invoke(delegate.valueIn(configuration)).value() override fun valueIn(configuration: Config, options: Configuration.Options) = convert.invoke(delegate.valueIn(configuration, options)).value()
override fun optional(): Configuration.Property.Definition.Optional<MAPPED> = OptionalDelegatedProperty(this) override fun optional(): Configuration.Property.Definition.Optional<MAPPED> = OptionalDelegatedProperty(this)
override fun validate(target: Config, options: Configuration.Validation.Options): Validated<Config, Configuration.Validation.Error> { override fun validate(target: Config, options: Configuration.Options): Validated<Config, Configuration.Validation.Error> {
val errors = mutableSetOf<Configuration.Validation.Error>() val errors = mutableSetOf<Configuration.Validation.Error>()
errors += delegate.validate(target, options).errors errors += delegate.validate(target, options).errors
if (errors.isEmpty()) { if (errors.isEmpty()) {
errors += convert.invoke(delegate.valueIn(target)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors errors += convert.invoke(delegate.valueIn(target, options)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors
} }
return Validated.withResult(target, errors) return Validated.withResult(target, errors)
} }
@ -248,7 +253,6 @@ private class ListMappingProperty<TYPE, MAPPED>(private val delegate: Configurat
} }
fun ConfigException.toValidationError(keyName: String? = null, typeName: String): Configuration.Validation.Error { fun ConfigException.toValidationError(keyName: String? = null, typeName: String): Configuration.Validation.Error {
val toError = when (this) { val toError = when (this) {
is ConfigException.Missing -> Configuration.Validation.Error.MissingValue.Companion::of is ConfigException.Missing -> Configuration.Validation.Error.MissingValue.Companion::of
is ConfigException.WrongType -> Configuration.Validation.Error.WrongType.Companion::of is ConfigException.WrongType -> Configuration.Validation.Error.WrongType.Companion::of
@ -260,10 +264,9 @@ fun ConfigException.toValidationError(keyName: String? = null, typeName: String)
return toError.invoke(message!!, keyName, typeName, emptyList()) return toError.invoke(message!!, keyName, typeName, emptyList())
} }
private fun Configuration.Property.Definition<*>.errorsWhenExtractingValue(target: Config): Set<Configuration.Validation.Error> { private fun Configuration.Property.Definition<*>.errorsWhenExtractingValue(target: Config, options: Configuration.Options): Set<Configuration.Validation.Error> {
try { try {
valueIn(target) valueIn(target, options)
return emptySet() return emptySet()
} catch (exception: ConfigException) { } catch (exception: ConfigException) {
if (isErrorExpected(exception)) { if (isErrorExpected(exception)) {

View File

@ -16,7 +16,7 @@ internal class Schema(override val name: String?, unorderedProperties: Iterable<
} }
} }
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> { override fun validate(target: Config, options: Configuration.Options): Valid<Config> {
val propertyErrors = properties.flatMap { property -> val propertyErrors = properties.flatMap { property ->
property.validate(target, options).errors property.validate(target, options).errors
@ -47,9 +47,9 @@ internal class Schema(override val name: String?, unorderedProperties: Iterable<
return description.toString() return description.toString()
} }
override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue {
return properties.asSequence().map { it.key to it.describe(configuration, serialiseValue) }.filter { it.second != null }.fold(configObject()) { config, (key, value) -> config.withValue(key, value) } return properties.asSequence().map { it.key to it.describe(configuration, serialiseValue, options) }.filter { it.second != null }.fold(configObject()) { config, (key, value) -> config.withValue(key, value) }
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@ -21,7 +21,11 @@ inline fun <TYPE, reified MAPPED> Configuration.Property.Definition.RequiredList
inline fun <TYPE, reified MAPPED> Configuration.Property.Definition.RequiredList<TYPE>.map(noinline convert: (List<TYPE>) -> MAPPED): Configuration.Property.Definition.Required<MAPPED> = map(MAPPED::class.java.simpleName, convert) inline fun <TYPE, reified MAPPED> Configuration.Property.Definition.RequiredList<TYPE>.map(noinline convert: (List<TYPE>) -> MAPPED): Configuration.Property.Definition.Required<MAPPED> = map(MAPPED::class.java.simpleName, convert)
operator fun <TYPE> Config.get(property: Configuration.Property.Definition<TYPE>): TYPE = property.valueIn(this) fun Config.withOptions(options: Configuration.Options) = ConfigurationWithOptions(this, options)
data class ConfigurationWithOptions(private val config: Config, private val options: Configuration.Options) {
operator fun <TYPE> get(property: Configuration.Value.Extractor<TYPE>): TYPE = property.valueIn(config, options)
}
inline fun <reified NESTED : Any> Configuration.Specification<*>.nested(specification: Configuration.Specification<NESTED>, key: String? = null, sensitive: Boolean = false): PropertyDelegate.Standard<NESTED> = nestedObject(schema = specification, key = key, sensitive = sensitive).map(ConfigObject::toConfig).mapValid { value -> specification.parse(value) } inline fun <reified NESTED : Any> Configuration.Specification<*>.nested(specification: Configuration.Specification<NESTED>, key: String? = null, sensitive: Boolean = false): PropertyDelegate.Standard<NESTED> = nestedObject(schema = specification, key = key, sensitive = sensitive).map(ConfigObject::toConfig).mapValid { value -> specification.parse(value) }
@ -66,15 +70,6 @@ internal typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Er
internal fun <TYPE> valid(target: TYPE) = Validated.valid<TYPE, Configuration.Validation.Error>(target) internal fun <TYPE> valid(target: TYPE) = Validated.valid<TYPE, Configuration.Validation.Error>(target)
/**
* Value extracted from a configuration file is a function of the actual value specified and configuration options.
* E.g. password value may be stored in the encrypted form rather than in a clear text.
*/
data class ConfigurationWithOptions(private val config: Config, private val options: Configuration.Validation.Options) {
operator fun <TYPE> get(property: Configuration.Property.Definition<TYPE>): TYPE = property.valueIn(config)
operator fun <TYPE> get(property: Configuration.Value.Extractor<TYPE>): TYPE = property.valueIn(config)
}
/** /**
* Helper interface to mark objects that will have [ConfigurationWithOptions] in them. * Helper interface to mark objects that will have [ConfigurationWithOptions] in them.
*/ */

View File

@ -6,21 +6,17 @@ import net.corda.common.configuration.parsing.internal.Valid
import net.corda.common.configuration.parsing.internal.valid import net.corda.common.configuration.parsing.internal.valid
internal class VersionExtractor(versionPath: String, versionDefaultValue: Int) : Configuration.Version.Extractor { internal class VersionExtractor(versionPath: String, versionDefaultValue: Int) : Configuration.Version.Extractor {
private val containingPath = versionPath.split(".").let { if (it.size > 1) it.subList(0, it.size - 1) else null } private val containingPath = versionPath.split(".").let { if (it.size > 1) it.subList(0, it.size - 1) else null }
private val key = versionPath.split(".").last() private val key = versionPath.split(".").last()
private val spec = Spec(key, versionDefaultValue, containingPath?.joinToString(".")) private val spec = Spec(key, versionDefaultValue, containingPath?.joinToString("."))
override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid<Int> { override fun parse(configuration: Config, options: Configuration.Options): Valid<Int> {
return spec.parse(configuration) return spec.parse(configuration)
} }
private class Spec(key: String, versionDefaultValue: Int, prefix: String?) : Configuration.Specification<Int>("Version", prefix) { private class Spec(key: String, versionDefaultValue: Int, prefix: String?) : Configuration.Specification<Int>("Version", prefix) {
private val version by int(key = key).optional().withDefaultValue(versionDefaultValue) private val version by int(key = key).optional().withDefaultValue(versionDefaultValue)
override fun parseValid(configuration: Config, options: Configuration.Options) = valid(version.valueIn(configuration, options))
override fun parseValid(configuration: Config) = valid(version.valueIn(configuration))
} }
} }

View File

@ -21,8 +21,8 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isTrue() assertThat(property.isMandatory).isTrue()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThat(property.valueIn(configuration)).isEqualTo(value) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value)
assertThat(configuration[property]).isEqualTo(value) assertThat(configuration.withOptions(Configuration.Options.defaults)[property]).isEqualTo(value)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -38,7 +38,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isTrue() assertThat(property.isMandatory).isTrue()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThatThrownBy { property.valueIn(configuration) }.isInstanceOf(ConfigException.WrongType::class.java) assertThatThrownBy { property.valueIn(configuration, Configuration.Options.defaults) }.isInstanceOf(ConfigException.WrongType::class.java)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -54,7 +54,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isTrue() assertThat(property.isMandatory).isTrue()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThat(property.valueIn(configuration)).isEqualTo(value) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -70,7 +70,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isTrue() assertThat(property.isMandatory).isTrue()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThat(property.valueIn(configuration)).isEqualTo(value.max()) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value.max())
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -85,7 +85,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThat(property.valueIn(configuration)).isEqualTo(null) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(null)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -101,7 +101,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isTrue() assertThat(property.isMandatory).isTrue()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThat(property.valueIn(configuration)).isEqualTo(value.max()) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value.max())
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -116,7 +116,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThat(property.valueIn(configuration)).isEqualTo(null) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(null)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -132,7 +132,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThat(property.valueIn(configuration)).isEqualTo(value) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -147,7 +147,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThat(property.valueIn(configuration)).isNull() assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isNull()
} }
@ -164,7 +164,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThat(property.valueIn(configuration)).isEqualTo(defaultValue) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(defaultValue)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -179,7 +179,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isTrue() assertThat(property.isMandatory).isTrue()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThatThrownBy { property.valueIn(configuration) }.isInstanceOf(ConfigException.Missing::class.java) assertThatThrownBy { property.valueIn(configuration, Configuration.Options.defaults) }.isInstanceOf(ConfigException.Missing::class.java)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -195,7 +195,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThat(property.valueIn(configuration)).isEqualTo(value) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -211,7 +211,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue()
assertThatThrownBy { property.valueIn(configuration) }.isInstanceOf(ConfigException.WrongType::class.java) assertThatThrownBy { property.valueIn(configuration, Configuration.Options.defaults) }.isInstanceOf(ConfigException.WrongType::class.java)
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -226,7 +226,7 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThat(property.valueIn(configuration)).isNull() assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isNull()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -242,6 +242,6 @@ class PropertyTest {
assertThat(property.key).isEqualTo(key) assertThat(property.key).isEqualTo(key)
assertThat(property.isMandatory).isFalse() assertThat(property.isMandatory).isFalse()
assertThat(property.isSpecifiedBy(configuration)).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse()
assertThat(property.valueIn(configuration)).isEqualTo(defaultValue) assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(defaultValue)
} }
} }

View File

@ -15,7 +15,7 @@ class PropertyValidationTest {
val property = Configuration.Property.Definition.long(key) val property = Configuration.Property.Definition.long(key)
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
@ -34,7 +34,7 @@ class PropertyValidationTest {
val property = Configuration.Property.Definition.long(key) val property = Configuration.Property.Definition.long(key)
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
@ -53,7 +53,7 @@ class PropertyValidationTest {
val property = Configuration.Property.Definition.long(key).list() val property = Configuration.Property.Definition.long(key).list()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
@ -72,7 +72,7 @@ class PropertyValidationTest {
val property = Configuration.Property.Definition.long(key).list() val property = Configuration.Property.Definition.long(key).list()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
@ -94,7 +94,7 @@ class PropertyValidationTest {
val property = Configuration.Property.Definition.long(key).list().mapValid(::parseMax) val property = Configuration.Property.Definition.long(key).list().mapValid(::parseMax)
assertThat(property.validate(configuration).errors).isEmpty() assertThat(property.validate(configuration, Configuration.Options.defaults).errors).isEmpty()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -114,7 +114,7 @@ class PropertyValidationTest {
val property = Configuration.Property.Definition.long(key).list().mapValid(::parseMax) val property = Configuration.Property.Definition.long(key).list().mapValid(::parseMax)
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.BadValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.BadValue::class.java) { error ->
@ -134,7 +134,7 @@ class PropertyValidationTest {
val configuration = configObject(key to false).toConfig() val configuration = configObject(key to false).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error ->
@ -154,7 +154,7 @@ class PropertyValidationTest {
val configuration = configObject(key to 1.2).toConfig() val configuration = configObject(key to 1.2).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error ->
@ -174,7 +174,7 @@ class PropertyValidationTest {
val configuration = configObject(key to 1).toConfig() val configuration = configObject(key to 1).toConfig()
assertThat(property.validate(configuration).isValid).isTrue() assertThat(property.validate(configuration, Configuration.Options.defaults).isValid).isTrue()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -186,7 +186,7 @@ class PropertyValidationTest {
val configuration = configObject(key to listOf(false, true)).toConfig() val configuration = configObject(key to listOf(false, true)).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error ->
@ -206,7 +206,7 @@ class PropertyValidationTest {
val configuration = configObject(key to listOf(1, 2, 3)).toConfig() val configuration = configObject(key to listOf(1, 2, 3)).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error ->
@ -226,7 +226,7 @@ class PropertyValidationTest {
val configuration = configObject(key to 1).toConfig() val configuration = configObject(key to 1).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error ->
@ -249,7 +249,7 @@ class PropertyValidationTest {
val configuration = configObject(key to configObject(nestedKey to false)).toConfig() val configuration = configObject(key to configObject(nestedKey to false)).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error ->
@ -272,7 +272,7 @@ class PropertyValidationTest {
val configuration = configObject(key to configObject()).toConfig() val configuration = configObject(key to configObject()).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
@ -295,7 +295,7 @@ class PropertyValidationTest {
val configuration = configObject(key to configObject(nestedKey to null)).toConfig() val configuration = configObject(key to configObject(nestedKey to null)).toConfig()
assertThat(property.validate(configuration).errors).satisfies { errors -> assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors ->
assertThat(errors).hasSize(1) assertThat(errors).hasSize(1)
assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error ->
@ -317,7 +317,7 @@ class PropertyValidationTest {
val configuration = configObject(key to configObject(nestedKey to false)).toConfig() val configuration = configObject(key to configObject(nestedKey to false)).toConfig()
assertThat(property.validate(configuration).isValid).isTrue() assertThat(property.validate(configuration, Configuration.Options.defaults).isValid).isTrue()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -333,7 +333,7 @@ class PropertyValidationTest {
val configuration = configObject(key to value).toConfig() val configuration = configObject(key to value).toConfig()
assertThat(property.validate(configuration).isValid).isTrue() assertThat(property.validate(configuration, Configuration.Options.defaults).isValid).isTrue()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -350,7 +350,7 @@ class PropertyValidationTest {
val configuration = configObject(key to value).toConfig() val configuration = configObject(key to value).toConfig()
val result = property.validate(configuration) val result = property.validate(configuration, Configuration.Options.defaults)
assertThat(result.errors).satisfies { errors -> assertThat(result.errors).satisfies { errors ->

View File

@ -29,7 +29,7 @@ class SchemaTest {
val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), double("prop5")) } val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), double("prop5")) }
val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) }
val result = barConfigSchema.validate(configuration) val result = barConfigSchema.validate(configuration, Configuration.Options.defaults)
println(barConfigSchema.description()) println(barConfigSchema.description())
assertThat(result.isValid).isTrue() assertThat(result.isValid).isTrue()
@ -59,17 +59,17 @@ class SchemaTest {
val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) } val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) }
val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) }
val strictErrors = barConfigSchema.validate(configuration, Configuration.Validation.Options(strict = true)).errors val strictErrors = barConfigSchema.validate(configuration, Configuration.Options(strict = true)).errors
assertThat(strictErrors).hasSize(2) assertThat(strictErrors).hasSize(2)
assertThat(strictErrors.filter { error -> error.keyName == "prop4" }).hasSize(1) assertThat(strictErrors.filter { error -> error.keyName == "prop4" }).hasSize(1)
assertThat(strictErrors.filter { error -> error.keyName == "prop6" }).hasSize(1) assertThat(strictErrors.filter { error -> error.keyName == "prop6" }).hasSize(1)
val errors = barConfigSchema.validate(configuration, Configuration.Validation.Options(strict = false)).errors val errors = barConfigSchema.validate(configuration, Configuration.Options(strict = false)).errors
assertThat(errors).isEmpty() assertThat(errors).isEmpty()
val errorsWithDefaultOptions = barConfigSchema.validate(configuration).errors val errorsWithDefaultOptions = barConfigSchema.validate(configuration, Configuration.Options.defaults).errors
assertThat(errorsWithDefaultOptions).isEmpty() assertThat(errorsWithDefaultOptions).isEmpty()
} }
@ -98,7 +98,7 @@ class SchemaTest {
val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) } val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) }
val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) }
val result = barConfigSchema.validate(configuration) val result = barConfigSchema.validate(configuration, Configuration.Options.defaults)
assertThat(result.isValid).isTrue() assertThat(result.isValid).isTrue()
} }
@ -127,7 +127,7 @@ class SchemaTest {
val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) } val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) }
val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) }
val errors = barConfigSchema.validate(configuration).errors val errors = barConfigSchema.validate(configuration, Configuration.Options.defaults).errors
errors.forEach(::println) errors.forEach(::println)
assertThat(errors).hasSize(2) assertThat(errors).hasSize(2)
@ -154,7 +154,7 @@ class SchemaTest {
val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), string("prop5", sensitive = true)) } val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), string("prop5", sensitive = true)) }
val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) }
val printedConfiguration = barConfigSchema.describe(configuration) val printedConfiguration = barConfigSchema.describe(configuration, options = Configuration.Options.defaults)
val description = printedConfiguration.serialize().also { println(it) } val description = printedConfiguration.serialize().also { println(it) }
@ -185,7 +185,7 @@ class SchemaTest {
val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), string("prop5", sensitive = true)) } val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), string("prop5", sensitive = true)) }
val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema).list()) } val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema).list()) }
val printedConfiguration = barConfigSchema.describe(configuration) val printedConfiguration = barConfigSchema.describe(configuration, options = Configuration.Options.defaults)
val description = printedConfiguration.serialize().also { println(it) } val description = printedConfiguration.serialize().also { println(it) }

View File

@ -16,7 +16,7 @@ class SpecificationTest {
val principal by string().mapValid(::parseAddress) val principal by string().mapValid(::parseAddress)
val admin by string().mapValid(::parseAddress) val admin by string().mapValid(::parseAddress)
override fun parseValid(configuration: Config) = valid(Addresses(configuration[principal], configuration[admin])) override fun parseValid(configuration: Config, options: Configuration.Options) = configuration.withOptions(options).let { valid(Addresses(it[principal], it[admin])) }
private fun parseAddress(rawValue: String): Valid<Address> { private fun parseAddress(rawValue: String): Valid<Address> {
@ -27,7 +27,7 @@ class SpecificationTest {
val useSsl by boolean() val useSsl by boolean()
val addresses by nested(AddressesSpec) val addresses by nested(AddressesSpec)
override fun parseValid(configuration: Config) = valid<RpcSettings>(RpcSettingsImpl(configuration[addresses], configuration[useSsl])) override fun parseValid(configuration: Config, options: Configuration.Options) = configuration.withOptions(options).let { valid<RpcSettings>(RpcSettingsImpl(it[addresses], it[useSsl])) }
} }
@Test(timeout=300_000) @Test(timeout=300_000)
@ -60,9 +60,9 @@ class SpecificationTest {
private val maxElement by long("elements").list().map { elements -> elements.max() } private val maxElement by long("elements").list().map { elements -> elements.max() }
override fun parseValid(configuration: Config): Valid<AtomicLong> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<AtomicLong> {
val config = configuration.withOptions(options)
return valid(AtomicLong(configuration[maxElement]!!)) return valid(AtomicLong(config[maxElement]!!))
} }
} }
@ -111,9 +111,9 @@ class SpecificationTest {
private val maxElement by long("elements").list().mapValid(::parseMax) private val maxElement by long("elements").list().mapValid(::parseMax)
override fun parseValid(configuration: Config): Valid<AtomicLong> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<AtomicLong> {
val config = configuration.withOptions(options)
return valid(AtomicLong(configuration[maxElement])) return valid(AtomicLong(config[maxElement]))
} }
} }
@ -159,7 +159,7 @@ class SpecificationTest {
@Suppress("unused") @Suppress("unused")
val myProp by string().list().optional() val myProp by string().list().optional()
override fun parseValid(configuration: Config) = valid(configuration[myProp]) override fun parseValid(configuration: Config, options: Configuration.Options) = configuration.withOptions(options).let { valid(it[myProp]) }
} }
assertThat(spec.properties).hasSize(1) assertThat(spec.properties).hasSize(1)

View File

@ -15,5 +15,5 @@ internal fun <VALUE> extractValueWithErrors(errors: Set<Configuration.Validation
internal fun <VALUE> extractValue(value: Valid<VALUE>) = object : Configuration.Value.Parser<VALUE> { internal fun <VALUE> extractValue(value: Valid<VALUE>) = object : Configuration.Value.Parser<VALUE> {
override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid<VALUE> = value override fun parse(configuration: Config, options: Configuration.Options): Valid<VALUE> = value
} }

View File

@ -2,9 +2,9 @@ package net.corda.nodeapi.internal.network
import com.typesafe.config.Config import com.typesafe.config.Config
import net.corda.common.configuration.parsing.internal.Configuration import net.corda.common.configuration.parsing.internal.Configuration
import net.corda.common.configuration.parsing.internal.get
import net.corda.common.configuration.parsing.internal.mapValid import net.corda.common.configuration.parsing.internal.mapValid
import net.corda.common.configuration.parsing.internal.nested import net.corda.common.configuration.parsing.internal.nested
import net.corda.common.configuration.parsing.internal.withOptions
import net.corda.common.validation.internal.Validated import net.corda.common.validation.internal.Validated
import net.corda.core.internal.noPackageOverlap import net.corda.core.internal.noPackageOverlap
import net.corda.core.internal.requirePackageValid import net.corda.core.internal.requirePackageValid
@ -17,7 +17,7 @@ import java.security.KeyStoreException
typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Error> typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Error>
fun Config.parseAsNetworkParametersConfiguration(options: Configuration.Validation.Options = Configuration.Validation.Options(strict = false)): fun Config.parseAsNetworkParametersConfiguration(options: Configuration.Options = Configuration.Options.defaults):
Valid<NetworkParametersOverrides> = NetworkParameterOverridesSpec.parse(this, options) Valid<NetworkParametersOverrides> = NetworkParameterOverridesSpec.parse(this, options)
internal fun <T> badValue(msg: String): Valid<T> = Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of(msg)).toSet()) internal fun <T> badValue(msg: String): Valid<T> = Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of(msg)).toSet())
@ -36,11 +36,12 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification<Netw
private val keystorePassword by string() private val keystorePassword by string()
private val keystoreAlias by string() private val keystoreAlias by string()
override fun parseValid(configuration: Config): Validated<PackageOwner, Configuration.Validation.Error> { override fun parseValid(configuration: Config, options: Configuration.Options): Validated<PackageOwner, Configuration.Validation.Error> {
val suppliedKeystorePath = configuration[keystore] val config = configuration.withOptions(options)
val keystorePassword = configuration[keystorePassword] val suppliedKeystorePath = config[keystore]
val keystorePassword = config[keystorePassword]
return try { return try {
val javaPackageName = configuration[packageName] val javaPackageName = config[packageName]
val absoluteKeystorePath = if (suppliedKeystorePath.isAbsolute) { val absoluteKeystorePath = if (suppliedKeystorePath.isAbsolute) {
suppliedKeystorePath suppliedKeystorePath
} else { } else {
@ -49,10 +50,10 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification<Netw
}.toAbsolutePath() }.toAbsolutePath()
val ks = loadKeyStore(absoluteKeystorePath, keystorePassword) val ks = loadKeyStore(absoluteKeystorePath, keystorePassword)
return try { return try {
val publicKey = ks.getCertificate(configuration[keystoreAlias]).publicKey val publicKey = ks.getCertificate(config[keystoreAlias]).publicKey
valid(PackageOwner(javaPackageName, publicKey)) valid(PackageOwner(javaPackageName, publicKey))
} catch (kse: KeyStoreException) { } catch (kse: KeyStoreException) {
badValue("Keystore has not been initialized for alias ${configuration[keystoreAlias]}.") badValue("Keystore has not been initialized for alias ${config[keystoreAlias]}")
} }
} catch (kse: KeyStoreException) { } catch (kse: KeyStoreException) {
badValue("Password is incorrect or the key store is damaged for keyStoreFilePath: $suppliedKeystorePath.") badValue("Password is incorrect or the key store is damaged for keyStoreFilePath: $suppliedKeystorePath.")
@ -79,8 +80,9 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification<Netw
} }
} }
override fun parseValid(configuration: Config): Valid<NetworkParametersOverrides> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<NetworkParametersOverrides> {
val packageOwnership = configuration[packageOwnership] val config = configuration.withOptions(options)
val packageOwnership = config[packageOwnership]
if (packageOwnership != null && !noPackageOverlap(packageOwnership.map { it.javaPackageName })) { if (packageOwnership != null && !noPackageOverlap(packageOwnership.map { it.javaPackageName })) {
return Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of( return Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of(
"Package namespaces must not overlap", "Package namespaces must not overlap",
@ -89,11 +91,11 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification<Netw
)).toSet()) )).toSet())
} }
return valid(NetworkParametersOverrides( return valid(NetworkParametersOverrides(
minimumPlatformVersion = configuration[minimumPlatformVersion], minimumPlatformVersion = config[minimumPlatformVersion],
maxMessageSize = configuration[maxMessageSize], maxMessageSize = config[maxMessageSize],
maxTransactionSize = configuration[maxTransactionSize], maxTransactionSize = config[maxTransactionSize],
packageOwnership = packageOwnership, packageOwnership = packageOwnership,
eventHorizon = configuration[eventHorizon] eventHorizon = config[eventHorizon]
)) ))
} }

View File

@ -49,7 +49,7 @@ open class SharedNodeCmdLineOptions {
var devMode: Boolean? = null var devMode: Boolean? = null
open fun parseConfiguration(configuration: Config): Valid<NodeConfiguration> { open fun parseConfiguration(configuration: Config): Valid<NodeConfiguration> {
val option = Configuration.Validation.Options(strict = unknownConfigKeysPolicy == UnknownConfigKeysPolicy.FAIL) val option = Configuration.Options(strict = unknownConfigKeysPolicy == UnknownConfigKeysPolicy.FAIL)
return configuration.parseAsNodeConfiguration(option) return configuration.parseAsNodeConfiguration(option)
} }

View File

@ -26,7 +26,7 @@ internal class ValidateConfigurationCli : CliWrapperBase("validate-configuration
return "for path: \"$pathAsString\": $message" return "for path: \"$pathAsString\": $message"
} }
internal fun logRawConfig(config: Config) = logger.info("Actual configuration:\n${V1NodeConfigurationSpec.describe(config, Any?::toConfigValue).render(configRenderingOptions)}") internal fun logRawConfig(config: Config) = logger.info("Actual configuration:\n${V1NodeConfigurationSpec.describe(config, Any?::toConfigValue, Configuration.Options()).render(configRenderingOptions)}")
} }
@Mixin @Mixin

View File

@ -107,7 +107,7 @@ object ConfigHelper {
newKey.let { key -> newKey.let { key ->
val cfg = ConfigFactory.parseMap(mapOf(key to it.value)) val cfg = ConfigFactory.parseMap(mapOf(key to it.value))
val result = V1NodeConfigurationSpec.validate(cfg, Configuration.Validation.Options(strict = true)) val result = V1NodeConfigurationSpec.validate(cfg, Configuration.Options(strict = true))
val isInvalidProperty = result.errors.any { err -> err is Configuration.Validation.Error.Unknown } val isInvalidProperty = result.errors.any { err -> err is Configuration.Validation.Error.Unknown }
if (isInvalidProperty) { if (isInvalidProperty) {

View File

@ -217,7 +217,7 @@ data class FlowTimeoutConfiguration(
internal typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Error> internal typealias Valid<TARGET> = Validated<TARGET, Configuration.Validation.Error>
fun Config.parseAsNodeConfiguration(options: Configuration.Validation.Options = Configuration.Validation.Options(strict = true)): Valid<NodeConfiguration> = V1NodeConfigurationSpec.parse(this, options) fun Config.parseAsNodeConfiguration(options: Configuration.Options = Configuration.Options(strict = true)): Valid<NodeConfiguration> = V1NodeConfigurationSpec.parse(this, options)
data class NodeH2Settings( data class NodeH2Settings(
val address: NetworkHostAndPort? val address: NetworkHostAndPort?

View File

@ -5,11 +5,11 @@ package net.corda.node.services.config.schema.v1
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigObject import com.typesafe.config.ConfigObject
import net.corda.common.configuration.parsing.internal.Configuration import net.corda.common.configuration.parsing.internal.Configuration
import net.corda.common.configuration.parsing.internal.get
import net.corda.common.configuration.parsing.internal.listOrEmpty import net.corda.common.configuration.parsing.internal.listOrEmpty
import net.corda.common.configuration.parsing.internal.map import net.corda.common.configuration.parsing.internal.map
import net.corda.common.configuration.parsing.internal.mapValid import net.corda.common.configuration.parsing.internal.mapValid
import net.corda.common.configuration.parsing.internal.nested import net.corda.common.configuration.parsing.internal.nested
import net.corda.common.configuration.parsing.internal.withOptions
import net.corda.common.validation.internal.Validated.Companion.invalid import net.corda.common.validation.internal.Validated.Companion.invalid
import net.corda.common.validation.internal.Validated.Companion.valid import net.corda.common.validation.internal.Validated.Companion.valid
import net.corda.core.context.AuthServiceId import net.corda.core.context.AuthServiceId
@ -55,11 +55,12 @@ internal object UserSpec : Configuration.Specification<User>("User") {
private val password by string(sensitive = true) private val password by string(sensitive = true)
private val permissions by string().listOrEmpty() private val permissions by string().listOrEmpty()
override fun parseValid(configuration: Config): Valid<User> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<User> {
val username = configuration[username] ?: configuration[user] val config = configuration.withOptions(options)
val username = config[username] ?: config[user]
return when (username) { return when (username) {
null -> invalid(Configuration.Validation.Error.MissingValue.forKey("username")) null -> invalid(Configuration.Validation.Error.MissingValue.forKey("username"))
else -> valid(User(username, configuration[password], configuration[permissions].toSet())) else -> valid(User(username, config[password], config[permissions].toSet()))
} }
} }
} }
@ -72,11 +73,12 @@ internal object SecurityConfigurationSpec : Configuration.Specification<Security
private val connection by nestedObject(sensitive = true).map(::toProperties).optional() private val connection by nestedObject(sensitive = true).map(::toProperties).optional()
private val users by nested(UserSpec).list().optional() private val users by nested(UserSpec).list().optional()
override fun parseValid(configuration: Config): Valid<SecurityConfiguration.AuthService.DataSource> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<SecurityConfiguration.AuthService.DataSource> {
val type = configuration[type] val config = configuration.withOptions(options)
val passwordEncryption = configuration[passwordEncryption] val type = config[type]
val connection = configuration[connection] val passwordEncryption = config[passwordEncryption]
val users = configuration[users] val connection = config[connection]
val users = config[users]
return when { return when {
type == AuthDataSourceType.INMEMORY && (users == null || connection != null) -> badValue("\"INMEMORY\" data source type requires \"users\" and cannot specify \"connection\"") type == AuthDataSourceType.INMEMORY && (users == null || connection != null) -> badValue("\"INMEMORY\" data source type requires \"users\" and cannot specify \"connection\"")
@ -91,15 +93,17 @@ internal object SecurityConfigurationSpec : Configuration.Specification<Security
private val expireAfterSecs by long().mapValid { value -> if (value >= 0) validValue(value) else badValue("cannot be less than 0'") } private val expireAfterSecs by long().mapValid { value -> if (value >= 0) validValue(value) else badValue("cannot be less than 0'") }
private val maxEntries by long().mapValid { value -> if (value >= 0) validValue(value) else badValue("cannot be less than 0'") } private val maxEntries by long().mapValid { value -> if (value >= 0) validValue(value) else badValue("cannot be less than 0'") }
override fun parseValid(configuration: Config): Valid<SecurityConfiguration.AuthService.Options.Cache> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<SecurityConfiguration.AuthService.Options.Cache> {
return valid(SecurityConfiguration.AuthService.Options.Cache(configuration[expireAfterSecs], configuration[maxEntries])) val config = configuration.withOptions(options)
return valid(SecurityConfiguration.AuthService.Options.Cache(config[expireAfterSecs], config[maxEntries]))
} }
} }
private val cache by nested(CacheSpec).optional() private val cache by nested(CacheSpec).optional()
override fun parseValid(configuration: Config): Valid<SecurityConfiguration.AuthService.Options> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<SecurityConfiguration.AuthService.Options> {
return valid(SecurityConfiguration.AuthService.Options(configuration[cache])) val config = configuration.withOptions(options)
return valid(SecurityConfiguration.AuthService.Options(config[cache]))
} }
} }
@ -107,21 +111,23 @@ internal object SecurityConfigurationSpec : Configuration.Specification<Security
private val id by string().map(::AuthServiceId).optional() private val id by string().map(::AuthServiceId).optional()
val options by nested(OptionsSpec).optional() val options by nested(OptionsSpec).optional()
override fun parseValid(configuration: Config): Valid<SecurityConfiguration.AuthService> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<SecurityConfiguration.AuthService> {
val dataSource = configuration[dataSource] val config = configuration.withOptions(options)
val id = configuration[id] ?: defaultAuthServiceId(dataSource.type) val dataSource = config[dataSource]
val options = configuration[options] val id = config[id] ?: defaultAuthServiceId(dataSource.type)
val authServiceOptions = config[this.options]
return when { return when {
dataSource.type == AuthDataSourceType.INMEMORY && options?.cache != null -> badValue("no cache supported for \"INMEMORY\" data provider") dataSource.type == AuthDataSourceType.INMEMORY && authServiceOptions?.cache != null -> badValue("no cache supported for \"INMEMORY\" data provider")
else -> valid(SecurityConfiguration.AuthService(dataSource, id, options)) else -> valid(SecurityConfiguration.AuthService(dataSource, id, authServiceOptions))
} }
} }
} }
private val authService by nested(AuthServiceSpec) private val authService by nested(AuthServiceSpec)
override fun parseValid(configuration: Config): Valid<SecurityConfiguration> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<SecurityConfiguration> {
return valid(SecurityConfiguration(configuration[authService])) val config = configuration.withOptions(options)
return valid(SecurityConfiguration(config[authService]))
} }
} }
@ -134,13 +140,15 @@ internal object DevModeOptionsSpec : Configuration.Specification<DevModeOptions>
private val bootstrapSource by string().optional() private val bootstrapSource by string().optional()
private val cordaSource by string().list() private val cordaSource by string().list()
override fun parseValid(configuration: Config): Valid<DJVMOptions> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<DJVMOptions> {
return valid(DJVMOptions(configuration[bootstrapSource], configuration[cordaSource])) val config = configuration.withOptions(options)
return valid(DJVMOptions(config[bootstrapSource], config[cordaSource]))
} }
} }
override fun parseValid(configuration: Config): Valid<DevModeOptions> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<DevModeOptions> {
return valid(DevModeOptions(configuration[disableCheckpointChecker], configuration[allowCompatibilityZone], configuration[djvm])) val config = configuration.withOptions(options)
return valid(DevModeOptions(config[disableCheckpointChecker], config[allowCompatibilityZone], config[djvm]))
} }
} }
@ -151,8 +159,9 @@ internal object NetworkServicesConfigSpec : Configuration.Specification<NetworkS
private val inferred by boolean().optional().withDefaultValue(false) private val inferred by boolean().optional().withDefaultValue(false)
private val csrToken by string(sensitive = true).optional() private val csrToken by string(sensitive = true).optional()
override fun parseValid(configuration: Config): Valid<NetworkServicesConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<NetworkServicesConfig> {
return valid(NetworkServicesConfig(configuration[doormanURL], configuration[networkMapURL], configuration[pnm], configuration[inferred], configuration[csrToken])) val config = configuration.withOptions(options)
return valid(NetworkServicesConfig(config[doormanURL], config[networkMapURL], config[pnm], config[inferred], config[csrToken]))
} }
} }
@ -160,22 +169,24 @@ internal object NetworkParameterAcceptanceSettingsSpec :
Configuration.Specification<NetworkParameterAcceptanceSettings>("NetworkParameterAcceptanceSettings") { Configuration.Specification<NetworkParameterAcceptanceSettings>("NetworkParameterAcceptanceSettings") {
private val autoAcceptEnabled by boolean().optional().withDefaultValue(true) private val autoAcceptEnabled by boolean().optional().withDefaultValue(true)
private val excludedAutoAcceptableParameters by string().listOrEmpty() private val excludedAutoAcceptableParameters by string().listOrEmpty()
override fun parseValid(configuration: Config): Valid<NetworkParameterAcceptanceSettings> { override fun parseValid(configuration: Config, options: Configuration.Options):
return valid(NetworkParameterAcceptanceSettings(configuration[autoAcceptEnabled], Valid<NetworkParameterAcceptanceSettings> {
configuration[excludedAutoAcceptableParameters].toSet()) val config = configuration.withOptions(options)
return valid(NetworkParameterAcceptanceSettings(config[autoAcceptEnabled],
config[excludedAutoAcceptableParameters].toSet())
) )
} }
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
internal object CertChainPolicyConfigSpec : Configuration.Specification<CertChainPolicyConfig>("CertChainPolicyConfig") { internal object CertChainPolicyConfigSpec : Configuration.Specification<CertChainPolicyConfig>("CertChainPolicyConfig") {
private val role by string() private val role by string()
private val policy by enum(CertChainPolicyType::class) private val policy by enum(CertChainPolicyType::class)
private val trustedAliases by string().listOrEmpty() private val trustedAliases by string().listOrEmpty()
override fun parseValid(configuration: Config): Valid<CertChainPolicyConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<CertChainPolicyConfig> {
return valid(CertChainPolicyConfig(configuration[role], configuration[policy], configuration[trustedAliases].toSet())) val config = configuration.withOptions(options)
return valid(CertChainPolicyConfig(config[role], config[policy], config[trustedAliases].toSet()))
} }
} }
@ -184,8 +195,9 @@ internal object FlowTimeoutConfigurationSpec : Configuration.Specification<FlowT
private val maxRestartCount by int() private val maxRestartCount by int()
private val backoffBase by double() private val backoffBase by double()
override fun parseValid(configuration: Config): Valid<FlowTimeoutConfiguration> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<FlowTimeoutConfiguration> {
return valid(FlowTimeoutConfiguration(configuration[timeout], configuration[maxRestartCount], configuration[backoffBase])) val config = configuration.withOptions(options)
return valid(FlowTimeoutConfiguration(config[timeout], config[maxRestartCount], config[backoffBase]))
} }
} }
@ -198,8 +210,9 @@ internal object NotaryConfigSpec : Configuration.Specification<NotaryConfig>("No
private val raft by nested(RaftConfigSpec).optional() private val raft by nested(RaftConfigSpec).optional()
private val bftSMaRt by nested(BFTSmartConfigSpec).optional() private val bftSMaRt by nested(BFTSmartConfigSpec).optional()
override fun parseValid(configuration: Config): Valid<NotaryConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<NotaryConfig> {
return valid(NotaryConfig(configuration[validating], configuration[serviceLegalName], configuration[className], configuration[etaMessageThresholdSeconds], configuration[extraConfig], configuration[raft], configuration[bftSMaRt])) val config = configuration.withOptions(options)
return valid(NotaryConfig(config[validating], config[serviceLegalName], config[className], config[etaMessageThresholdSeconds], config[extraConfig], config[raft], config[bftSMaRt]))
} }
} }
@ -207,8 +220,9 @@ internal object RaftConfigSpec : Configuration.Specification<RaftConfig>("RaftCo
private val nodeAddress by string().mapValid(::toNetworkHostAndPort) private val nodeAddress by string().mapValid(::toNetworkHostAndPort)
private val clusterAddresses by string().mapValid(::toNetworkHostAndPort).listOrEmpty() private val clusterAddresses by string().mapValid(::toNetworkHostAndPort).listOrEmpty()
override fun parseValid(configuration: Config): Valid<RaftConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<RaftConfig> {
return valid(RaftConfig(configuration[nodeAddress], configuration[clusterAddresses])) val config = configuration.withOptions(options)
return valid(RaftConfig(config[nodeAddress], config[clusterAddresses]))
} }
} }
@ -218,19 +232,20 @@ internal object BFTSmartConfigSpec : Configuration.Specification<BFTSmartConfig>
private val debug by boolean().optional().withDefaultValue(false) private val debug by boolean().optional().withDefaultValue(false)
private val exposeRaces by boolean().optional().withDefaultValue(false) private val exposeRaces by boolean().optional().withDefaultValue(false)
override fun parseValid(configuration: Config): Valid<BFTSmartConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<BFTSmartConfig> {
return valid(BFTSmartConfig(configuration[replicaId], configuration[clusterAddresses], configuration[debug], configuration[exposeRaces])) val config = configuration.withOptions(options)
return valid(BFTSmartConfig(config[replicaId], config[clusterAddresses], config[debug], config[exposeRaces]))
} }
} }
internal object NodeRpcSettingsSpec : Configuration.Specification<NodeRpcSettings>("NodeRpcSettings") { internal object NodeRpcSettingsSpec : Configuration.Specification<NodeRpcSettings>("NodeRpcSettings") {
internal object BrokerRpcSslOptionsSpec : Configuration.Specification<BrokerRpcSslOptions>("BrokerRpcSslOptions") { internal object BrokerRpcSslOptionsSpec : Configuration.Specification<BrokerRpcSslOptions>("BrokerRpcSslOptions") {
private val keyStorePath by string().mapValid(::toPath) private val keyStorePath by string().mapValid(::toPath)
private val keyStorePassword by string(sensitive = true) private val keyStorePassword by string(sensitive = true)
override fun parseValid(configuration: Config): Valid<BrokerRpcSslOptions> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<BrokerRpcSslOptions> {
return valid(BrokerRpcSslOptions(configuration[keyStorePath], configuration[keyStorePassword])) val config = configuration.withOptions(options)
return valid(BrokerRpcSslOptions(config[keyStorePath], config[keyStorePassword]))
} }
} }
@ -240,18 +255,18 @@ internal object NodeRpcSettingsSpec : Configuration.Specification<NodeRpcSetting
private val useSsl by boolean().optional().withDefaultValue(NodeRpcSettings.Defaults.useSsl) private val useSsl by boolean().optional().withDefaultValue(NodeRpcSettings.Defaults.useSsl)
private val ssl by nested(BrokerRpcSslOptionsSpec).optional() private val ssl by nested(BrokerRpcSslOptionsSpec).optional()
override fun parseValid(configuration: Config): Valid<NodeRpcSettings> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<NodeRpcSettings> {
return valid(NodeRpcSettings(configuration[address], configuration[adminAddress], configuration[standAloneBroker], configuration[useSsl], configuration[ssl])) val config = configuration.withOptions(options)
return valid(NodeRpcSettings(config[address], config[adminAddress], config[standAloneBroker], config[useSsl], config[ssl]))
} }
} }
internal object SSHDConfigurationSpec : Configuration.Specification<SSHDConfiguration>("SSHDConfiguration") { internal object SSHDConfigurationSpec : Configuration.Specification<SSHDConfiguration>("SSHDConfiguration") {
private val port by int() private val port by int()
override fun parseValid(configuration: Config): Valid<SSHDConfiguration> = attempt<SSHDConfiguration, IllegalArgumentException> { SSHDConfiguration(configuration[port]) } override fun parseValid(configuration: Config, options: Configuration.Options): Valid<SSHDConfiguration> = attempt<SSHDConfiguration, IllegalArgumentException> { SSHDConfiguration(configuration.withOptions(options)[port]) }
} }
internal object DatabaseConfigSpec : Configuration.Specification<DatabaseConfig>("DatabaseConfig") { internal object DatabaseConfigSpec : Configuration.Specification<DatabaseConfig>("DatabaseConfig") {
private val initialiseSchema by boolean().optional().withDefaultValue(DatabaseConfig.Defaults.initialiseSchema) private val initialiseSchema by boolean().optional().withDefaultValue(DatabaseConfig.Defaults.initialiseSchema)
private val initialiseAppSchema by enum(SchemaInitializationType::class).optional().withDefaultValue(DatabaseConfig.Defaults.initialiseAppSchema) private val initialiseAppSchema by enum(SchemaInitializationType::class).optional().withDefaultValue(DatabaseConfig.Defaults.initialiseAppSchema)
@ -259,16 +274,18 @@ internal object DatabaseConfigSpec : Configuration.Specification<DatabaseConfig>
private val exportHibernateJMXStatistics by boolean().optional().withDefaultValue(DatabaseConfig.Defaults.exportHibernateJMXStatistics) private val exportHibernateJMXStatistics by boolean().optional().withDefaultValue(DatabaseConfig.Defaults.exportHibernateJMXStatistics)
private val mappedSchemaCacheSize by long().optional().withDefaultValue(DatabaseConfig.Defaults.mappedSchemaCacheSize) private val mappedSchemaCacheSize by long().optional().withDefaultValue(DatabaseConfig.Defaults.mappedSchemaCacheSize)
override fun parseValid(configuration: Config): Valid<DatabaseConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<DatabaseConfig> {
return valid(DatabaseConfig(configuration[initialiseSchema], configuration[initialiseAppSchema], configuration[transactionIsolationLevel], configuration[exportHibernateJMXStatistics], configuration[mappedSchemaCacheSize])) val config = configuration.withOptions(options)
return valid(DatabaseConfig(config[initialiseSchema], config[initialiseAppSchema], config[transactionIsolationLevel], config[exportHibernateJMXStatistics], config[mappedSchemaCacheSize]))
} }
} }
internal object NodeH2SettingsSpec : Configuration.Specification<NodeH2Settings>("NodeH2Settings") { internal object NodeH2SettingsSpec : Configuration.Specification<NodeH2Settings>("NodeH2Settings") {
private val address by string().mapValid(::toNetworkHostAndPort).optional() private val address by string().mapValid(::toNetworkHostAndPort).optional()
override fun parseValid(configuration: Config): Valid<NodeH2Settings> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<NodeH2Settings> {
return valid(NodeH2Settings(configuration[address])) val config = configuration.withOptions(options)
return valid(NodeH2Settings(config[address]))
} }
} }
@ -277,14 +294,16 @@ internal object FlowOverridesConfigSpec : Configuration.Specification<FlowOverri
private val initiator by string() private val initiator by string()
private val responder by string() private val responder by string()
override fun parseValid(configuration: Config): Valid<FlowOverride> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<FlowOverride> {
return valid(FlowOverride(configuration[initiator], configuration[responder])) val config = configuration.withOptions(options)
return valid(FlowOverride(config[initiator], config[responder]))
} }
} }
private val overrides by nested(FlowOverridesConfigSpec.SingleSpec).listOrEmpty() private val overrides by nested(FlowOverridesConfigSpec.SingleSpec).listOrEmpty()
override fun parseValid(configuration: Config): Valid<FlowOverrideConfig> { override fun parseValid(configuration: Config, options: Configuration.Options): Valid<FlowOverrideConfig> {
return valid(FlowOverrideConfig(configuration[overrides])) val config = configuration.withOptions(options)
return valid(FlowOverrideConfig(config[overrides]))
} }
} }

View File

@ -70,67 +70,68 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
@Suppress("unused") @Suppress("unused")
private val systemProperties by nestedObject().optional() private val systemProperties by nestedObject().optional()
override fun parseValid(configuration: Config): Validated<NodeConfiguration, Configuration.Validation.Error> { override fun parseValid(configuration: Config, options: Configuration.Options): Validated<NodeConfiguration, Configuration.Validation.Error> {
val config = configuration.withOptions(options)
val messagingServerExternal = configuration[messagingServerExternal] ?: Defaults.messagingServerExternal(configuration[messagingServerAddress]) val messagingServerExternal = config[messagingServerExternal] ?: Defaults.messagingServerExternal(config[messagingServerAddress])
val database = configuration[database] ?: Defaults.database(configuration[devMode]) val database = config[database] ?: Defaults.database(config[devMode])
val baseDirectoryPath = configuration[baseDirectory] val baseDirectoryPath = config[baseDirectory]
val cordappDirectories = configuration[cordappDirectories] ?: Defaults.cordappsDirectories(baseDirectoryPath) val cordappDirectories = config[cordappDirectories] ?: Defaults.cordappsDirectories(baseDirectoryPath)
val result = try { val result = try {
valid<NodeConfigurationImpl, Configuration.Validation.Error>(NodeConfigurationImpl( valid<NodeConfigurationImpl, Configuration.Validation.Error>(NodeConfigurationImpl(
baseDirectory = baseDirectoryPath, baseDirectory = baseDirectoryPath,
myLegalName = configuration[myLegalName], myLegalName = config[myLegalName],
emailAddress = configuration[emailAddress], emailAddress = config[emailAddress],
p2pAddress = configuration[p2pAddress], p2pAddress = config[p2pAddress],
keyStorePassword = configuration[keyStorePassword], keyStorePassword = config[keyStorePassword],
trustStorePassword = configuration[trustStorePassword], trustStorePassword = config[trustStorePassword],
crlCheckSoftFail = configuration[crlCheckSoftFail], crlCheckSoftFail = config[crlCheckSoftFail],
dataSourceProperties = configuration[dataSourceProperties], dataSourceProperties = config[dataSourceProperties],
rpcUsers = configuration[rpcUsers], rpcUsers = config[rpcUsers],
verifierType = configuration[verifierType], verifierType = config[verifierType],
flowTimeout = configuration[flowTimeout], flowTimeout = config[flowTimeout],
rpcSettings = configuration[rpcSettings], rpcSettings = config[rpcSettings],
messagingServerAddress = configuration[messagingServerAddress], messagingServerAddress = config[messagingServerAddress],
notary = configuration[notary], notary = config[notary],
flowOverrides = configuration[flowOverrides], flowOverrides = config[flowOverrides],
additionalP2PAddresses = configuration[additionalP2PAddresses], additionalP2PAddresses = config[additionalP2PAddresses],
additionalNodeInfoPollingFrequencyMsec = configuration[additionalNodeInfoPollingFrequencyMsec], additionalNodeInfoPollingFrequencyMsec = config[additionalNodeInfoPollingFrequencyMsec],
jmxMonitoringHttpPort = configuration[jmxMonitoringHttpPort], jmxMonitoringHttpPort = config[jmxMonitoringHttpPort],
security = configuration[security], security = config[security],
devMode = configuration[devMode], devMode = config[devMode],
devModeOptions = configuration[devModeOptions], devModeOptions = config[devModeOptions],
compatibilityZoneURL = configuration[compatibilityZoneURL], compatibilityZoneURL = config[compatibilityZoneURL],
networkServices = configuration[networkServices], networkServices = config[networkServices],
certificateChainCheckPolicies = configuration[certificateChainCheckPolicies], certificateChainCheckPolicies = config[certificateChainCheckPolicies],
messagingServerExternal = messagingServerExternal, messagingServerExternal = messagingServerExternal,
useTestClock = configuration[useTestClock], useTestClock = config[useTestClock],
lazyBridgeStart = configuration[lazyBridgeStart], lazyBridgeStart = config[lazyBridgeStart],
detectPublicIp = configuration[detectPublicIp], detectPublicIp = config[detectPublicIp],
sshd = configuration[sshd], sshd = config[sshd],
localShellAllowExitInSafeMode = configuration[localShellAllowExitInSafeMode], localShellAllowExitInSafeMode = config[localShellAllowExitInSafeMode],
localShellUnsafe = configuration[localShellUnsafe], localShellUnsafe = config[localShellUnsafe],
database = database, database = database,
noLocalShell = configuration[noLocalShell], noLocalShell = config[noLocalShell],
attachmentCacheBound = configuration[attachmentCacheBound], attachmentCacheBound = config[attachmentCacheBound],
extraNetworkMapKeys = configuration[extraNetworkMapKeys], extraNetworkMapKeys = config[extraNetworkMapKeys],
tlsCertCrlDistPoint = configuration[tlsCertCrlDistPoint], tlsCertCrlDistPoint = config[tlsCertCrlDistPoint],
tlsCertCrlIssuer = configuration[tlsCertCrlIssuer], tlsCertCrlIssuer = config[tlsCertCrlIssuer],
h2Settings = configuration[h2Settings], h2Settings = config[h2Settings],
flowMonitorPeriodMillis = configuration[flowMonitorPeriodMillis], flowMonitorPeriodMillis = config[flowMonitorPeriodMillis],
flowMonitorSuspensionLoggingThresholdMillis = configuration[flowMonitorSuspensionLoggingThresholdMillis], flowMonitorSuspensionLoggingThresholdMillis = config[flowMonitorSuspensionLoggingThresholdMillis],
jmxReporterType = configuration[jmxReporterType], jmxReporterType = config[jmxReporterType],
rpcAddress = configuration[rpcAddress], rpcAddress = config[rpcAddress],
transactionCacheSizeMegaBytes = configuration[transactionCacheSizeMegaBytes], transactionCacheSizeMegaBytes = config[transactionCacheSizeMegaBytes],
attachmentContentCacheSizeMegaBytes = configuration[attachmentContentCacheSizeMegaBytes], attachmentContentCacheSizeMegaBytes = config[attachmentContentCacheSizeMegaBytes],
h2port = configuration[h2port], h2port = config[h2port],
jarDirs = configuration[jarDirs], jarDirs = config[jarDirs],
cordappDirectories = cordappDirectories.map { baseDirectoryPath.resolve(it) }, cordappDirectories = cordappDirectories.map { baseDirectoryPath.resolve(it) },
cordappSignerKeyFingerprintBlacklist = configuration[cordappSignerKeyFingerprintBlacklist], cordappSignerKeyFingerprintBlacklist = config[cordappSignerKeyFingerprintBlacklist],
blacklistedAttachmentSigningKeys = configuration[blacklistedAttachmentSigningKeys], blacklistedAttachmentSigningKeys = config[blacklistedAttachmentSigningKeys],
networkParameterAcceptanceSettings = configuration[networkParameterAcceptanceSettings], networkParameterAcceptanceSettings = config[networkParameterAcceptanceSettings],
configurationWithOptions = ConfigurationWithOptions(configuration, Configuration.Validation.Options.defaults), configurationWithOptions = ConfigurationWithOptions(configuration, Configuration.Options.defaults),
flowExternalOperationThreadPoolSize = configuration[flowExternalOperationThreadPoolSize], flowExternalOperationThreadPoolSize = config[flowExternalOperationThreadPoolSize],
quasarExcludePackages = configuration[quasarExcludePackages] quasarExcludePackages = config[quasarExcludePackages]
)) ))
} catch (e: Exception) { } catch (e: Exception) {
return when (e) { return when (e) {