├── testsuite ├── extra │ ├── .env │ ├── config │ │ ├── application.yml │ │ ├── application.yaml │ │ └── application.properties │ └── src │ │ └── test │ │ ├── resources │ │ ├── application.yaml │ │ ├── application.yml │ │ ├── application.properties │ │ └── beans.xml │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── test │ │ ├── mapping │ │ ├── KotlinDefaultFunction.kt │ │ ├── KotlinDefaulltFunctionTest.kt │ │ └── KotlinMappingGetter.kt │ │ ├── builder │ │ ├── CustomConfigBuilder.java │ │ ├── CustomOneConfigBuilder.java │ │ └── CustomTwoConfigBuilder.java │ │ ├── provider │ │ ├── ProviderBeanWithList.java │ │ ├── ProviderAlone.java │ │ ├── InstanceAlone.java │ │ ├── ProviderBean.java │ │ └── Email.java │ │ ├── collections │ │ ├── KotlinCollectionsBean.kt │ │ ├── broken │ │ │ └── CollectionWithNoDefaultValueBean.java │ │ └── KotlinCollectionsBeanTest.java │ │ ├── converter │ │ ├── IntConverter.java │ │ └── ConverterBean.java │ │ ├── source │ │ ├── YamlPropertiesTest.java │ │ ├── OrdinalSourceTest.java │ │ ├── MultiplePropertiesConfigSourceTest.java │ │ └── MultipleProfilePropertiesConfigSourceTest.java │ │ ├── location │ │ ├── LocationConfigTest.java │ │ └── DotEnvTest.java │ │ └── secrets │ │ └── MultipleSecretHandlersTest.java └── pom.xml ├── CODEOWNERS ├── implementation └── src │ ├── test │ ├── resources │ │ ├── more.properties │ │ ├── additional.properties │ │ ├── META-INF │ │ │ └── services │ │ │ │ ├── io.smallrye.config.ConfigSourceInterceptor │ │ │ │ └── io.smallrye.config.ConfigSourceInterceptorFactory │ │ ├── config-values.properties │ │ ├── junit-platform.properties │ │ └── random.yml │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ ├── ServiceLoaderConfigSourceInterceptor.java │ │ ├── ServiceLoaderConfigSourceInterceptorFactory.java │ │ ├── SysPropConfigSourceTest.java │ │ ├── InterceptorChainTest.java │ │ ├── ConfigMappingLoaderParallelTest.java │ │ ├── NameIteratorTest.java │ │ ├── ConfigValueConfigSourceWrapperTest.java │ │ └── MultiValueTest.java │ └── main │ ├── resources │ └── META-INF │ │ └── services │ │ ├── io.smallrye.config.ConfigSourceFactory │ │ └── org.eclipse.microprofile.config.spi.ConfigProviderResolver │ └── java │ └── io │ └── smallrye │ └── config │ ├── ConfigMappingClassMapper.java │ ├── ConfigMappingMetadata.java │ ├── WithParentName.java │ ├── ConfigValidator.java │ ├── WithDefaults.java │ ├── WithDefault.java │ ├── WithName.java │ ├── ProfileConfigSourceFactory.java │ ├── WithConverter.java │ ├── PropertiesLocationConfigSourceFactory.java │ ├── Priorities.java │ ├── WithUnnamedKey.java │ ├── Expressions.java │ ├── SecretKeysHandler.java │ ├── SmallRyeConfigBuilderCustomizer.java │ ├── AbstractLocationConfigSourceFactory.java │ ├── Secret.java │ ├── SecretKeysConfigSourceInterceptor.java │ ├── ConfigSourceInterceptorContext.java │ ├── FallbackConfigSourceInterceptor.java │ ├── RelocateConfigSourceInterceptor.java │ ├── ConfigurableConfigSource.java │ ├── LoggingConfigSourceInterceptor.java │ ├── ConfigSourceContext.java │ ├── ConfigSourceInterceptorFactory.java │ ├── WithKeys.java │ ├── AbstractMappingConfigSourceInterceptor.java │ └── DotEnvConfigSourceProvider.java ├── sources ├── yaml │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ ├── more.yml │ │ │ │ └── additional.yml │ │ │ └── java │ │ │ │ └── io │ │ │ │ └── smallrye │ │ │ │ └── config │ │ │ │ └── source │ │ │ │ └── yaml │ │ │ │ ├── YamlConfigSourceLoaderTest.java │ │ │ │ └── BasicTest.java │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ ├── io.smallrye.config.ConfigSourceFactory │ │ │ │ └── org.eclipse.microprofile.config.spi.ConfigSourceProvider │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── source │ │ │ └── yaml │ │ │ └── YamlLocationConfigSourceFactory.java │ └── pom.xml ├── file-system │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── io │ │ │ │ └── smallrye │ │ │ │ └── config │ │ │ │ └── source │ │ │ │ └── file │ │ │ │ ├── configDir │ │ │ │ ├── myKey2 │ │ │ │ ├── config_ordinal │ │ │ │ ├── myKey1 │ │ │ │ ├── MyService_mp_rest_url │ │ │ │ └── OTHERSERVICE_MP_REST_URL │ │ │ │ └── configDir2 │ │ │ │ ├── myNewKey1 │ │ │ │ └── config_ordinal │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── io.smallrye.config.ConfigSourceFactory │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── source │ │ │ └── file │ │ │ ├── FileSystemLogging.java │ │ │ └── FileSystemConfigSourceFactory.java │ └── pom.xml ├── hocon │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ ├── expressions.conf │ │ │ │ ├── META-INF │ │ │ │ └── microprofile-config.conf │ │ │ │ └── list.conf │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ ├── io.smallrye.config.ConfigSourceFactory │ │ │ │ └── org.eclipse.microprofile.config.spi.ConfigSourceProvider │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── source │ │ │ └── hocon │ │ │ ├── HoconConfigSourceFactory.java │ │ │ └── HoconConfigSourceProvider.java │ └── pom.xml ├── keystore │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── keystore │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── io.smallrye.config.ConfigSourceFactory │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── source │ │ │ └── keystore │ │ │ └── KeyStoreConfig.java │ └── pom.xml └── zookeeper │ └── src │ ├── main │ ├── resources │ │ └── META-INF │ │ │ └── services │ │ │ └── io.smallrye.config.ConfigSourceFactory │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── source │ │ └── zookeeper │ │ ├── ZooKeeperConfigException.java │ │ ├── ZooKeeperMessages.java │ │ ├── ZooKeeperConfigSourceFactory.java │ │ └── ZooKeepperLogging.java │ └── test │ └── resources │ └── META-INF │ └── microprofile-config.properties ├── examples ├── interceptors │ └── src │ │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ ├── microprofile-config.properties │ │ │ │ └── services │ │ │ │ └── io.smallrye.config.ConfigSourceInterceptor │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── examples │ │ │ └── interceptors │ │ │ └── ExampleInterceptor.java │ │ └── test │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── examples │ │ └── interceptors │ │ └── ExampleInterceptorTest.java ├── expansion │ └── src │ │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── microprofile-config.properties │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── examples │ │ │ └── expansion │ │ │ ├── ExampleExpansion.java │ │ │ └── ExampleExpansionBean.java │ │ └── test │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── examples │ │ └── expansion │ │ ├── ExampleExpansionTest.java │ │ └── ExampleExpansionBeanTest.java ├── profiles │ └── src │ │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── microprofile-config.properties │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── examples │ │ │ └── profiles │ │ │ ├── ExampleProfiles.java │ │ │ └── ExampleProfilesBean.java │ │ └── test │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── examples │ │ └── profiles │ │ ├── ExampleProfilesTest.java │ │ └── ExampleProfilesBeanTest.java ├── mapping │ └── src │ │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ ├── services │ │ │ │ ├── org.eclipse.microprofile.config.spi.Converter │ │ │ │ └── io.smallrye.config.SmallRyeConfigFactory │ │ │ │ └── microprofile-config.properties │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── examples │ │ │ └── mapping │ │ │ ├── ServerMappingBean.java │ │ │ ├── ServerMapping.java │ │ │ ├── MappingSmallRyeConfigFactory.java │ │ │ ├── DurationConverter.java │ │ │ └── Server.java │ │ └── test │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── examples │ │ └── mapping │ │ ├── ServerMappingTest.java │ │ └── ServerMappingBeanTest.java ├── configmap │ ├── .kubernetes │ │ └── configmap-app.yml │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── examples │ │ │ └── configmap │ │ │ └── ConfigMapApp.java │ └── README.adoc └── pom.xml ├── documentation ├── src │ └── main │ │ ├── resources │ │ └── attributes.yaml │ │ └── docs │ │ ├── assets │ │ ├── favicon.ico │ │ ├── extra.css │ │ └── smallrye-icon.svg │ │ ├── config-sources │ │ ├── json.md │ │ ├── yaml.md │ │ ├── zookeeper.md │ │ ├── hocon.md │ │ └── filesystem.md │ │ ├── config │ │ ├── config-value.md │ │ ├── expressions.md │ │ ├── map-support.md │ │ ├── indexed-properties.md │ │ ├── secret-handlers │ │ │ └── jasypt.java │ │ ├── customizer.md │ │ └── configuration.md │ │ ├── extensions │ │ ├── logging.md │ │ ├── config-source-injection.md │ │ ├── relocate.md │ │ └── fallback.md │ │ └── index.md └── Pipfile ├── cdi └── src │ └── main │ ├── resources │ └── META-INF │ │ └── services │ │ └── jakarta.enterprise.inject.spi.Extension │ └── java │ └── io │ └── smallrye │ └── config │ └── inject │ ├── MetadataInjectionPoint.java │ ├── SecuritySupport.java │ └── ConfigException.java ├── .github ├── project.yml ├── dependabot.yml └── workflows │ ├── update-milestone.yml │ ├── prepare-release.yml │ ├── review-release.yml │ ├── release.yml │ ├── publish-tck.yml │ └── publish-docs.yml ├── utils ├── crypto │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ ├── key │ │ │ │ ├── keystore │ │ │ │ └── properties │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── io.smallrye.config.SecretKeysHandlerFactory │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── crypto │ │ │ └── AESGCMNoPaddingSecretKeysHandler.java │ └── pom.xml ├── jasypt │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── io.smallrye.config.SecretKeysHandlerFactory │ │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── jasypt │ │ │ ├── JasyptSecretKeysHandler.java │ │ │ └── JasyptSecretKeysHandlerFactory.java │ └── pom.xml ├── events │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── smallrye │ │ │ │ └── config │ │ │ │ └── events │ │ │ │ ├── Type.java │ │ │ │ ├── regex │ │ │ │ ├── Field.java │ │ │ │ ├── RegexLogging.java │ │ │ │ └── RegexFilter.java │ │ │ │ ├── TypeFilter.java │ │ │ │ ├── KeyFilter.java │ │ │ │ ├── SourceFilter.java │ │ │ │ └── ChangeEvent.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── beans.xml │ └── pom.xml └── cdi-provider │ ├── src │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── beans.xml │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── util │ │ │ └── injection │ │ │ ├── ConfigSourceMap.java │ │ │ └── Name.java │ └── test │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── util │ │ └── injection │ │ └── InjectionTestConfigFactory.java │ └── pom.xml ├── NOTICE ├── common ├── src │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── smallrye │ │ │ └── config │ │ │ └── common │ │ │ ├── AbstractConverter.java │ │ │ ├── AbstractSimpleDelegatingConverter.java │ │ │ ├── AbstractDelegatingConverter.java │ │ │ └── AbstractConfigSource.java │ └── test │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── common │ │ └── utils │ │ └── ConfigSourceUtilTest.java └── pom.xml ├── validator └── src │ ├── main │ └── java │ │ └── io │ │ └── smallrye │ │ └── config │ │ └── validator │ │ └── BeanValidationConfigValidatorImpl.java │ └── test │ └── java │ └── io │ └── smallrye │ └── config │ └── validator │ ├── external │ └── ValidationVisibilityTest.java │ └── KeyValuesConfigSource.java ├── message-ranges.txt └── .gitignore /testsuite/extra/.env: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testsuite/extra/config/application.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | .github @smallrye/config 2 | -------------------------------------------------------------------------------- /testsuite/extra/config/application.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testsuite/extra/config/application.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/resources/application.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /implementation/src/test/resources/more.properties: -------------------------------------------------------------------------------- 1 | more.prop=5678 2 | -------------------------------------------------------------------------------- /sources/yaml/src/test/resources/more.yml: -------------------------------------------------------------------------------- 1 | more: 2 | prop: 5678 3 | -------------------------------------------------------------------------------- /sources/yaml/src/test/resources/additional.yml: -------------------------------------------------------------------------------- 1 | my: 2 | prop: 1234 3 | -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir/myKey2: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /examples/interceptors/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | my.prop=1 2 | -------------------------------------------------------------------------------- /implementation/src/test/resources/additional.properties: -------------------------------------------------------------------------------- 1 | config_ordinal=500 2 | my.prop=1234 3 | -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir/config_ordinal: -------------------------------------------------------------------------------- 1 | 4567 -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir/myKey1: -------------------------------------------------------------------------------- 1 | myValue1 -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir2/myNewKey1: -------------------------------------------------------------------------------- 1 | myValue1 -------------------------------------------------------------------------------- /documentation/src/main/resources/attributes.yaml: -------------------------------------------------------------------------------- 1 | attributes: 2 | version: '${project.version}' 3 | -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir2/config_ordinal: -------------------------------------------------------------------------------- 1 | 4567 -------------------------------------------------------------------------------- /cdi/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension: -------------------------------------------------------------------------------- 1 | io.smallrye.config.inject.ConfigExtension -------------------------------------------------------------------------------- /.github/project.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Config 2 | release: 3 | current-version: 3.15.0 4 | next-version: 3.15.1-SNAPSHOT 5 | -------------------------------------------------------------------------------- /examples/expansion/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | my.prop=${another.prop} 2 | another.prop=expanded 3 | -------------------------------------------------------------------------------- /examples/profiles/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | my.prop=development 2 | %prod.my.prop=production 3 | -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir/MyService_mp_rest_url: -------------------------------------------------------------------------------- 1 | http://localhost:8080/my-service -------------------------------------------------------------------------------- /utils/crypto/src/test/resources/key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-config/HEAD/utils/crypto/src/test/resources/key -------------------------------------------------------------------------------- /sources/hocon/src/test/resources/expressions.conf: -------------------------------------------------------------------------------- 1 | { 2 | foo: "bar", 3 | expression: ${foo}, 4 | interceptor: "${foo}" 5 | } 6 | -------------------------------------------------------------------------------- /sources/file-system/src/test/resources/io/smallrye/config/source/file/configDir/OTHERSERVICE_MP_REST_URL: -------------------------------------------------------------------------------- 1 | http://localhost:8080/other-service -------------------------------------------------------------------------------- /utils/crypto/src/test/resources/keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-config/HEAD/utils/crypto/src/test/resources/keystore -------------------------------------------------------------------------------- /sources/hocon/src/test/resources/META-INF/microprofile-config.conf: -------------------------------------------------------------------------------- 1 | hello { 2 | world = 1 3 | foo { 4 | bar = "Hell yeah!" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /sources/keystore/src/test/resources/keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-config/HEAD/sources/keystore/src/test/resources/keystore -------------------------------------------------------------------------------- /utils/crypto/src/test/resources/properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-config/HEAD/utils/crypto/src/test/resources/properties -------------------------------------------------------------------------------- /documentation/src/main/docs/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-config/HEAD/documentation/src/main/docs/assets/favicon.ico -------------------------------------------------------------------------------- /implementation/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.PropertiesLocationConfigSourceFactory 2 | -------------------------------------------------------------------------------- /sources/hocon/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.hocon.HoconConfigSourceFactory 2 | -------------------------------------------------------------------------------- /examples/mapping/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter: -------------------------------------------------------------------------------- 1 | io.smallrye.config.examples.mapping.DurationConverter 2 | -------------------------------------------------------------------------------- /implementation/src/test/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptor: -------------------------------------------------------------------------------- 1 | io.smallrye.config.ServiceLoaderConfigSourceInterceptor 2 | -------------------------------------------------------------------------------- /sources/yaml/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.yaml.YamlLocationConfigSourceFactory 2 | -------------------------------------------------------------------------------- /utils/jasypt/src/main/resources/META-INF/services/io.smallrye.config.SecretKeysHandlerFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.jasypt.JasyptSecretKeysHandlerFactory 2 | -------------------------------------------------------------------------------- /examples/mapping/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.examples.mapping.MappingSmallRyeConfigFactory 2 | -------------------------------------------------------------------------------- /implementation/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigProviderResolver: -------------------------------------------------------------------------------- 1 | io.smallrye.config.SmallRyeConfigProviderResolver -------------------------------------------------------------------------------- /sources/file-system/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.file.FileSystemConfigSourceFactory 2 | -------------------------------------------------------------------------------- /sources/keystore/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.keystore.KeyStoreConfigSourceFactory 2 | -------------------------------------------------------------------------------- /sources/zookeeper/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.zookeeper.ZooKeeperConfigSourceFactory 2 | -------------------------------------------------------------------------------- /utils/crypto/src/main/resources/META-INF/services/io.smallrye.config.SecretKeysHandlerFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.crypto.AESGCMNoPaddingSecretKeysHandlerFactory 2 | -------------------------------------------------------------------------------- /examples/interceptors/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptor: -------------------------------------------------------------------------------- 1 | io.smallrye.config.examples.interceptors.ExampleInterceptor 2 | -------------------------------------------------------------------------------- /implementation/src/test/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory: -------------------------------------------------------------------------------- 1 | io.smallrye.config.ServiceLoaderConfigSourceInterceptorFactory 2 | -------------------------------------------------------------------------------- /sources/hocon/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.hocon.HoconConfigSourceProvider -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/Type.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events; 2 | 3 | public enum Type { 4 | NEW, 5 | REMOVE, 6 | UPDATE 7 | } -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2009-2017 Mark Struberg 2 | Copyright 2018 Red Hat, inc. 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /implementation/src/test/resources/config-values.properties: -------------------------------------------------------------------------------- 1 | my.prop=abc 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | secret=1234567\ 11 | 8 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | my.prop.20=abd 21 | -------------------------------------------------------------------------------- /documentation/src/main/docs/assets/extra.css: -------------------------------------------------------------------------------- 1 | /* Add stuff here if required */ 2 | 3 | .md-typeset__table { 4 | min-width: 100%; 5 | } 6 | 7 | .md-typeset table:not([class]) { 8 | display: table; 9 | } 10 | -------------------------------------------------------------------------------- /sources/yaml/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider: -------------------------------------------------------------------------------- 1 | io.smallrye.config.source.yaml.YamlConfigSourceLoader$InClassPath 2 | io.smallrye.config.source.yaml.YamlConfigSourceLoader$InFileSystem 3 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigMappingClassMapper.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | public interface ConfigMappingClassMapper { 4 | default Object map() { 5 | throw new UnsupportedOperationException(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config-sources/json.md: -------------------------------------------------------------------------------- 1 | # JSON Config Source 2 | 3 | The [YAML Config Source](yaml.md) also accepts the JSON format as its contents. The configuration file 4 | `META-INF/microprofile-config.yaml`, still requires to use the `yaml` extension. 5 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigMappingMetadata.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | public interface ConfigMappingMetadata { 4 | Class getInterfaceType(); 5 | 6 | String getClassName(); 7 | 8 | byte[] getClassBytes(); 9 | } 10 | -------------------------------------------------------------------------------- /sources/zookeeper/src/test/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | #Properties that are used to bootstrap the configuration of the ZKMicroProfileConifgSource 2 | io.smallrye.configsource.zookeeper.url=localhost:2181 3 | io.smallrye.configsource.zookeeper.applicationId=/test1 -------------------------------------------------------------------------------- /documentation/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | mkdocs = "*" 8 | mkdocs-material = "*" 9 | mkdocs-macros-plugin = "*" 10 | mike = "*" 11 | 12 | [dev-packages] 13 | 14 | [requires] 15 | python_version = "3" 16 | -------------------------------------------------------------------------------- /implementation/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.execution.parallel.enabled = true 2 | junit.jupiter.execution.parallel.config.fixed.parallelism = 8 3 | junit.jupiter.execution.parallel.mode.classes.default = same_thread 4 | junit.jupiter.execution.parallel.mode.default = same_thread -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | open-pull-requests-limit: 10 13 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/resources/beans.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /utils/events/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /utils/cdi-provider/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/mapping/KotlinDefaultFunction.kt: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.mapping 2 | 3 | import io.smallrye.config.ConfigMapping 4 | 5 | @ConfigMapping(prefix = "server") 6 | interface KotlinDefaultFunction { 7 | fun host(): String 8 | 9 | fun serverUrl(): String = "https://${host()}" 10 | } 11 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/regex/Field.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events.regex; 2 | 3 | /** 4 | * a field to apply a regex on 5 | * 6 | * @author Phillip Kruger 7 | */ 8 | public enum Field { 9 | key, 10 | oldValue, 11 | newValue, 12 | fromSource 13 | } 14 | -------------------------------------------------------------------------------- /examples/profiles/src/main/java/io/smallrye/config/examples/profiles/ExampleProfiles.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.profiles; 2 | 3 | import org.eclipse.microprofile.config.ConfigProvider; 4 | 5 | public class ExampleProfiles { 6 | public static String getMyProp() { 7 | return ConfigProvider.getConfig().getValue("my.prop", String.class); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /implementation/src/test/resources/random.yml: -------------------------------------------------------------------------------- 1 | admin: 2 | users: 3 | - 4 | email: "joe@gmail.com" 5 | username: "joe" 6 | password: "123456" 7 | roles: 8 | - "Moderator" 9 | - "Admin" 10 | - 11 | email: "jack@gmail.com" 12 | username: "jack" 13 | password: "654321" 14 | roles: 15 | - "Moderator" 16 | -------------------------------------------------------------------------------- /examples/expansion/src/main/java/io/smallrye/config/examples/expansion/ExampleExpansion.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.expansion; 2 | 3 | import org.eclipse.microprofile.config.ConfigProvider; 4 | 5 | public class ExampleExpansion { 6 | public static String getMyProp() { 7 | return ConfigProvider.getConfig().getValue("my.prop", String.class); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /sources/zookeeper/src/main/java/io/smallrye/config/source/zookeeper/ZooKeeperConfigException.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.zookeeper; 2 | 3 | public class ZooKeeperConfigException extends RuntimeException { 4 | 5 | public ZooKeeperConfigException() { 6 | super(); 7 | } 8 | 9 | public ZooKeeperConfigException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/mapping/src/main/java/io/smallrye/config/examples/mapping/ServerMappingBean.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import jakarta.enterprise.context.ApplicationScoped; 4 | import jakarta.inject.Inject; 5 | 6 | @ApplicationScoped 7 | public class ServerMappingBean { 8 | @Inject 9 | Server server; 10 | 11 | public Server getServer() { 12 | return server; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/update-milestone.yml: -------------------------------------------------------------------------------- 1 | name: Update Milestone 2 | 3 | on: 4 | pull_request_target: 5 | types: [closed] 6 | 7 | jobs: 8 | update: 9 | runs-on: ubuntu-latest 10 | name: update-milestone 11 | if: ${{github.event.pull_request.merged == true}} 12 | 13 | steps: 14 | - uses: radcortez/milestone-set-action@main 15 | name: milestone set 16 | with: 17 | github-token: ${{secrets.GITHUB_TOKEN}} 18 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/config-value.md: -------------------------------------------------------------------------------- 1 | # Config Value 2 | 3 | The `io.smallrye.config.ConfigValue` is a metadata object that holds additional information after the lookup of a 4 | configuration property. It is able to hold information of configuration property name, value, profile, the 5 | `ConfigSource` from where the configuration was loaded, the ordinal of the `ConfigSource` and a line number from where 6 | the configuration was loaded if exists. 7 | 8 | -------------------------------------------------------------------------------- /examples/expansion/src/test/java/io/smallrye/config/examples/expansion/ExampleExpansionTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.expansion; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class ExampleExpansionTest { 8 | @Test 9 | void expand() { 10 | final String myProp = ExampleExpansion.getMyProp(); 11 | assertEquals("expanded", myProp); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/profiles/src/test/java/io/smallrye/config/examples/profiles/ExampleProfilesTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.profiles; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class ExampleProfilesTest { 8 | @Test 9 | void profiles() { 10 | final String myProp = ExampleProfiles.getMyProp(); 11 | assertEquals("production", myProp); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/io/smallrye/config/common/AbstractConverter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.common; 2 | 3 | import java.io.Serial; 4 | import java.io.Serializable; 5 | 6 | import org.eclipse.microprofile.config.spi.Converter; 7 | 8 | /** 9 | * A basic converter. 10 | */ 11 | public abstract class AbstractConverter implements Converter, Serializable { 12 | @Serial 13 | private static final long serialVersionUID = 6881031847338407885L; 14 | } 15 | -------------------------------------------------------------------------------- /examples/mapping/src/main/java/io/smallrye/config/examples/mapping/ServerMapping.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import org.eclipse.microprofile.config.ConfigProvider; 4 | 5 | import io.smallrye.config.SmallRyeConfig; 6 | 7 | public class ServerMapping { 8 | public static Server getServer() { 9 | SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); 10 | return config.getConfigMapping(Server.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/builder/CustomConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.builder; 2 | 3 | import io.smallrye.config.SmallRyeConfigBuilder; 4 | import io.smallrye.config.SmallRyeConfigBuilderCustomizer; 5 | 6 | public class CustomConfigBuilder implements SmallRyeConfigBuilderCustomizer { 7 | @Override 8 | public void configBuilder(final SmallRyeConfigBuilder builder) { 9 | builder.withDefaultValue("from.custom.builder", "1234"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/prepare-release.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Prepare Release 2 | 3 | on: 4 | pull_request: 5 | types: [ closed ] 6 | paths: 7 | - '.github/project.yml' 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | prepare-release: 15 | name: Prepare Release 16 | if: ${{ github.event.pull_request.merged == true}} 17 | uses: smallrye/.github/.github/workflows/prepare-release.yml@main 18 | secrets: inherit 19 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithParentName.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Use the parent's configuration name. 11 | */ 12 | @Documented 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface WithParentName { 16 | } 17 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigValidator.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | public interface ConfigValidator { 4 | void validateMapping(Class mappingClass, String prefix, Object mappingObject) throws ConfigValidationException; 5 | 6 | ConfigValidator EMPTY = new ConfigValidator() { 7 | @Override 8 | public void validateMapping(Class mappingClass, String prefix, Object mappingObject) 9 | throws ConfigValidationException { 10 | 11 | } 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/ServiceLoaderConfigSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | public class ServiceLoaderConfigSourceInterceptor implements ConfigSourceInterceptor { 4 | @Override 5 | public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { 6 | if ("my.prop.loader".equals(name)) { 7 | return ConfigValue.builder().withName(name).withValue("loader").build(); 8 | } 9 | return context.proceed(name); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/ServiceLoaderConfigSourceInterceptorFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | public class ServiceLoaderConfigSourceInterceptorFactory implements ConfigSourceInterceptorFactory { 4 | @Override 5 | public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { 6 | final ConfigValue profile = context.proceed("config.profile"); 7 | return new ProfileConfigSourceInterceptor(profile != null ? profile.getValue() : null); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/profiles/src/main/java/io/smallrye/config/examples/profiles/ExampleProfilesBean.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.profiles; 2 | 3 | import jakarta.enterprise.context.ApplicationScoped; 4 | import jakarta.inject.Inject; 5 | 6 | import org.eclipse.microprofile.config.inject.ConfigProperty; 7 | 8 | @ApplicationScoped 9 | public class ExampleProfilesBean { 10 | @Inject 11 | @ConfigProperty(name = "my.prop") 12 | private String myProperty; 13 | 14 | public String getMyProperty() { 15 | return myProperty; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/expansion/src/main/java/io/smallrye/config/examples/expansion/ExampleExpansionBean.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.expansion; 2 | 3 | import jakarta.enterprise.context.ApplicationScoped; 4 | import jakarta.inject.Inject; 5 | 6 | import org.eclipse.microprofile.config.inject.ConfigProperty; 7 | 8 | @ApplicationScoped 9 | public class ExampleExpansionBean { 10 | @Inject 11 | @ConfigProperty(name = "my.prop") 12 | private String myProperty; 13 | 14 | public String getMyProperty() { 15 | return myProperty; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/interceptors/src/test/java/io/smallrye/config/examples/interceptors/ExampleInterceptorTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.interceptors; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.eclipse.microprofile.config.ConfigProvider; 6 | import org.junit.jupiter.api.Test; 7 | 8 | class ExampleInterceptorTest { 9 | @Test 10 | void getValue() { 11 | final String myProp = ConfigProvider.getConfig().getValue("my.prop", String.class); 12 | assertEquals("intercepted 1", myProp); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/mapping/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | server.host=localhost 2 | server.port=8080 3 | server.timeout=60s 4 | server.io-threads=200 5 | 6 | server.form.login-page=login.html 7 | server.form.error-page=error.html 8 | server.form.landing-page=index.html 9 | 10 | server.ssl.port=8443 11 | server.ssl.certificate=certificate 12 | 13 | server.cors.origins[0].host=some-server 14 | server.cors.origins[0].port=9000 15 | server.cors.origins[1].host=another-server 16 | server.cors.origins[1].port=8000 17 | server.cors.methods[0]=GET 18 | server.cors.methods[1]=POST 19 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/builder/CustomOneConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.builder; 2 | 3 | import io.smallrye.config.SmallRyeConfigBuilder; 4 | import io.smallrye.config.SmallRyeConfigBuilderCustomizer; 5 | 6 | public class CustomOneConfigBuilder implements SmallRyeConfigBuilderCustomizer { 7 | @Override 8 | public void configBuilder(final SmallRyeConfigBuilder builder) { 9 | builder.withDefaultValue("one", "one").addDefaultSources(); 10 | } 11 | 12 | @Override 13 | public int priority() { 14 | return 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/provider/ProviderBeanWithList.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.provider; 2 | 3 | import java.util.List; 4 | 5 | import jakarta.inject.Inject; 6 | import jakarta.inject.Provider; 7 | 8 | import org.eclipse.microprofile.config.inject.ConfigProperty; 9 | 10 | public class ProviderBeanWithList { 11 | 12 | @Inject 13 | @ConfigProperty(name = "objectIds", defaultValue = "") 14 | Provider> objectdIds; 15 | 16 | @Inject 17 | @ConfigProperty(name = "numbers", defaultValue = "") 18 | Provider> numbers; 19 | } 20 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/collections/KotlinCollectionsBean.kt: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.collections 2 | 3 | import org.eclipse.microprofile.config.inject.ConfigProperty 4 | import jakarta.enterprise.context.Dependent 5 | import jakarta.inject.Inject 6 | 7 | @Dependent 8 | class KotlinCollectionsBean { 9 | @Inject 10 | @ConfigProperty(name = "property.list") 11 | lateinit var typeList: List 12 | 13 | @Inject 14 | @ConfigProperty(name = "property.single") 15 | lateinit var singleType: MyType 16 | } 17 | 18 | class MyType(val value: String) { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /validator/src/main/java/io/smallrye/config/validator/BeanValidationConfigValidatorImpl.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.validator; 2 | 3 | import jakarta.validation.Validation; 4 | import jakarta.validation.Validator; 5 | 6 | public class BeanValidationConfigValidatorImpl implements BeanValidationConfigValidator { 7 | private Validator validator; 8 | 9 | public BeanValidationConfigValidatorImpl() { 10 | this.validator = Validation.buildDefaultValidatorFactory().getValidator(); 11 | } 12 | 13 | @Override 14 | public Validator getValidator() { 15 | return validator; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/io/smallrye/config/common/AbstractSimpleDelegatingConverter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.common; 2 | 3 | import java.io.Serial; 4 | 5 | import org.eclipse.microprofile.config.spi.Converter; 6 | 7 | /** 8 | * A converter which wraps another converter of the same type. 9 | */ 10 | public abstract class AbstractSimpleDelegatingConverter extends AbstractDelegatingConverter { 11 | @Serial 12 | private static final long serialVersionUID = 8320492892722511026L; 13 | 14 | protected AbstractSimpleDelegatingConverter(final Converter delegate) { 15 | super(delegate); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithDefaults.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Marker annotation to be used only in a Map mapping to allow the Map to return the default 11 | * value for the value element on any key lookup. 12 | */ 13 | @Documented 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target({ ElementType.METHOD }) 16 | public @interface WithDefaults { 17 | } 18 | -------------------------------------------------------------------------------- /utils/cdi-provider/src/main/java/io/smallrye/config/util/injection/ConfigSourceMap.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.util.injection; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import jakarta.inject.Qualifier; 9 | 10 | /** 11 | * Mark a map that contains the config sources 12 | * 13 | * @author Phillip Kruger 14 | */ 15 | @Qualifier 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target({ ElementType.METHOD, ElementType.FIELD }) 18 | public @interface ConfigSourceMap { 19 | } 20 | -------------------------------------------------------------------------------- /documentation/src/main/docs/extensions/logging.md: -------------------------------------------------------------------------------- 1 | ## LoggingConfigSourceInterceptor 2 | 3 | The `io.smallrye.config.LoggingConfigSourceInterceptor` logs lookups of configuration names in the provided logging 4 | platform. The log information includes config name and value, the config source origin and location if it exists. 5 | 6 | The log is done as `debug`, so the debug threshold must be set to `debug` for the `io.smallrye.config` appender to 7 | display the logs. 8 | 9 | This requires registration via the `ServiceLoader` mechanism in the 10 | `META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory` file of the 11 | `io.smallrye.config.LoggingConfigSourceInterceptor` interceptor. 12 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithDefault.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Specify the default value of a property. 11 | */ 12 | @Documented 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target({ ElementType.METHOD, ElementType.FIELD }) 15 | public @interface WithDefault { 16 | /** 17 | * The default value of the property. 18 | * 19 | * @return the default value as a string 20 | */ 21 | String value(); 22 | } 23 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithName.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * The name of the configuration property or group. 11 | */ 12 | @Documented 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target({ ElementType.METHOD, ElementType.FIELD }) 15 | public @interface WithName { 16 | /** 17 | * The name of the property or group. Must not be empty. 18 | * 19 | * @return the name 20 | */ 21 | String value(); 22 | } 23 | -------------------------------------------------------------------------------- /sources/hocon/src/test/resources/list.conf: -------------------------------------------------------------------------------- 1 | { 2 | "countries": [ 3 | { 4 | "name": "Fiji", 5 | "code": "FJ" 6 | }, 7 | { 8 | "name": "Finland", 9 | "code": "FI" 10 | }, 11 | { 12 | "name": "France", 13 | "code": "FR" 14 | }, 15 | { 16 | "name": "French Guiana", 17 | "code": "GF" 18 | }, 19 | { 20 | "name": "French Polynesia", 21 | "code": "PF" 22 | }, 23 | { 24 | "name": "French Southern Territories", 25 | "code": "TF" 26 | }, 27 | { 28 | "name": "Gabon", 29 | "code": "GA" 30 | }, 31 | { 32 | "name": "Gambia", 33 | "code": "GM" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/builder/CustomTwoConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.builder; 2 | 3 | import io.smallrye.config.SmallRyeConfigBuilder; 4 | import io.smallrye.config.SmallRyeConfigBuilderCustomizer; 5 | 6 | public class CustomTwoConfigBuilder implements SmallRyeConfigBuilderCustomizer { 7 | @Override 8 | public void configBuilder(final SmallRyeConfigBuilder builder) { 9 | builder.withDefaultValue("one", "two"); 10 | if (builder.isAddDefaultSources()) { 11 | builder.withDefaultValue("addDefaultSources", "true"); 12 | } 13 | } 14 | 15 | @Override 16 | public int priority() { 17 | return 2; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /utils/cdi-provider/src/main/java/io/smallrye/config/util/injection/Name.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.util.injection; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import jakarta.enterprise.util.Nonbinding; 9 | import jakarta.inject.Qualifier; 10 | 11 | /** 12 | * The define the name of a config source 13 | * 14 | * @author Phillip Kruger 15 | */ 16 | @Qualifier 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Target({ ElementType.METHOD, ElementType.FIELD }) 19 | public @interface Name { 20 | @Nonbinding 21 | String value(); 22 | } 23 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ProfileConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.eclipse.microprofile.config.spi.ConfigSource; 7 | 8 | interface ProfileConfigSourceFactory extends ConfigSourceFactory { 9 | @Override 10 | default Iterable getConfigSources(final ConfigSourceContext context) { 11 | final List profiles = context.getProfiles(); 12 | if (profiles.isEmpty()) { 13 | return Collections.emptyList(); 14 | } 15 | 16 | return getProfileConfigSources(profiles); 17 | } 18 | 19 | Iterable getProfileConfigSources(final List profiles); 20 | } 21 | -------------------------------------------------------------------------------- /examples/interceptors/src/main/java/io/smallrye/config/examples/interceptors/ExampleInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.interceptors; 2 | 3 | import io.smallrye.config.ConfigSourceInterceptor; 4 | import io.smallrye.config.ConfigSourceInterceptorContext; 5 | import io.smallrye.config.ConfigValue; 6 | 7 | public class ExampleInterceptor implements ConfigSourceInterceptor { 8 | @Override 9 | public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { 10 | final ConfigValue configValue = context.proceed(name); 11 | if (configValue != null) { 12 | return configValue.withValue("intercepted " + configValue.getValue()); 13 | } 14 | 15 | return configValue; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sources/hocon/src/main/java/io/smallrye/config/source/hocon/HoconConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.hocon; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import org.eclipse.microprofile.config.spi.ConfigSource; 7 | 8 | import io.smallrye.config.AbstractLocationConfigSourceFactory; 9 | 10 | public class HoconConfigSourceFactory extends AbstractLocationConfigSourceFactory { 11 | @Override 12 | protected String[] getFileExtensions() { 13 | return new String[] { 14 | "conf" 15 | }; 16 | } 17 | 18 | @Override 19 | protected ConfigSource loadConfigSource(final URL url, final int ordinal) throws IOException { 20 | return new HoconConfigSource(url, ordinal); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithConverter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.eclipse.microprofile.config.spi.Converter; 10 | 11 | /** 12 | * Specify the converter to use to convert the annotated type. 13 | */ 14 | @Documented 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target({ ElementType.METHOD, ElementType.TYPE_USE }) 17 | public @interface WithConverter { 18 | /** 19 | * The converter class to use. 20 | * 21 | * @return the converter class 22 | */ 23 | Class> value(); 24 | } 25 | -------------------------------------------------------------------------------- /sources/zookeeper/src/main/java/io/smallrye/config/source/zookeeper/ZooKeeperMessages.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.zookeeper; 2 | 3 | import java.lang.invoke.MethodHandles; 4 | 5 | import org.jboss.logging.Messages; 6 | import org.jboss.logging.annotations.Message; 7 | import org.jboss.logging.annotations.MessageBundle; 8 | 9 | @MessageBundle(projectCode = "SRCFG", length = 5) 10 | interface ZooKeeperMessages { 11 | ZooKeeperMessages msg = Messages.getBundle(MethodHandles.lookup(), ZooKeeperMessages.class); 12 | 13 | @Message(id = 4000, value = "Please set properties for \"" + 14 | ZooKeeperConfigSource.ZOOKEEPER_URL_KEY + "\" and \"" + 15 | ZooKeeperConfigSource.APPLICATION_ID_KEY + "\"") 16 | ZooKeeperConfigException propertiesNotSet(); 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/io/smallrye/config/common/AbstractDelegatingConverter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.common; 2 | 3 | import java.io.Serial; 4 | 5 | import org.eclipse.microprofile.config.spi.Converter; 6 | 7 | /** 8 | * A converter which wraps another converter (possibly of a different type). 9 | */ 10 | public abstract class AbstractDelegatingConverter extends AbstractConverter { 11 | @Serial 12 | private static final long serialVersionUID = 7514544475086344689L; 13 | 14 | private final Converter delegate; 15 | 16 | protected AbstractDelegatingConverter(final Converter delegate) { 17 | this.delegate = delegate; 18 | } 19 | 20 | public Converter getDelegate() { 21 | return delegate; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config-sources/yaml.md: -------------------------------------------------------------------------------- 1 | # YAML Config Source 2 | 3 | This Config Source allows to use a `yaml` file to load configuration values. The YAML Config Source loads the configuration from the following files: 4 | 5 | 1. (`265`) `application.yaml|yml` in `config` folder, located in the current working directory 6 | 2. (`255`) `application.yaml|yml` in the classpath 7 | 3. (`110`) MicroProfile Config configuration file `META-INF/microprofile-config.yaml|yml` in the classpath 8 | 9 | The following dependency is required in the classpath to use the YAML Config Source: 10 | 11 | ```xml 12 | 13 | io.smallrye.config 14 | smallrye-config-source-yaml 15 | {{attributes['version']}} 16 | 17 | ``` 18 | -------------------------------------------------------------------------------- /sources/yaml/src/main/java/io/smallrye/config/source/yaml/YamlLocationConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.yaml; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import org.eclipse.microprofile.config.spi.ConfigSource; 7 | 8 | import io.smallrye.config.AbstractLocationConfigSourceFactory; 9 | 10 | public class YamlLocationConfigSourceFactory extends AbstractLocationConfigSourceFactory { 11 | @Override 12 | public String[] getFileExtensions() { 13 | return new String[] { 14 | "yaml", 15 | "yml" 16 | }; 17 | } 18 | 19 | @Override 20 | protected ConfigSource loadConfigSource(final URL url, final int ordinal) throws IOException { 21 | return new YamlConfigSource(url, ordinal); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/mapping/KotlinDefaulltFunctionTest.kt: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.mapping 2 | 3 | import io.smallrye.config.SmallRyeConfigBuilder 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Test 6 | 7 | class KotlinDefaulltFunctionTest { 8 | @Test 9 | fun kotlinDefaultMethod() { 10 | val config = SmallRyeConfigBuilder() 11 | .withMapping(KotlinDefaultFunction::class.java) 12 | .withDefaultValue("server.host", "localhost") 13 | .build() 14 | 15 | val mapping = config.getConfigMapping(KotlinDefaultFunction::class.java) 16 | assertEquals("localhost", mapping.host()) 17 | assertEquals("https://localhost", mapping.serverUrl()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/PropertiesLocationConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import org.eclipse.microprofile.config.spi.ConfigSource; 7 | 8 | public class PropertiesLocationConfigSourceFactory extends AbstractLocationConfigSourceFactory { 9 | @Override 10 | public String[] getFileExtensions() { 11 | return new String[] { "properties" }; 12 | } 13 | 14 | @Override 15 | public Iterable getConfigSources(final ConfigSourceContext context) { 16 | return super.getConfigSources(context); 17 | } 18 | 19 | @Override 20 | protected ConfigSource loadConfigSource(final URL url, final int ordinal) throws IOException { 21 | return new PropertiesConfigSource(url, ordinal); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /message-ranges.txt: -------------------------------------------------------------------------------- 1 | # This document is intended to establish the ranges for message IDs in the various sub-projects. 2 | 3 | # Range = owner 4 | 5 | 00000-00999 = smallrye-config [io.smallrye.config] (messages) 6 | 7 | 01000-01999 = smallrye-config [io.smallrye.config] (logging) 8 | 9 | 02000-02999 = smallrye-config [io.smallrye.config.inject] (messages) 10 | 11 | 03000-03999 = smallrye-config-source-file-system (logging) 12 | 13 | 04000-04999 = smallrye-config-source-zookeeper 14 | 15 | 05000-05999 = smallrye-config-events 16 | 17 | 06000-06999 = 18 | 19 | 07000-07999 = 20 | 21 | 08000-08999 = 22 | 23 | 09000-09999 = 24 | 25 | 10000-10999 = 26 | 27 | 11000-11999 = 28 | 29 | 12000-12999 = 30 | 31 | 13000-13999 = 32 | 33 | 14000-14999 = 34 | 35 | 15000-15999 = 36 | 37 | 16000-16999 = 38 | 39 | 17000-17999 = 40 | 41 | 18000-18999 = 42 | 43 | 19000-19999 = -------------------------------------------------------------------------------- /sources/keystore/src/main/java/io/smallrye/config/source/keystore/KeyStoreConfig.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.keystore; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | import io.smallrye.config.ConfigMapping; 7 | import io.smallrye.config.WithDefault; 8 | import io.smallrye.config.WithParentName; 9 | 10 | @ConfigMapping(prefix = "smallrye.config.source.keystore") 11 | public interface KeyStoreConfig { 12 | @WithParentName 13 | Map keystores(); 14 | 15 | interface KeyStore { 16 | String path(); 17 | 18 | @WithDefault("PKCS12") 19 | String type(); 20 | 21 | Optional handler(); 22 | 23 | Map aliases(); 24 | 25 | interface Alias { 26 | Optional name(); 27 | 28 | Optional handler(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/regex/RegexLogging.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events.regex; 2 | 3 | import java.lang.invoke.MethodHandles; 4 | 5 | import org.jboss.logging.BasicLogger; 6 | import org.jboss.logging.Logger; 7 | import org.jboss.logging.annotations.LogMessage; 8 | import org.jboss.logging.annotations.Message; 9 | import org.jboss.logging.annotations.MessageLogger; 10 | 11 | @MessageLogger(projectCode = "SRCFG", length = 5) 12 | interface RegexLogging extends BasicLogger { 13 | RegexLogging log = Logger.getMessageLogger(MethodHandles.lookup(), RegexLogging.class, 14 | RegexLogging.class.getPackage().getName()); 15 | 16 | @LogMessage(level = Logger.Level.WARN) 17 | @Message(id = 5000, value = "Can not find ChangeEvent parameter for method %s. @RegexFilter is being ignored") 18 | void changeEventParameterMissing(String methodName); 19 | } 20 | -------------------------------------------------------------------------------- /sources/file-system/src/main/java/io/smallrye/config/source/file/FileSystemLogging.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.file; 2 | 3 | import java.lang.invoke.MethodHandles; 4 | 5 | import org.jboss.logging.BasicLogger; 6 | import org.jboss.logging.Logger; 7 | import org.jboss.logging.annotations.LogMessage; 8 | import org.jboss.logging.annotations.Message; 9 | import org.jboss.logging.annotations.MessageLogger; 10 | 11 | @MessageLogger(projectCode = "SRCFG", length = 5) 12 | interface FileSystemLogging extends BasicLogger { 13 | FileSystemLogging log = Logger.getMessageLogger(MethodHandles.lookup(), FileSystemLogging.class, 14 | FileSystemLogging.class.getPackage().getName()); 15 | 16 | @LogMessage(level = Logger.Level.WARN) 17 | @Message(id = 3000, value = "Unable to read content from file %s. Exception: %s") 18 | void failedToReadFileContent(String file, String cause); 19 | } 20 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/regex/RegexFilter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events.regex; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import jakarta.enterprise.util.Nonbinding; 10 | import jakarta.interceptor.InterceptorBinding; 11 | 12 | /** 13 | * an interceptor that match the value to a regular expression 14 | * 15 | * @author Phillip Kruger 16 | */ 17 | @Inherited 18 | @InterceptorBinding 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Target({ ElementType.METHOD, ElementType.TYPE }) 21 | public @interface RegexFilter { 22 | @Nonbinding 23 | String value(); 24 | 25 | @Nonbinding 26 | Field onField() default Field.key; 27 | } 28 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/Priorities.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | /** 4 | * A collection of built-in priority constants for {@link ConfigSourceInterceptor} that are supposed to be 5 | * ordered based on their {@code jakarta.annotation.Priority} class-level annotation. 6 | */ 7 | public final class Priorities { 8 | /** 9 | * Range for early interceptors defined by Platform specifications. 10 | */ 11 | public static final int PLATFORM = 1000; 12 | 13 | /** 14 | * Range for interceptors defined by SmallRye Config or Extension Libraries. 15 | */ 16 | public static final int LIBRARY = 3000; 17 | 18 | /** 19 | * Range for interceptors defined by User Applications. 20 | */ 21 | public static final int APPLICATION = 5000; 22 | 23 | private Priorities() { 24 | throw new UnsupportedOperationException(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithUnnamedKey.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Omits a single map key from the configuration name when populating {@link java.util.Map} types. Configuration values 11 | * for the {@link java.util.Map} may be retrieved by the key defined in {@link WithUnnamedKey#value()}. 12 | */ 13 | @Documented 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target({ ElementType.METHOD, ElementType.TYPE_USE }) 16 | public @interface WithUnnamedKey { 17 | /** 18 | * The key name to use to populate configuration values from a configuration path without a key. 19 | * 20 | * @return the Map key 21 | */ 22 | String value() default ""; 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/io/smallrye/config/common/AbstractConfigSource.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.common; 2 | 3 | import java.io.Serial; 4 | import java.io.Serializable; 5 | 6 | import org.eclipse.microprofile.config.spi.ConfigSource; 7 | 8 | public abstract class AbstractConfigSource implements ConfigSource, Serializable { 9 | @Serial 10 | private static final long serialVersionUID = 9018847720072978115L; 11 | 12 | private final int ordinal; 13 | private final String name; 14 | 15 | public AbstractConfigSource(String name, int ordinal) { 16 | this.name = name; 17 | this.ordinal = ordinal; 18 | } 19 | 20 | @Override 21 | public int getOrdinal() { 22 | return ordinal; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return getName(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/review-release.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Review Release 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '.github/project.yml' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | name: pre release 12 | 13 | steps: 14 | - uses: radcortez/project-metadata-action@main 15 | name: retrieve project metadata 16 | id: metadata 17 | with: 18 | github-token: ${{secrets.GITHUB_TOKEN}} 19 | metadata-file-path: '.github/project.yml' 20 | 21 | - name: Validate version 22 | if: contains(steps.metadata.outputs.current-version, 'SNAPSHOT') 23 | run: | 24 | echo '::error::Cannot release a SNAPSHOT version.' 25 | exit 1 26 | 27 | - uses: radcortez/milestone-review-action@main 28 | name: milestone review 29 | with: 30 | github-token: ${{secrets.GITHUB_TOKEN}} 31 | milestone-title: ${{steps.metadata.outputs.current-version}} 32 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/SysPropConfigSourceTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.eclipse.microprofile.config.spi.ConfigSource; 6 | import org.junit.jupiter.api.AfterEach; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class SysPropConfigSourceTest { 11 | @BeforeEach 12 | void setUp() { 13 | System.setProperty("config_ordinal", "1000"); 14 | } 15 | 16 | @AfterEach 17 | void tearDown() { 18 | System.clearProperty("config_ordinal"); 19 | } 20 | 21 | @Test 22 | void ordinal() { 23 | SmallRyeConfig config = new SmallRyeConfigBuilder().withSources(new SysPropConfigSource()).build(); 24 | ConfigSource configSource = config.getConfigSources().iterator().next(); 25 | 26 | assertTrue(configSource instanceof SysPropConfigSource); 27 | assertEquals(configSource.getOrdinal(), 1000); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/mapping/src/main/java/io/smallrye/config/examples/mapping/MappingSmallRyeConfigFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import io.smallrye.config.SmallRyeConfig; 4 | import io.smallrye.config.SmallRyeConfigFactory; 5 | import io.smallrye.config.SmallRyeConfigProviderResolver; 6 | 7 | public class MappingSmallRyeConfigFactory extends SmallRyeConfigFactory { 8 | @Override 9 | public SmallRyeConfig getConfigFor( 10 | final SmallRyeConfigProviderResolver configProviderResolver, final ClassLoader classLoader) { 11 | 12 | return configProviderResolver.getBuilder() 13 | .forClassLoader(classLoader) 14 | .addDiscoveredCustomizers() 15 | .addDefaultSources() 16 | .addDefaultInterceptors() 17 | .addDiscoveredSources() 18 | .addDiscoveredConverters() 19 | .addDiscoveredInterceptors() 20 | .withMapping(Server.class) 21 | .build(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config-sources/zookeeper.md: -------------------------------------------------------------------------------- 1 | # ZooKeeper Config Source 2 | 3 | This Config Source allows using [Apache ZooKeeper](https://zookeeper.apache.org/index.html) to load configuration 4 | values. 5 | 6 | The following dependency is required in the classpath to use the ZooKeeper Config Source: 7 | 8 | ```xml 9 | 10 | io.smallrye.config 11 | smallrye-config-source-zookeeper 12 | {{attributes['version']}} 13 | 14 | ``` 15 | 16 | It also requires to set up additional configuration properties to identify the ZooKeeper instance: 17 | 18 | ```properties 19 | io.smallrye.configsource.zookeeper.url=localhost:2181 20 | io.smallrye.configsource.zookeeper.applicationId=applicationId 21 | ``` 22 | 23 | The ZooKeeper Config Source will look for configuration values in a ZooKeeper instance running in the url set in 24 | `io.smallrye.configsource.zookeeper.url` and in the znodes available in `/applicationId/`. 25 | 26 | This Config Source has an ordinal of `150`. 27 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/converter/IntConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.smallrye.config.test.converter; 17 | 18 | import jakarta.annotation.Priority; 19 | 20 | import org.eclipse.microprofile.config.spi.Converter; 21 | 22 | @Priority(102) 23 | public class IntConverter implements Converter { 24 | 25 | @Override 26 | public Integer convert(String s) { 27 | return 102; 28 | } 29 | } -------------------------------------------------------------------------------- /utils/cdi-provider/src/test/java/io/smallrye/config/util/injection/InjectionTestConfigFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.util.injection; 2 | 3 | import java.util.HashMap; 4 | 5 | import io.smallrye.config.PropertiesConfigSource; 6 | import io.smallrye.config.SmallRyeConfig; 7 | import io.smallrye.config.SmallRyeConfigFactory; 8 | import io.smallrye.config.SmallRyeConfigProviderResolver; 9 | 10 | public class InjectionTestConfigFactory extends SmallRyeConfigFactory { 11 | @Override 12 | public SmallRyeConfig getConfigFor( 13 | final SmallRyeConfigProviderResolver configProviderResolver, final ClassLoader classLoader) { 14 | return configProviderResolver.getBuilder().forClassLoader(classLoader) 15 | .addDefaultSources() 16 | .withSources(new PropertiesConfigSource(new HashMap() { 17 | { 18 | put("testkey", "testvalue"); 19 | } 20 | }, "memory", 0)) 21 | .addDefaultInterceptors() 22 | .build(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /utils/jasypt/src/main/java/io/smallrye/config/jasypt/JasyptSecretKeysHandler.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.jasypt; 2 | 3 | import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; 4 | import org.jasypt.iv.RandomIvGenerator; 5 | import org.jasypt.properties.PropertyValueEncryptionUtils; 6 | 7 | import io.smallrye.config.SecretKeysHandler; 8 | 9 | public class JasyptSecretKeysHandler implements SecretKeysHandler { 10 | private final StandardPBEStringEncryptor encryptor; 11 | 12 | public JasyptSecretKeysHandler(final String password, final String algorithm) { 13 | encryptor = new StandardPBEStringEncryptor(); 14 | encryptor.setPassword(password); 15 | encryptor.setAlgorithm(algorithm); 16 | encryptor.setIvGenerator(new RandomIvGenerator()); 17 | encryptor.initialize(); 18 | } 19 | 20 | @Override 21 | public String decode(final String secret) { 22 | return PropertyValueEncryptionUtils.decrypt(secret, encryptor); 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return "jasypt"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sources/zookeeper/src/main/java/io/smallrye/config/source/zookeeper/ZooKeeperConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.zookeeper; 2 | 3 | import static io.smallrye.config.source.zookeeper.ZooKeeperConfigSource.APPLICATION_ID_KEY; 4 | import static io.smallrye.config.source.zookeeper.ZooKeeperConfigSource.ZOOKEEPER_URL_KEY; 5 | 6 | import java.util.Collections; 7 | import java.util.OptionalInt; 8 | 9 | import org.eclipse.microprofile.config.spi.ConfigSource; 10 | 11 | import io.smallrye.config.ConfigSourceContext; 12 | import io.smallrye.config.ConfigSourceFactory; 13 | 14 | public class ZooKeeperConfigSourceFactory implements ConfigSourceFactory { 15 | @Override 16 | public Iterable getConfigSources(final ConfigSourceContext context) { 17 | return Collections.singletonList(new ZooKeeperConfigSource(context.getValue(ZOOKEEPER_URL_KEY).getValue(), 18 | context.getValue(APPLICATION_ID_KEY).getValue())); 19 | } 20 | 21 | @Override 22 | public OptionalInt getPriority() { 23 | return OptionalInt.of(150); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/expansion/src/test/java/io/smallrye/config/examples/expansion/ExampleExpansionBeanTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.expansion; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.enterprise.context.ApplicationScoped; 6 | import jakarta.inject.Inject; 7 | 8 | import org.jboss.weld.junit5.WeldInitiator; 9 | import org.jboss.weld.junit5.WeldJunit5Extension; 10 | import org.jboss.weld.junit5.WeldSetup; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | 14 | import io.smallrye.config.inject.ConfigExtension; 15 | 16 | @ExtendWith(WeldJunit5Extension.class) 17 | class ExampleExpansionBeanTest { 18 | @WeldSetup 19 | WeldInitiator weld = WeldInitiator.from(ConfigExtension.class, ExampleExpansionBean.class) 20 | .addBeans() 21 | .activate(ApplicationScoped.class) 22 | .inject(this) 23 | .build(); 24 | 25 | @Inject 26 | ExampleExpansionBean bean; 27 | 28 | @Test 29 | void expand() { 30 | assertEquals("expanded", bean.getMyProperty()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/profiles/src/test/java/io/smallrye/config/examples/profiles/ExampleProfilesBeanTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.profiles; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.enterprise.context.ApplicationScoped; 6 | import jakarta.inject.Inject; 7 | 8 | import org.jboss.weld.junit5.WeldInitiator; 9 | import org.jboss.weld.junit5.WeldJunit5Extension; 10 | import org.jboss.weld.junit5.WeldSetup; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | 14 | import io.smallrye.config.inject.ConfigExtension; 15 | 16 | @ExtendWith(WeldJunit5Extension.class) 17 | class ExampleProfilesBeanTest { 18 | @WeldSetup 19 | WeldInitiator weld = WeldInitiator.from(ConfigExtension.class, ExampleProfilesBean.class) 20 | .addBeans() 21 | .activate(ApplicationScoped.class) 22 | .inject(this) 23 | .build(); 24 | 25 | @Inject 26 | ExampleProfilesBean bean; 27 | 28 | @Test 29 | void profiles() { 30 | assertEquals("production", bean.getMyProperty()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/Expressions.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.util.function.Supplier; 4 | 5 | @SuppressWarnings("squid:S5164") 6 | public final class Expressions { 7 | private static final ThreadLocal ENABLE = new ThreadLocal<>(); 8 | 9 | private Expressions() { 10 | throw new UnsupportedOperationException(); 11 | } 12 | 13 | public static boolean isEnabled() { 14 | Boolean result = ENABLE.get(); 15 | return result == null ? true : result; 16 | } 17 | 18 | public static void withoutExpansion(final Runnable action) { 19 | withoutExpansion(() -> { 20 | action.run(); 21 | return null; 22 | }); 23 | } 24 | 25 | public static T withoutExpansion(Supplier supplier) { 26 | if (isEnabled()) { 27 | ENABLE.set(false); 28 | try { 29 | return supplier.get(); 30 | } finally { 31 | ENABLE.remove(); 32 | } 33 | } else { 34 | return supplier.get(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/TypeFilter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import jakarta.enterprise.util.AnnotationLiteral; 10 | import jakarta.inject.Qualifier; 11 | 12 | /** 13 | * filter by change type 14 | * 15 | * @author Phillip Kruger 16 | */ 17 | @Qualifier 18 | @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD }) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Documented 21 | public @interface TypeFilter { 22 | Type value(); 23 | 24 | class TypeFilterLiteral extends AnnotationLiteral implements TypeFilter { 25 | private final Type type; 26 | 27 | TypeFilterLiteral(Type type) { 28 | this.type = type; 29 | } 30 | 31 | @Override 32 | public Type value() { 33 | return this.type; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/KeyFilter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import jakarta.enterprise.util.AnnotationLiteral; 10 | import jakarta.inject.Qualifier; 11 | 12 | /** 13 | * Filter the event on the key 14 | * 15 | * @author Phillip Kruger 16 | */ 17 | @Qualifier 18 | @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD }) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Documented 21 | public @interface KeyFilter { 22 | String value(); 23 | 24 | class KeyFilterLiteral extends AnnotationLiteral implements KeyFilter { 25 | private final String key; 26 | 27 | KeyFilterLiteral(String key) { 28 | this.key = key; 29 | } 30 | 31 | @Override 32 | public String value() { 33 | return this.key; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sources/hocon/src/main/java/io/smallrye/config/source/hocon/HoconConfigSourceProvider.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.hocon; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.ArrayList; 6 | 7 | import org.eclipse.microprofile.config.spi.ConfigSource; 8 | import org.eclipse.microprofile.config.spi.ConfigSourceProvider; 9 | 10 | import io.smallrye.config.AbstractLocationConfigSourceLoader; 11 | 12 | public class HoconConfigSourceProvider extends AbstractLocationConfigSourceLoader implements ConfigSourceProvider { 13 | @Override 14 | protected String[] getFileExtensions() { 15 | return new String[] { 16 | "conf" 17 | }; 18 | } 19 | 20 | @Override 21 | protected ConfigSource loadConfigSource(final URL url, final int ordinal) throws IOException { 22 | return new HoconConfigSource(url, ordinal); 23 | } 24 | 25 | @Override 26 | public Iterable getConfigSources(final ClassLoader classLoader) { 27 | return new ArrayList<>(loadConfigSources("META-INF/microprofile-config.conf", HoconConfigSource.ORDINAL, classLoader)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/SourceFilter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import jakarta.enterprise.util.AnnotationLiteral; 10 | import jakarta.inject.Qualifier; 11 | 12 | /** 13 | * Filter by a config source 14 | * 15 | * @author Phillip Kruger 16 | */ 17 | @Qualifier 18 | @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD }) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Documented 21 | public @interface SourceFilter { 22 | String value(); 23 | 24 | class SourceFilterLiteral extends AnnotationLiteral implements SourceFilter { 25 | private final String name; 26 | 27 | SourceFilterLiteral(String name) { 28 | this.name = name; 29 | } 30 | 31 | @Override 32 | public String value() { 33 | return this.name; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/source/YamlPropertiesTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.source; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.inject.Inject; 6 | 7 | import org.eclipse.microprofile.config.Config; 8 | import org.jboss.arquillian.container.test.api.Deployment; 9 | import org.jboss.arquillian.junit5.ArquillianExtension; 10 | import org.jboss.shrinkwrap.api.ShrinkWrap; 11 | import org.jboss.shrinkwrap.api.asset.StringAsset; 12 | import org.jboss.shrinkwrap.api.spec.WebArchive; 13 | import org.junit.jupiter.api.Test; 14 | import org.junit.jupiter.api.extension.ExtendWith; 15 | 16 | @ExtendWith(ArquillianExtension.class) 17 | class YamlPropertiesTest { 18 | @Deployment 19 | static WebArchive deploy() { 20 | return ShrinkWrap.create(WebArchive.class) 21 | .addAsResource(new StringAsset("my:\n yaml: 1234\n"), "META-INF/microprofile-config.yaml") 22 | .as(WebArchive.class); 23 | } 24 | 25 | @Inject 26 | Config config; 27 | 28 | @Test 29 | void yaml() { 30 | assertEquals("1234", config.getValue("my.yaml", String.class)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /documentation/src/main/docs/extensions/config-source-injection.md: -------------------------------------------------------------------------------- 1 | # Config Source Injection 2 | 3 | The Config Source Injection extension allows you to use CDI injection to inject a ConfigSource by name in your CDI 4 | aware beans, or by looking it up programatically in the CDI `BeanManager`. 5 | 6 | ## Usage 7 | 8 | To use the Config Source Injection, add the following to your Maven `pom.xml`: 9 | 10 | ```xml 11 | 12 | io.smallrye.config 13 | smallrye-config-source-injection 14 | {{attributes['version']}} 15 | 16 | ``` 17 | 18 | ### Injecting Sources 19 | 20 | You can inject a `ConfigSource` by referencing it by name: 21 | 22 | ```java 23 | @Inject 24 | @Name("MemoryConfigSource") 25 | private ConfigSource memoryConfigSource; 26 | 27 | @Inject 28 | @Name("SysPropConfigSource") 29 | private ConfigSource systemPropertiesConfigSource; 30 | ``` 31 | 32 | You can also get a Map of all config sources. The map key holds the `ConfigSource` name and the map value the 33 | `ConfigSource`: 34 | 35 | ```java 36 | @Inject 37 | @ConfigSourceMap 38 | private Map configSourceMap; 39 | ``` 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Release 2 | run-name: Perform ${{github.event.inputs.tag || github.ref_name}} Release 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | workflow_dispatch: 8 | inputs: 9 | tag: 10 | description: 'Tag to release' 11 | required: true 12 | 13 | permissions: 14 | attestations: write 15 | id-token: write 16 | # Needed for the publish-* workflows 17 | contents: write 18 | 19 | concurrency: 20 | group: ${{ github.workflow }}-${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | perform-release: 25 | name: Perform Release 26 | uses: smallrye/.github/.github/workflows/perform-release.yml@main 27 | secrets: inherit 28 | with: 29 | version: ${{github.event.inputs.tag || github.ref_name}} 30 | 31 | publish-docs: 32 | name: Publish Docs 33 | uses: ./.github/workflows/publish-docs.yml 34 | secrets: inherit 35 | with: 36 | version: ${{github.event.inputs.tag || github.ref_name}} 37 | 38 | publish-tck: 39 | name: Publish TCK Report 40 | uses: ./.github/workflows/publish-tck.yml 41 | secrets: inherit 42 | with: 43 | version: ${{github.event.inputs.tag || github.ref_name}} 44 | -------------------------------------------------------------------------------- /validator/src/test/java/io/smallrye/config/validator/external/ValidationVisibilityTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.validator.external; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.hibernate.validator.constraints.Length; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.SmallRyeConfig; 10 | import io.smallrye.config.SmallRyeConfigBuilder; 11 | import io.smallrye.config.validator.BeanValidationConfigValidatorImpl; 12 | 13 | public class ValidationVisibilityTest { 14 | @Test 15 | void visibility() { 16 | SmallRyeConfig config = new SmallRyeConfigBuilder() 17 | .withDefaultValue("default.visibility.value", "12345678") 18 | .withValidator(new BeanValidationConfigValidatorImpl()) 19 | .withMapping(DefaultVisibility.class) 20 | .build(); 21 | 22 | DefaultVisibility mapping = config.getConfigMapping(DefaultVisibility.class); 23 | 24 | assertEquals("12345678", mapping.value()); 25 | } 26 | 27 | @ConfigMapping(prefix = "default.visibility") 28 | interface DefaultVisibility { 29 | @Length(max = 10) 30 | String value(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/expressions.md: -------------------------------------------------------------------------------- 1 | # Property Expressions 2 | 3 | SmallRye Config provides property expressions expansion on configuration values. An expression string is a mix of plain 4 | strings and expression segments, which are wrapped by the sequence ${ ... }. 5 | 6 | For instance, the following configuration properties file: 7 | 8 | ```properties 9 | remote.host=smallrye.io 10 | callable.url=https://${remote.host}/ 11 | ``` 12 | 13 | The resolved value of the `callable.url` property is `https://smallrye.io/`. 14 | 15 | Additionally, the Expression Expansion engine supports the following segments: 16 | 17 | - `${expression:value}` - Provides a default value after the `:` if the expansion doesn’t find a value. 18 | - `${my.prop${compose}}` - Composed expressions. Inner expressions are resolved first. 19 | - `${my.prop}${my.prop}` - Multiple expressions. 20 | 21 | If an expression cannot be expanded and no default is supplied a `NoSuchElementException` is thrown. 22 | 23 | Expression expansion may be selectively disabled with `io.smallrye.config.Expressions`: 24 | 25 | ```java 26 | Config config = ConfigProvider.getConfig(); 27 | 28 | String url = Expressions.withoutExpansion(() -> 29 | config.getValue("callable.url", String.class)); 30 | ``` 31 | -------------------------------------------------------------------------------- /.github/workflows/publish-tck.yml: -------------------------------------------------------------------------------- 1 | name: Publish TCK 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | version: 7 | required: true 8 | description: Tag version to perform release 9 | type: string 10 | 11 | jobs: 12 | publish-tck: 13 | name: Publish TCK 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | java: [ 17, 21 ] 18 | 19 | steps: 20 | - uses: actions/checkout@v6 21 | name: checkout ${{inputs.version}} 22 | with: 23 | ref: ${{inputs.version}} 24 | 25 | - uses: actions/setup-java@v5 26 | name: set up jdk ${{matrix.java}} 27 | with: 28 | distribution: 'temurin' 29 | java-version: ${{matrix.java}} 30 | cache: 'maven' 31 | cache-dependency-path: '**/pom.xml' 32 | 33 | - name: generate tck report for jdk ${{matrix.java}} 34 | env: 35 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 36 | ZIP_NAME: smallrye-config-${{inputs.version}}-tck-results-java-${{matrix.java}}.zip 37 | run: | 38 | mvn -B formatter:validate verify --file pom.xml 39 | cd testsuite/tck/target 40 | zip -r $ZIP_NAME surefire-reports/ 41 | gh release upload ${{inputs.version}} $ZIP_NAME 42 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.config 7 | smallrye-config-parent 8 | 3.15.1-SNAPSHOT 9 | 10 | 11 | smallrye-config-common 12 | 13 | SmallRye Config: Common 14 | 15 | 16 | 17 | org.eclipse.microprofile.config 18 | microprofile-config-api 19 | 20 | 21 | io.smallrye.common 22 | smallrye-common-classloader 23 | 24 | 25 | org.jboss.logging 26 | jboss-logging 27 | 28 | 29 | 30 | 31 | org.junit.jupiter 32 | junit-jupiter 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/SecretKeysHandler.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | /** 4 | * A {@code SecretKeysHandler} provides a way to decode or decrypt a secret configuration value. 5 | *

6 | * A secret configuration value may be expressed as {@code ${handler::value}}, where the {@code handler} is 7 | * the name of the {@code SecretKeysHandler} to use for decode or decryption the {@code value} separated by a 8 | * double colon {@code ::}. 9 | *

10 | * Instances of this interface will be discovered via the {@link java.util.ServiceLoader} mechanism and can be 11 | * registered by providing a {@code META-INF/services/io.smallrye.config.SecretKeysHandler} which contains the fully 12 | * qualified class name of the custom {@code SecretKeysHandler} implementation. 13 | * 14 | * @see io.smallrye.config.SecretKeysHandlerFactory 15 | */ 16 | public interface SecretKeysHandler { 17 | /** 18 | * Decodes the secret configuration value. 19 | * 20 | * @param secret the value to decode. 21 | * @return the secret decoded. 22 | */ 23 | String decode(String secret); 24 | 25 | /** 26 | * The name of {@code SecretKeysHandler}. 27 | * 28 | * @return the name of the {@code SecretKeysHandler}. 29 | */ 30 | String getName(); 31 | } 32 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/converter/ConverterBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.smallrye.config.test.converter; 17 | 18 | import jakarta.inject.Inject; 19 | 20 | import org.eclipse.microprofile.config.inject.ConfigProperty; 21 | 22 | public class ConverterBean { 23 | 24 | @Inject 25 | @ConfigProperty(name = "myInt", defaultValue = "1") 26 | private int myInt; 27 | 28 | @Inject 29 | @ConfigProperty(name = "myInteger", defaultValue = "1") 30 | private Integer myInteger; 31 | 32 | public int getInt() { 33 | return myInt; 34 | } 35 | 36 | public Integer getInteger() { 37 | return myInteger; 38 | } 39 | } -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/SmallRyeConfigBuilderCustomizer.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | /** 4 | * This {@code SmallRyeConfigBuilderCustomizer} allows to customize a {@link SmallRyeConfigBuilder}, used to create 5 | * a {@link SmallRyeConfig} instance. 6 | *

7 | * Instances of this interface will be discovered via the {@link java.util.ServiceLoader} mechanism and can be 8 | * registered by providing a {@code META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer} which 9 | * contains the fully qualified class name of the custom {@link SmallRyeConfigBuilderCustomizer} implementation. 10 | */ 11 | public interface SmallRyeConfigBuilderCustomizer { 12 | /** 13 | * Customize the current {@link SmallRyeConfigBuilder}. 14 | * 15 | * @param builder the current {@link SmallRyeConfigBuilder}. 16 | */ 17 | void configBuilder(SmallRyeConfigBuilder builder); 18 | 19 | /** 20 | * Returns the customizer priority. Customizers are sorted by ascending priority and executed in that order, meaning 21 | * that higher numeric priorities will be executing last, possible overriding values set by previous customizers. 22 | * 23 | * @return the priority value. 24 | */ 25 | default int priority() { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /utils/jasypt/src/main/java/io/smallrye/config/jasypt/JasyptSecretKeysHandlerFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.jasypt; 2 | 3 | import java.util.NoSuchElementException; 4 | 5 | import io.smallrye.config.ConfigSourceContext; 6 | import io.smallrye.config.ConfigValue; 7 | import io.smallrye.config.SecretKeysHandler; 8 | import io.smallrye.config.SecretKeysHandlerFactory; 9 | import io.smallrye.config._private.ConfigMessages; 10 | 11 | public class JasyptSecretKeysHandlerFactory implements SecretKeysHandlerFactory { 12 | @Override 13 | public SecretKeysHandler getSecretKeysHandler(final ConfigSourceContext context) { 14 | String password = requireValue(context, "smallrye.config.secret-handler.jasypt.password"); 15 | String algorithm = requireValue(context, "smallrye.config.secret-handler.jasypt.algorithm"); 16 | return new JasyptSecretKeysHandler(password, algorithm); 17 | } 18 | 19 | @Override 20 | public String getName() { 21 | return "jasypt"; 22 | } 23 | 24 | private static String requireValue(final ConfigSourceContext context, final String name) { 25 | ConfigValue value = context.getValue(name); 26 | if (value != null) { 27 | return value.getValue(); 28 | } 29 | throw new NoSuchElementException(ConfigMessages.msg.propertyNotFound(name)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore .svn metadata files 2 | .svn 3 | # ignore Maven generated target folders 4 | ~ 5 | target 6 | # ignore downloaded maven 7 | /tools/maven 8 | /tools/maven.zip 9 | # ignore eclipse files 10 | .project 11 | .classpath 12 | .settings 13 | .metadata 14 | .checkstyle 15 | # ignore m2e annotation processing files 16 | .factorypath 17 | # ignore IDEA files 18 | *.iml 19 | *.ipr 20 | *.iws 21 | .idea 22 | # ignore NetBeans files 23 | nbactions.xml 24 | nb-configuration.xml 25 | catalog.xml 26 | # 27 | maven-ant-tasks.jar 28 | test-output 29 | transaction.log 30 | # vim files 31 | *.swp 32 | /.gitk-tmp.* 33 | atlassian-ide-plugin.xml 34 | # temp files 35 | *~ 36 | # maven versions plugin 37 | pom.xml.versionsBackup 38 | # hprof dumps 39 | /*.hprof 40 | # ignore 'randomly' strewn around logs 41 | server.log 42 | # ignore java crashes 43 | hs_err_pid*.log 44 | # H2 databases produced by tests 45 | *.h2.db 46 | # JBoss transaction generated files 47 | PutObjectStoreDirHere 48 | # ignore mvn-rpmbuild repo 49 | /.m2 50 | # ignore eap repo 51 | local-repo-eap 52 | 53 | #These keep hanging around 54 | arquillian/*/server.log* 55 | client/shade/dependency-reduced-pom.xml 56 | 57 | #OS X stuff 58 | .DS_Store 59 | 60 | # Zanata files 61 | **/.zanata-cache/ 62 | 63 | # Jenv 64 | .java-version 65 | 66 | # MkDocs 67 | site 68 | 69 | # formatter cache directories 70 | .cache 71 | -------------------------------------------------------------------------------- /examples/mapping/src/main/java/io/smallrye/config/examples/mapping/DurationConverter.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import java.time.Duration; 4 | import java.time.format.DateTimeParseException; 5 | import java.util.regex.Pattern; 6 | 7 | import org.eclipse.microprofile.config.spi.Converter; 8 | 9 | public class DurationConverter implements Converter { 10 | private static final long serialVersionUID = 7499347081928776532L; 11 | private static final String PERIOD_OF_TIME = "PT"; 12 | private static final Pattern DIGITS = Pattern.compile("^[-+]?\\d+$"); 13 | private static final Pattern START_WITH_DIGITS = Pattern.compile("^[-+]?\\d+.*"); 14 | 15 | @Override 16 | public Duration convert(String value) { 17 | value = value.trim(); 18 | if (value.isEmpty()) { 19 | return null; 20 | } 21 | if (DIGITS.asPredicate().test(value)) { 22 | return Duration.ofSeconds(Long.parseLong(value)); 23 | } 24 | 25 | try { 26 | if (START_WITH_DIGITS.asPredicate().test(value)) { 27 | return Duration.parse(PERIOD_OF_TIME + value); 28 | } 29 | 30 | return Duration.parse(value); 31 | } catch (DateTimeParseException e) { 32 | throw new IllegalArgumentException(e); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/publish-docs.yml: -------------------------------------------------------------------------------- 1 | name: Publish Docs 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | version: 7 | required: true 8 | description: Tag version to perform release 9 | type: string 10 | 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | publish-docs: 16 | name: Publish Docs 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v6 21 | name: checkout ${{inputs.version}} 22 | with: 23 | ref: ${{inputs.version}} 24 | 25 | - name: git author 26 | run: | 27 | git config --global user.name "SmallRye CI" 28 | git config --global user.email "smallrye@googlegroups.com" 29 | 30 | - uses: actions/setup-python@v6 31 | with: 32 | python-version: '3.9' 33 | 34 | - uses: actions/setup-java@v5 35 | with: 36 | distribution: 'temurin' 37 | java-version: 17 38 | 39 | - name: docs release ${{inputs.version}} 40 | run: | 41 | cd documentation 42 | mvn package 43 | pipx install pipenv 44 | pipenv install 45 | git fetch origin gh-pages --depth=1 46 | pipenv run mike deploy --config-file=mkdocs.yaml --push --update-aliases "${PROJECT_VERSION}" Latest 47 | env: 48 | PROJECT_VERSION: ${{inputs.version}} 49 | -------------------------------------------------------------------------------- /cdi/src/main/java/io/smallrye/config/inject/MetadataInjectionPoint.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.inject; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Member; 5 | import java.lang.reflect.Type; 6 | import java.util.Collections; 7 | import java.util.Set; 8 | 9 | import jakarta.enterprise.inject.Default; 10 | import jakarta.enterprise.inject.spi.Annotated; 11 | import jakarta.enterprise.inject.spi.Bean; 12 | import jakarta.enterprise.inject.spi.InjectionPoint; 13 | import jakarta.enterprise.util.AnnotationLiteral; 14 | 15 | class MetadataInjectionPoint implements InjectionPoint { 16 | @Override 17 | public Type getType() { 18 | return InjectionPoint.class; 19 | } 20 | 21 | @SuppressWarnings("serial") 22 | @Override 23 | public Set getQualifiers() { 24 | return Collections.singleton(new AnnotationLiteral() { 25 | }); 26 | } 27 | 28 | @Override 29 | public Bean getBean() { 30 | return null; 31 | } 32 | 33 | @Override 34 | public Member getMember() { 35 | return null; 36 | } 37 | 38 | @Override 39 | public Annotated getAnnotated() { 40 | return null; 41 | } 42 | 43 | @Override 44 | public boolean isDelegate() { 45 | return false; 46 | } 47 | 48 | @Override 49 | public boolean isTransient() { 50 | return false; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/mapping/KotlinMappingGetter.kt: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.mapping 2 | 3 | import io.smallrye.config.ConfigMapping 4 | import io.smallrye.config.SmallRyeConfigBuilder 5 | import io.smallrye.config.WithDefault 6 | import org.junit.jupiter.api.Assertions.assertEquals 7 | import org.junit.jupiter.api.Test 8 | 9 | class KotlinMappingGetter { 10 | @Test 11 | fun mappingGetterNames() { 12 | val config = SmallRyeConfigBuilder() 13 | .withMapping(GraphOption::class.java) 14 | .withDefaultValue("graph.get-tenant", "tenant") 15 | .withDefaultValue("graph.get-client-id", "id") 16 | .withDefaultValue("graph.get-client-secret", "secret") 17 | .withDefaultValue("graph.get-a-boolean", "secret") 18 | .build() 19 | 20 | val mapping = config.getConfigMapping(GraphOption::class.java) 21 | assertEquals("url", mapping.baseUrl) 22 | assertEquals("tenant", mapping.tenant) 23 | assertEquals("id", mapping.clientId) 24 | assertEquals("secret", mapping.clientSecret) 25 | } 26 | 27 | @ConfigMapping(prefix = "graph") 28 | interface GraphOption { 29 | @get:WithDefault("url") 30 | val baseUrl: String 31 | val tenant: String 32 | val clientId: String 33 | val clientSecret: String 34 | val aBoolean: Boolean 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config-sources/hocon.md: -------------------------------------------------------------------------------- 1 | # HOCON Config Source 2 | 3 | This Config Source allows to use the [HOCON](https://github.com/lightbend/config/blob/main/HOCON.md) file format to 4 | load configuration values. The HOCON Config Source loads the 5 | configuration from the file `META-INF/microprofile-config.conf`. It has a lower ordinal (`50`) than the 6 | `microprofile-config.properties`. 7 | 8 | The following dependency is required in the classpath to use the HOCON Config Source: 9 | 10 | ```xml 11 | 12 | io.smallrye.config 13 | smallrye-config-source-hocon 14 | {{attributes['version']}} 15 | 16 | ``` 17 | 18 | Expressions defined as `${value}` (unquoted) are resolved internally by the HOCON Config Source as described in the 19 | [HOCON Substitutions](https://github.com/lightbend/config/blob/main/HOCON.md#substitutions) documentation. Quoted 20 | Expressions defined as `"${value}"` are resolved by [SmallRye Config Property Expressions](../config/expressions.md). 21 | 22 | Consider: 23 | 24 | **hocon.conf** 25 | ```conf 26 | { 27 | foo: "bar", 28 | hocon: ${foo}, 29 | config: "${foo}" 30 | } 31 | ``` 32 | 33 | **application.properties** 34 | ```properties 35 | config_ordinal=1000 36 | foo=baz 37 | ``` 38 | 39 | The value of `hocon` is `bar` and the value of `config` is `baz` (if the properties source has a higher ordinal). 40 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/InterceptorChainTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import org.eclipse.microprofile.config.Config; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class InterceptorChainTest { 10 | @Test 11 | void chain() { 12 | final Config config = buildConfig( 13 | "my.prop", "1", // original property 14 | "%my.prop.profile", "2", // profile property with expansion 15 | "%prof.my.prop.profile", "3", 16 | "my.prop.relocate", "4", // relocation 17 | "%prof.my.prop.relocate", "${%prof.my.prop.profile}", // profile with relocation 18 | SMALLRYE_CONFIG_PROFILE, "prof" // profile to use 19 | ); 20 | assertEquals("3", config.getValue("my.prop", String.class)); 21 | } 22 | 23 | private static Config buildConfig(String... keyValues) { 24 | return new SmallRyeConfigBuilder() 25 | .addDefaultSources() 26 | .addDefaultInterceptors() 27 | .withSources(KeyValuesConfigSource.config(keyValues)) 28 | .withInterceptors( 29 | new RelocateConfigSourceInterceptor(s -> s.replaceAll("my\\.prop", "my.prop.relocate"))) 30 | .build(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sources/yaml/src/test/java/io/smallrye/config/source/yaml/YamlConfigSourceLoaderTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.yaml; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.net.URL; 9 | import java.net.URLClassLoader; 10 | import java.nio.file.Path; 11 | 12 | import org.junit.jupiter.api.Test; 13 | import org.junit.jupiter.api.io.TempDir; 14 | 15 | import io.smallrye.config.SmallRyeConfig; 16 | import io.smallrye.config.SmallRyeConfigBuilder; 17 | 18 | public class YamlConfigSourceLoaderTest { 19 | @Test 20 | void applicationYaml(@TempDir Path tempDir) throws Exception { 21 | String yaml = "my:\n" + 22 | " prop: 1234\n"; 23 | File file = tempDir.resolve("application.yaml").toFile(); 24 | try (FileOutputStream out = new FileOutputStream(file)) { 25 | out.write(yaml.getBytes()); 26 | } 27 | 28 | SmallRyeConfig config = new SmallRyeConfigBuilder() 29 | .forClassLoader(new URLClassLoader(new URL[] { tempDir.toUri().toURL() })) 30 | .addDiscoveredSources() 31 | .build(); 32 | 33 | assertTrue(config.getConfigSources(YamlConfigSource.class).iterator().hasNext()); 34 | assertEquals("1234", config.getConfigValue("my.prop").getValue()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/source/OrdinalSourceTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.source; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.inject.Inject; 6 | 7 | import org.eclipse.microprofile.config.Config; 8 | import org.eclipse.microprofile.config.spi.ConfigSource; 9 | import org.jboss.arquillian.container.test.api.Deployment; 10 | import org.jboss.arquillian.junit5.ArquillianExtension; 11 | import org.jboss.shrinkwrap.api.ShrinkWrap; 12 | import org.jboss.shrinkwrap.api.asset.StringAsset; 13 | import org.jboss.shrinkwrap.api.spec.WebArchive; 14 | import org.junit.jupiter.api.Test; 15 | import org.junit.jupiter.api.extension.ExtendWith; 16 | 17 | @ExtendWith(ArquillianExtension.class) 18 | class OrdinalSourceTest { 19 | @Deployment 20 | static WebArchive deploy() { 21 | return ShrinkWrap.create(WebArchive.class, "ProviderTest.war") 22 | .addAsResource(new StringAsset("config_ordinal=1234"), 23 | "META-INF/microprofile-config.properties") 24 | .as(WebArchive.class); 25 | } 26 | 27 | @Inject 28 | Config config; 29 | 30 | @Test 31 | void ordinal() { 32 | for (ConfigSource configSource : config.getConfigSources()) { 33 | if (configSource.getName().contains("microprofile-config.properties")) { 34 | assertEquals(1234, configSource.getOrdinal()); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/configmap/.kubernetes/configmap-app.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: configmap-app 6 | spec: 7 | type: "LoadBalancer" 8 | ports: 9 | - name: "http" 10 | port: 8080 11 | targetPort: 8080 12 | selector: 13 | app: configmap-app 14 | --- 15 | apiVersion: apps/v1 16 | kind: Deployment 17 | metadata: 18 | name: configmap-app 19 | labels: 20 | app: configmap-app 21 | spec: 22 | replicas: 1 23 | selector: 24 | matchLabels: 25 | app: configmap-app 26 | template: 27 | metadata: 28 | labels: 29 | app: configmap-app 30 | spec: 31 | containers: 32 | - name: configmap-app 33 | image: docker-registry:5000/smallrye-config-examples/configmap-app 34 | imagePullPolicy: Always 35 | ports: 36 | - containerPort: 8080 37 | env: 38 | - name: SMALLRYE_CONFIG_SOURCE_FILE_LOCATION 39 | value: "/usr/local/apps/config" 40 | volumeMounts: 41 | - name: configmap-app 42 | mountPath: /usr/local/apps/config 43 | volumes: 44 | - name: configmap-app 45 | configMap: 46 | name: configmap-app 47 | restartPolicy: Always 48 | --- 49 | apiVersion: v1 50 | kind: ConfigMap 51 | metadata: 52 | name: configmap-app 53 | labels: 54 | app: configmap-app 55 | data: 56 | smallrye.config.example.configmap.foo: something 57 | smallrye.config.example.configmap.bar: something-else 58 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/provider/ProviderAlone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2019, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | 23 | package io.smallrye.config.test.provider; 24 | 25 | import jakarta.inject.Inject; 26 | import jakarta.inject.Provider; 27 | 28 | import org.eclipse.microprofile.config.inject.ConfigProperty; 29 | 30 | public class ProviderAlone { 31 | 32 | @Inject 33 | @ConfigProperty(name = "myEmail") 34 | Provider emailProvider; 35 | } 36 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/AbstractLocationConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static io.smallrye.config.Converters.STRING_CONVERTER; 4 | import static io.smallrye.config.Converters.newArrayConverter; 5 | import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS; 6 | 7 | import java.net.URI; 8 | import java.util.Collections; 9 | 10 | import org.eclipse.microprofile.config.spi.ConfigSource; 11 | 12 | /** 13 | * This {@code AbstractLocationConfigSourceFactory} allows to initialize additional config locations with the 14 | * configuration {@link SmallRyeConfig#SMALLRYE_CONFIG_LOCATIONS}. The configuration support multiple 15 | * locations separated by a comma and each must represent a valid {@link URI}. 16 | */ 17 | public abstract class AbstractLocationConfigSourceFactory extends AbstractLocationConfigSourceLoader 18 | implements ConfigSourceFactory { 19 | 20 | @Override 21 | protected boolean failOnMissingFile() { 22 | return true; 23 | } 24 | 25 | @Override 26 | public Iterable getConfigSources(final ConfigSourceContext context) { 27 | final ConfigValue value = context.getValue(SMALLRYE_CONFIG_LOCATIONS); 28 | if (value.getValue() == null) { 29 | return Collections.emptyList(); 30 | } 31 | 32 | return loadConfigSources(newArrayConverter(STRING_CONVERTER, String[].class).convert(value.getValue()), 33 | value.getConfigSourceOrdinal()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/provider/InstanceAlone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2019, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | 23 | package io.smallrye.config.test.provider; 24 | 25 | import jakarta.enterprise.inject.Instance; 26 | import jakarta.inject.Inject; 27 | 28 | import org.eclipse.microprofile.config.inject.ConfigProperty; 29 | 30 | public class InstanceAlone { 31 | 32 | @Inject 33 | @ConfigProperty(name = "myEmail") 34 | Instance emailInstance; 35 | } 36 | -------------------------------------------------------------------------------- /utils/events/src/main/java/io/smallrye/config/events/ChangeEvent.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.events; 2 | 3 | import java.io.Serializable; 4 | import java.util.Optional; 5 | 6 | /** 7 | * an Event on a config element 8 | * 9 | * @author Phillip Kruger 10 | */ 11 | public class ChangeEvent implements Serializable { 12 | 13 | private final Type type; 14 | private final String key; 15 | private final Optional oldValue; 16 | private final String newValue; 17 | private final String fromSource; 18 | 19 | public ChangeEvent(Type type, String key, Optional oldValue, String newValue, String fromSource) { 20 | this.type = type; 21 | this.key = key; 22 | this.oldValue = oldValue; 23 | this.newValue = newValue; 24 | this.fromSource = fromSource; 25 | } 26 | 27 | public Type getType() { 28 | return type; 29 | } 30 | 31 | public String getKey() { 32 | return key; 33 | } 34 | 35 | public Optional getOldValue() { 36 | return oldValue; 37 | } 38 | 39 | public String getNewValue() { 40 | return newValue; 41 | } 42 | 43 | public String getFromSource() { 44 | return fromSource; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "ChangeEvent{" + "type=" + type + ", key=" + key + ", oldValue=" + oldValue + ", newValue=" + newValue 50 | + ", fromSource=" + fromSource + '}'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/ConfigMappingLoaderParallelTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.parallel.Execution; 7 | import org.junit.jupiter.api.parallel.ExecutionMode; 8 | 9 | @Execution(ExecutionMode.CONCURRENT) 10 | class ConfigMappingLoaderParallelTest { 11 | @Test 12 | void testParallelThreadOne() { 13 | loadTestClass(); 14 | } 15 | 16 | @Test 17 | void testParallelThreadTwo() { 18 | loadTestClass(); 19 | } 20 | 21 | @Test 22 | void testParallelThreadThree() { 23 | loadTestClass(); 24 | } 25 | 26 | @Test 27 | void testParallelThreadFour() { 28 | loadTestClass(); 29 | } 30 | 31 | private void loadTestClass() { 32 | ConfigMappingLoader.ensureLoaded(ConfigMappingLoaderTest.Server.class); 33 | ConfigMappingLoader.ensureLoaded(ConfigMappingLoaderTest.Server.class); 34 | 35 | SmallRyeConfig config = new SmallRyeConfigBuilder().withSources( 36 | KeyValuesConfigSource.config("server.host", "localhost", "server.port", "8080")) 37 | .withMapping(ConfigMappingLoaderTest.Server.class) 38 | .build(); 39 | 40 | ConfigMappingLoaderTest.Server server = config.getConfigMapping(ConfigMappingLoaderTest.Server.class); 41 | assertEquals("localhost", server.host()); 42 | assertEquals(8080, server.port()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/Secret.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | /** 4 | * A container type to mark a {@link io.smallrye.config.ConfigMapping} member as a {@link Secret} value. 5 | *

6 | * 7 | * A {@link Secret} value modifies the behaviour of the config system by: 8 | *

    9 | *
  1. Omitting the name of the secret in {@link SmallRyeConfig#getPropertyNames()}
  2. 10 | *
  3. Omitting the name and value of the secret in the mapping {@code toString} method
  4. 11 | *
  5. Throwing a {@link SecurityException} when trying to retrieve the value via {@link SmallRyeConfig} programmatic API
  6. 12 | *
13 | * 14 | * A {@link ConfigMapping} is still capable of performing the mapping without these restrictions, and the secret value 15 | * is available for retrieval in its declared member: 16 | * 17 | *
18 |  * @ConfigMapping(prefix = "credentials")
19 |  * public interface Credentials {
20 |  *     String username();
21 |  *
22 |  *     Secret<String> password();
23 |  * }
24 |  * 
25 | * 26 | * A Secret can be of any type that can be converted by a registered 27 | * {@link org.eclipse.microprofile.config.spi.Converter} of the same type. 28 | * 29 | * @param the secret type 30 | * 31 | * @see SecretKeys 32 | * @see SmallRyeConfigBuilder#withSecretKeys(String...) 33 | */ 34 | public interface Secret { 35 | /** 36 | * Get the actual value of the {@link Secret}. 37 | * 38 | * @return the actual value of the {@link Secret}. 39 | */ 40 | T get(); 41 | } 42 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/SecretKeysConfigSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.io.Serial; 4 | import java.util.Set; 5 | 6 | import jakarta.annotation.Priority; 7 | 8 | import io.smallrye.config._private.ConfigMessages; 9 | 10 | /** 11 | * Intercept the resolution of a configuration name and throw {@link java.lang.SecurityException} if the name is a 12 | * Secret Key and the keys are locked. 13 | *

14 | * To avoid having to recalculate the list of property names, the filter of secret keys is applied in 15 | * {@code SmallRyeConfig.ConfigSources.PropertyNames}, so this interceptor does not implement 16 | * {@link io.smallrye.config.ConfigSourceInterceptor#iterateNames(ConfigSourceInterceptorContext)}. 17 | * 18 | * @see SecretKeys 19 | */ 20 | @Priority(Priorities.LIBRARY + 100) 21 | public class SecretKeysConfigSourceInterceptor implements ConfigSourceInterceptor { 22 | @Serial 23 | private static final long serialVersionUID = 7291982039729980590L; 24 | 25 | private final Set secrets; 26 | 27 | public SecretKeysConfigSourceInterceptor(final Set secrets) { 28 | this.secrets = secrets; 29 | } 30 | 31 | @Override 32 | public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { 33 | if (SecretKeys.isLocked() && secrets.contains(PropertyName.unprofiled(name))) { 34 | throw ConfigMessages.msg.notAllowed(name); 35 | } 36 | return context.proceed(name); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sources/file-system/src/main/java/io/smallrye/config/source/file/FileSystemConfigSourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.file; 2 | 3 | import static io.smallrye.config.Converters.newArrayConverter; 4 | 5 | import java.util.Collections; 6 | import java.util.OptionalInt; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.Stream; 9 | 10 | import org.eclipse.microprofile.config.spi.ConfigSource; 11 | 12 | import io.smallrye.config.ConfigSourceContext; 13 | import io.smallrye.config.ConfigSourceFactory; 14 | import io.smallrye.config.ConfigValue; 15 | import io.smallrye.config.Converters; 16 | 17 | public class FileSystemConfigSourceFactory implements ConfigSourceFactory { 18 | public static final String SMALLRYE_CONFIG_SOURCE_FILE_LOCATIONS = "smallrye.config.source.file.locations"; 19 | 20 | @Override 21 | public Iterable getConfigSources(final ConfigSourceContext context) { 22 | final ConfigValue value = context.getValue(SMALLRYE_CONFIG_SOURCE_FILE_LOCATIONS); 23 | if (value == null || value.getValue() == null) { 24 | return Collections.emptyList(); 25 | } 26 | 27 | return Stream 28 | .of(newArrayConverter(Converters.getImplicitConverter(String.class), String[].class) 29 | .convert(value.getValue())) 30 | .map(location -> new FileSystemConfigSource(location)) 31 | .collect(Collectors.toList()); 32 | } 33 | 34 | @Override 35 | public OptionalInt getPriority() { 36 | return OptionalInt.of(290); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sources/file-system/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | smallrye-config-parent 6 | io.smallrye.config 7 | 3.15.1-SNAPSHOT 8 | ../../pom.xml 9 | 10 | 11 | smallrye-config-source-file-system 12 | SmallRye Config: ConfigSource - FileSystem 13 | 14 | 15 | 16 | io.smallrye.config 17 | smallrye-config-common 18 | 19 | 20 | io.smallrye.config 21 | smallrye-config 22 | 23 | 24 | org.jboss.logging 25 | jboss-logging-annotations 26 | 27 | 28 | org.jboss.logging 29 | jboss-logging-processor 30 | 31 | 32 | 33 | org.junit.jupiter 34 | junit-jupiter 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/map-support.md: -------------------------------------------------------------------------------- 1 | # Map Support 2 | 3 | SmallRye Config allows injecting multiple configuration parameters as a `Map`. The configuration value syntax is 4 | represented by `property.name.map-key=value` Consider: 5 | 6 | ```properties 7 | server.reasons.200=OK 8 | server.reasons.201=Created 9 | ``` 10 | 11 | The previous configuration could be injected directly in a CDI Bean: 12 | 13 | With `@ConfigProperty` 14 | 15 | ```java 16 | @ApplicationScoped 17 | public class ConfigBean { 18 | @Inject 19 | @ConfigProperty(name = "server.reasons") 20 | Map reasons; 21 | } 22 | ``` 23 | 24 | With `@ConfigProperties` 25 | 26 | ```java 27 | @ConfigProperties(prefix = "server") 28 | public class Config { 29 | Map reasons; 30 | } 31 | ``` 32 | 33 | The `Map` will contains the keys `200` and `201`, which map to the values `OK` and `Created`. 34 | 35 | !!!note 36 | 37 | Only the direct sub properties will be converted into a `Map` and 38 | injected into the target bean, the rest will be ignored. In other words, 39 | in the previous example, a property whose name is `reasons.200.a` would 40 | be ignored as not considered as a direct sub property. 41 | 42 | !!!note 43 | 44 | The property will be considered as missing if no direct sub properties 45 | could be found. 46 | 47 | It is also possible to retrieve the `Map` programmatically by calling the methods 48 | `SmallRyeConfig#getValues("server.reasons", Integer.class, String.class)` or 49 | `SmallRyeConfig#getOptionalValues("server.reasons", Integer.class, String.class)`. 50 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigSourceInterceptorContext.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.io.Serializable; 4 | import java.util.Iterator; 5 | 6 | /** 7 | * Exposes contextual information about the intercepted invocation of {@link ConfigSourceInterceptor}. This allows 8 | * implementers to control the behavior of the invocation chain. 9 | */ 10 | public interface ConfigSourceInterceptorContext extends Serializable { 11 | /** 12 | * Proceeds to the next interceptor in the chain. 13 | * 14 | * @param name the configuration name to look up (can be the original key) 15 | * @return a {@link ConfigValue} with information about the name, value, config source and ordinal, or {@code null} 16 | * if the value isn't present. 17 | */ 18 | ConfigValue proceed(String name); 19 | 20 | /** 21 | * Re-calls the first interceptor in the chain. 22 | * If the original name is given, then it is possible to cause a recursive loop, so care must be taken. 23 | * This method is intended to be used by relocating and other compatibility-related interceptors. 24 | * 25 | * @param name the configuration name to look up (can be the original key) 26 | * @return a {@link ConfigValue} with information about the name, value, config source and ordinal, or {@code null} 27 | * if the value isn't present. 28 | */ 29 | ConfigValue restart(String name); 30 | 31 | /** 32 | * @return an iterator over the configuration names known to this interceptor. 33 | */ 34 | Iterator iterateNames(); 35 | } 36 | -------------------------------------------------------------------------------- /sources/hocon/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | smallrye-config-parent 6 | io.smallrye.config 7 | 3.15.1-SNAPSHOT 8 | ../../pom.xml 9 | 10 | 11 | smallrye-config-source-hocon 12 | SmallRye Config: ConfigSource - HOCON 13 | 14 | 15 | 1.4.5 16 | 17 | 18 | 19 | 20 | com.typesafe 21 | config 22 | ${lightbend-config.version} 23 | 24 | 25 | io.smallrye.config 26 | smallrye-config-core 27 | 28 | 29 | 30 | org.junit.jupiter 31 | junit-jupiter 32 | 33 | 34 | jakarta.annotation 35 | jakarta.annotation-api 36 | test 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zookeeper/src/main/java/io/smallrye/config/source/zookeeper/ZooKeepperLogging.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.zookeeper; 2 | 3 | import java.lang.invoke.MethodHandles; 4 | 5 | import org.jboss.logging.BasicLogger; 6 | import org.jboss.logging.Logger; 7 | import org.jboss.logging.annotations.Cause; 8 | import org.jboss.logging.annotations.LogMessage; 9 | import org.jboss.logging.annotations.Message; 10 | import org.jboss.logging.annotations.MessageLogger; 11 | 12 | @MessageLogger(projectCode = "SRCFG", length = 5) 13 | interface ZooKeepperLogging extends BasicLogger { 14 | ZooKeepperLogging log = Logger.getMessageLogger(MethodHandles.lookup(), ZooKeepperLogging.class, 15 | ZooKeepperLogging.class.getPackage().getName()); 16 | 17 | @LogMessage(level = Logger.Level.WARN) 18 | @Message(id = 4500, value = "Failed to retrieve property names from ZooKeeperConfigSource") 19 | void failedToRetrievePropertyNames(@Cause Throwable throwable); 20 | 21 | @LogMessage(level = Logger.Level.WARN) 22 | @Message(id = 4501, value = "Failed to retrieve properties from ZooKeeperConfigSource") 23 | void failedToRetrieveProperties(@Cause Throwable throwable); 24 | 25 | @LogMessage(level = Logger.Level.WARN) 26 | @Message(id = 4502, value = "Failed to retrieve property value for %s from ZooKeeperConfigSource") 27 | void failedToRetrieveValue(@Cause Throwable throwable, String key); 28 | 29 | @LogMessage(level = Logger.Level.INFO) 30 | @Message(id = 4503, value = "Configuring ZooKeeperConfigSource using url: %s, and applicationId: %s") 31 | void configuringZookeeper(String url, String applicationId); 32 | } 33 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/NameIteratorTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class NameIteratorTest { 8 | @Test 9 | void getNextSegment() { 10 | NameIterator nameIterator = new NameIterator("foo.bar"); 11 | assertEquals("foo", nameIterator.getNextSegment()); 12 | assertEquals("foo", nameIterator.getNextSegment()); 13 | } 14 | 15 | @Test 16 | void next() { 17 | NameIterator nameIterator = new NameIterator("foo.bar"); 18 | nameIterator.next(); 19 | assertEquals("bar", nameIterator.getNextSegment()); 20 | } 21 | 22 | @Test 23 | void getPreviousSegment() { 24 | NameIterator nameIterator = new NameIterator("foo.bar"); 25 | nameIterator.next(); 26 | assertEquals("foo", nameIterator.getPreviousSegment()); 27 | assertEquals("foo", nameIterator.getPreviousSegment()); 28 | } 29 | 30 | @Test 31 | void previous() { 32 | NameIterator nameIterator = new NameIterator("foo.bar"); 33 | nameIterator.next(); 34 | nameIterator.previous(); 35 | assertEquals("foo", nameIterator.getNextSegment()); 36 | } 37 | 38 | @Test 39 | void quotes() { 40 | NameIterator nameIterator = new NameIterator("one.\"two.three\".four"); 41 | assertEquals("one", nameIterator.getNextSegment()); 42 | nameIterator.next(); 43 | assertEquals("two.three", nameIterator.getNextSegment()); 44 | nameIterator.next(); 45 | assertEquals("four", nameIterator.getNextSegment()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/indexed-properties.md: -------------------------------------------------------------------------------- 1 | # Indexed Properties 2 | 3 | In [MicroProfile Config](https://github.com/eclipse/microprofile-config/), a config value with unescaped commas may be 4 | converted to `Collection`. It works for simple cases, but it becomes cumbersome and limited for more advanced use cases. 5 | 6 | Indexed Properties provide a way to use indexes in config property names to map specific elements in a `Collection` 7 | type. Since the indexed element is part of the property name, it can also map complex object types. Consider: 8 | 9 | ```properties 10 | # MicroProfile Config - Collection Values 11 | my.collection=dog,cat,turtle 12 | 13 | # SmallRye Config - Indexed Property 14 | my.indexed.collection[0]=dog 15 | my.indexed.collection[1]=cat 16 | my.indexed.collection[2]=turtle 17 | ``` 18 | 19 | The indexed property syntax uses the property name and square brackets with an index in between. 20 | 21 | A call to `Config#getValues("my.collection", String.class)`, will automatically create and convert a `List` 22 | that contains the values `dog`, `cat` and `turtle`. A call to `Config#getValues("my.indexed.collection", String.class)` 23 | returns the exact same result. The indexed property format is prioritized when both styles are found in the same 24 | configuration source. When available in multiple sources, the higher ordinal source wins, like any other configuration 25 | lookup. 26 | 27 | The indexed property is sorted by its index before being added to the target `Collection`. Any gaps in the indexes do 28 | not resolve to the target `Collection`, which means that the `Collection` result will store all values without empty 29 | elements. 30 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/location/LocationConfigTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.location; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.inject.Inject; 6 | 7 | import org.eclipse.microprofile.config.Config; 8 | import org.jboss.arquillian.container.test.api.Deployment; 9 | import org.jboss.arquillian.junit5.ArquillianExtension; 10 | import org.jboss.shrinkwrap.api.ShrinkWrap; 11 | import org.jboss.shrinkwrap.api.asset.StringAsset; 12 | import org.jboss.shrinkwrap.api.spec.WebArchive; 13 | import org.junit.jupiter.api.Test; 14 | import org.junit.jupiter.api.extension.ExtendWith; 15 | 16 | @ExtendWith(ArquillianExtension.class) 17 | public class LocationConfigTest { 18 | @Deployment 19 | static WebArchive deploy() { 20 | return ShrinkWrap.create(WebArchive.class, "LocationConfigTest.war") 21 | .addAsResource(new StringAsset("smallrye.config.locations=config.properties,config.yml"), 22 | "META-INF/microprofile-config.properties") 23 | .addAsResource(new StringAsset("my.prop=1234"), "config.properties") 24 | .addAsResource(new StringAsset("my:\n" + 25 | " yml: 1234\n"), "config.yml") 26 | .as(WebArchive.class); 27 | } 28 | 29 | @Inject 30 | Config config; 31 | 32 | @Test 33 | void locationConfig() { 34 | assertEquals("config.properties,config.yml", config.getValue("smallrye.config.locations", String.class)); 35 | assertEquals("1234", config.getValue("my.prop", String.class)); 36 | assertEquals("1234", config.getValue("my.yml", String.class)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/provider/ProviderBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2018, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | 23 | package io.smallrye.config.test.provider; 24 | 25 | import jakarta.inject.Inject; 26 | import jakarta.inject.Provider; 27 | 28 | import org.eclipse.microprofile.config.inject.ConfigProperty; 29 | 30 | /** 31 | * @author Jeff Mesnil (c) 2018 Red Hat inc. 32 | */ 33 | public class ProviderBean { 34 | 35 | @Inject 36 | @ConfigProperty(name = "myEmail") 37 | Email email; 38 | 39 | @Inject 40 | @ConfigProperty(name = "myEmail") 41 | Provider emailProvider; 42 | } 43 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/collections/broken/CollectionWithNoDefaultValueBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Red Hat, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.smallrye.config.test.collections.broken; 18 | 19 | import java.util.List; 20 | import java.util.Set; 21 | 22 | import jakarta.inject.Inject; 23 | 24 | import org.eclipse.microprofile.config.inject.ConfigProperty; 25 | 26 | /** 27 | * @author Jeff Mesnil (c) 2018 Red Hat inc. 28 | */ 29 | public class CollectionWithNoDefaultValueBean { 30 | 31 | @Inject 32 | @ConfigProperty(name = "myPets") 33 | private String[] arrayPets; 34 | 35 | @Inject 36 | @ConfigProperty(name = "myPets") 37 | private List listPets; 38 | 39 | @Inject 40 | @ConfigProperty(name = "myPets") 41 | private Set setPets; 42 | 43 | public String[] getArrayPets() { 44 | return arrayPets; 45 | } 46 | 47 | public List getListPets() { 48 | return listPets; 49 | } 50 | 51 | public Set getSetPets() { 52 | return setPets; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/collections/KotlinCollectionsBeanTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.collections; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.inject.Inject; 6 | 7 | import org.jboss.arquillian.container.test.api.Deployment; 8 | import org.jboss.arquillian.junit5.ArquillianExtension; 9 | import org.jboss.shrinkwrap.api.ShrinkWrap; 10 | import org.jboss.shrinkwrap.api.asset.StringAsset; 11 | import org.jboss.shrinkwrap.api.spec.WebArchive; 12 | import org.junit.jupiter.api.Test; 13 | import org.junit.jupiter.api.extension.ExtendWith; 14 | 15 | @ExtendWith(ArquillianExtension.class) 16 | class KotlinCollectionsBeanTest { 17 | @Deployment 18 | static WebArchive deploy() { 19 | return ShrinkWrap 20 | .create(WebArchive.class) 21 | .addClasses(CollectionBean.class) 22 | .addClasses(KotlinCollectionsBean.class, KotlinCollectionsBeanTest.class) 23 | .addAsManifestResource("beans.xml") 24 | .addAsResource(new StringAsset("property.list=1,2,3\n" + 25 | "property.single=1234\n"), 26 | "META-INF/microprofile-config.properties"); 27 | } 28 | 29 | @Inject 30 | KotlinCollectionsBean kotlinCollectionsBean; 31 | 32 | @Test 33 | void kotlinCollections() { 34 | assertEquals("1", kotlinCollectionsBean.typeList.get(0).getValue()); 35 | assertEquals("2", kotlinCollectionsBean.typeList.get(1).getValue()); 36 | assertEquals("3", kotlinCollectionsBean.typeList.get(2).getValue()); 37 | assertEquals("1234", kotlinCollectionsBean.singleType.getValue()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /utils/crypto/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | smallrye-config-parent 6 | io.smallrye.config 7 | 3.15.1-SNAPSHOT 8 | ../../pom.xml 9 | 10 | 11 | smallrye-config-crypto 12 | 13 | SmallRye Config: Crypto 14 | 15 | 16 | 17 | io.smallrye.config 18 | smallrye-config 19 | 20 | 21 | 22 | 23 | org.junit.jupiter 24 | junit-jupiter 25 | 26 | 27 | io.smallrye.testing 28 | smallrye-testing-utilities 29 | 30 | 31 | jakarta.annotation 32 | jakarta.annotation-api 33 | test 34 | 35 | 36 | io.smallrye.config 37 | smallrye-config-source-keystore 38 | ${project.version} 39 | test 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/secrets/MultipleSecretHandlersTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.secrets; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.util.Map; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import io.smallrye.config.PropertiesConfigSource; 10 | import io.smallrye.config.SmallRyeConfig; 11 | import io.smallrye.config.SmallRyeConfigBuilder; 12 | 13 | class MultipleSecretHandlersTest { 14 | @Test 15 | void multipleHandlers() { 16 | Map properties = Map.of( 17 | "smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key", 18 | "c29tZWFyYml0cmFyeWNyYXp5c3RyaW5ndGhhdGRvZXNub3RtYXR0ZXI", 19 | "smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key-decode", "true", 20 | "aes-gcm-nopadding.secret", "${aes-gcm-nopadding::DJNrZ6LfpupFv6QbXyXhvzD8eVDnDa_kTliQBpuzTobDZxlg}", 21 | "smallrye.config.secret-handler.jasypt.password", "jasypt", 22 | "smallrye.config.secret-handler.jasypt.algorithm", "PBEWithHMACSHA512AndAES_256", 23 | "jasypt.secret", "${jasypt::ENC(wqp8zDeiCQ5JaFvwDtoAcr2WMLdlD0rjwvo8Rh0thG5qyTQVGxwJjBIiW26y0dtU)}"); 24 | 25 | SmallRyeConfig config = new SmallRyeConfigBuilder() 26 | .addDefaultInterceptors() 27 | .addDiscoveredSecretKeysHandlers() 28 | .withSources(new PropertiesConfigSource(properties, "", 0)) 29 | .build(); 30 | 31 | assertEquals("decoded", config.getConfigValue("aes-gcm-nopadding.secret").getValue()); 32 | assertEquals("12345678", config.getConfigValue("jasypt.secret").getValue()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /utils/jasypt/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | smallrye-config-parent 6 | io.smallrye.config 7 | 3.15.1-SNAPSHOT 8 | ../../pom.xml 9 | 10 | 11 | smallrye-config-jasypt 12 | 13 | SmallRye Config: Jasypt 14 | 15 | 16 | 1.9.3 17 | 18 | 19 | 20 | 21 | io.smallrye.config 22 | smallrye-config 23 | 24 | 25 | org.jasypt 26 | jasypt 27 | ${version.jasypt} 28 | 29 | 30 | 31 | 32 | org.junit.jupiter 33 | junit-jupiter 34 | 35 | 36 | io.smallrye.testing 37 | smallrye-testing-utilities 38 | 39 | 40 | jakarta.annotation 41 | jakarta.annotation-api 42 | test 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /cdi/src/main/java/io/smallrye/config/inject/SecuritySupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Red Hat, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.smallrye.config.inject; 18 | 19 | import java.security.AccessController; 20 | import java.security.PrivilegedAction; 21 | 22 | import io.smallrye.config._private.ConfigLogging; 23 | 24 | /** 25 | * @author Jeff Mesnil (c) 2018 Red Hat inc. 26 | */ 27 | class SecuritySupport { 28 | private SecuritySupport() { 29 | } 30 | 31 | static ClassLoader getContextClassLoader() { 32 | if (System.getSecurityManager() == null) { 33 | return Thread.currentThread().getContextClassLoader(); 34 | } else { 35 | return AccessController.doPrivileged((PrivilegedAction) () -> { 36 | ClassLoader tccl = null; 37 | try { 38 | tccl = Thread.currentThread().getContextClassLoader(); 39 | } catch (SecurityException ex) { 40 | ConfigLogging.log.failedToRetrieveClassloader(ex); 41 | } 42 | return tccl; 43 | }); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /documentation/src/main/docs/extensions/relocate.md: -------------------------------------------------------------------------------- 1 | # Relocate 2 | 3 | The `io.smallrye.config.RelocateConfigSourceInterceptor` allows to relocate a configuration name to another name, by 4 | providing a transformation function or just a simple key value map. 5 | 6 | When a configuration key is renamed, lookup needs to happen on the new name, but also on the old name if the 7 | config sources are not updated yet. The relocation function gives priority to the new resolved configuration name or 8 | resolves to the old name if no value is found under the new relocation name. 9 | 10 | ```java 11 | package org.acme.config; 12 | 13 | import io.smallrye.config.RelocateConfigSourceInterceptor; 14 | 15 | public class MicroProfileConfigRelocateInterceptor extends RelocateConfigSourceInterceptor { 16 | public MicroProfileConfigRelocateInterceptor() { 17 | super(name -> name.startsWith("mp.config") ? 18 | name.replaceAll("mp\\.config", "smallrye.config") : 19 | name); 20 | } 21 | } 22 | ``` 23 | 24 | And registration in: 25 | 26 | ```properties title="META-INF/services/io.smallrye.config.ConfigSourceInterceptor" 27 | org.acme.config.MicroProfileConfigRelocateInterceptor 28 | ``` 29 | 30 | The `MicroProfileConfigRelocateInterceptor` can relocate configuration names in the `mp.config` namespace 31 | to the `smallrye.config` namespace. 32 | 33 | !!! example 34 | 35 | ```properties title="application.properties" 36 | mp.config.profile=test 37 | smallrye.config.profile=prod 38 | ``` 39 | 40 | A lookup to `mp.config.profile` returns the value `prod`. The config finds a valid value in the relocated name 41 | `smallrye.config.profile`, so the interceptor will use this value instead of the one in `mp.config.profile`. 42 | -------------------------------------------------------------------------------- /utils/cdi-provider/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.config 7 | smallrye-config-parent 8 | 3.15.1-SNAPSHOT 9 | ../../ 10 | 11 | 12 | smallrye-config-source-injection 13 | 14 | SmallRye Config: CDI ConfigSource Injection 15 | 16 | 17 | 18 | jakarta.enterprise 19 | jakarta.enterprise.cdi-api 20 | provided 21 | 22 | 23 | 24 | org.eclipse.microprofile.config 25 | microprofile-config-api 26 | provided 27 | 28 | 29 | 30 | 31 | org.junit.jupiter 32 | junit-jupiter 33 | 34 | 35 | 36 | org.jboss.weld 37 | weld-junit5 38 | 39 | 40 | 41 | io.smallrye.config 42 | smallrye-config 43 | test 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/secret-handlers/jasypt.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //DEPS info.picocli:picocli:4.5.0 3 | //DEPS org.jasypt:jasypt:1.9.3 4 | 5 | import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; 6 | import org.jasypt.iv.RandomIvGenerator; 7 | import org.jasypt.properties.PropertyValueEncryptionUtils; 8 | import picocli.CommandLine; 9 | import picocli.CommandLine.Command; 10 | import picocli.CommandLine.Option; 11 | import picocli.CommandLine.Parameters; 12 | 13 | import java.util.concurrent.Callable; 14 | import java.util.logging.Logger; 15 | 16 | @Command(name = "jasypt", mixinStandardHelpOptions = true) 17 | class jasypt implements Callable { 18 | @Option(names = {"-s", "--secret" }, description = "Secret", required = true) 19 | private String secret; 20 | @Option(names = {"-p", "--password" }, description = "Password", required = true) 21 | private String password; 22 | @Option(names = {"-a", "--algorithm" }, description = "Algorithm", defaultValue = "PBEWithHMACSHA512AndAES_256") 23 | private String algorithm; 24 | 25 | public static void main(String... args) { 26 | int exitCode = new CommandLine(new jasypt()).execute(args); 27 | System.exit(exitCode); 28 | } 29 | 30 | @Override 31 | public Integer call() { 32 | StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); 33 | encryptor.setPassword(password); 34 | encryptor.setAlgorithm(algorithm); 35 | encryptor.setIvGenerator(new RandomIvGenerator()); 36 | encryptor.initialize(); 37 | 38 | String encrypt = PropertyValueEncryptionUtils.encrypt(secret, encryptor); 39 | System.out.println("${jasypt::" + encrypt + "}"); 40 | 41 | return 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/FallbackConfigSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static io.smallrye.config.ConfigValue.CONFIG_SOURCE_COMPARATOR; 4 | 5 | import java.io.Serial; 6 | import java.util.Map; 7 | import java.util.function.Function; 8 | 9 | import jakarta.annotation.Priority; 10 | 11 | @Priority(Priorities.LIBRARY + 600) 12 | public class FallbackConfigSourceInterceptor extends AbstractMappingConfigSourceInterceptor { 13 | @Serial 14 | private static final long serialVersionUID = 1472367702046537565L; 15 | 16 | public FallbackConfigSourceInterceptor(final Function mapping) { 17 | super(mapping); 18 | } 19 | 20 | public FallbackConfigSourceInterceptor(final Map mappings) { 21 | super(mappings); 22 | } 23 | 24 | @Override 25 | public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { 26 | ConfigValue configValue = context.proceed(name); 27 | String map = getMapping().apply(name); 28 | 29 | if (name.equals(map)) { 30 | return configValue; 31 | } 32 | 33 | ConfigValue fallbackValue = context.proceed(map); 34 | // Check which one comes from a higher ordinal source 35 | if (configValue != null && fallbackValue != null) { 36 | return CONFIG_SOURCE_COMPARATOR.compare(configValue, fallbackValue) >= 0 ? configValue 37 | : fallbackValue.withName(name); 38 | } else { 39 | if (configValue != null) { 40 | return configValue; 41 | } else if (fallbackValue != null) { 42 | return fallbackValue.withName(name); 43 | } 44 | return null; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/RelocateConfigSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static io.smallrye.config.ConfigValue.CONFIG_SOURCE_COMPARATOR; 4 | 5 | import java.io.Serial; 6 | import java.util.Map; 7 | import java.util.function.Function; 8 | 9 | import jakarta.annotation.Priority; 10 | 11 | @Priority(Priorities.LIBRARY + 300) 12 | public class RelocateConfigSourceInterceptor extends AbstractMappingConfigSourceInterceptor { 13 | @Serial 14 | private static final long serialVersionUID = 3476637906383945843L; 15 | 16 | public RelocateConfigSourceInterceptor(final Function mapping) { 17 | super(mapping); 18 | } 19 | 20 | public RelocateConfigSourceInterceptor(final Map mappings) { 21 | super(mappings); 22 | } 23 | 24 | @Override 25 | public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { 26 | String map = getMapping().apply(name); 27 | ConfigValue relocateValue = context.proceed(map); 28 | 29 | if (name.equals(map)) { 30 | return relocateValue; 31 | } 32 | 33 | ConfigValue configValue = context.proceed(name); 34 | // Check which one comes from a higher ordinal source 35 | if (relocateValue != null && configValue != null) { 36 | return CONFIG_SOURCE_COMPARATOR.compare(relocateValue, configValue) >= 0 ? relocateValue 37 | : configValue.withName(map); 38 | } else { 39 | if (relocateValue != null) { 40 | return relocateValue; 41 | } else if (configValue != null) { 42 | return configValue.withName(map); 43 | } 44 | return null; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /validator/src/test/java/io/smallrye/config/validator/KeyValuesConfigSource.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.validator; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collections; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | import org.eclipse.microprofile.config.spi.ConfigSource; 10 | 11 | public class KeyValuesConfigSource implements ConfigSource, Serializable { 12 | 13 | private final Map properties = new HashMap<>(); 14 | 15 | private KeyValuesConfigSource(Map properties) { 16 | this.properties.putAll(properties); 17 | } 18 | 19 | @Override 20 | public Map getProperties() { 21 | return Collections.unmodifiableMap(properties); 22 | } 23 | 24 | @Override 25 | public Set getPropertyNames() { 26 | return Collections.unmodifiableSet(properties.keySet()); 27 | } 28 | 29 | @Override 30 | public String getValue(String propertyName) { 31 | return properties.get(propertyName); 32 | } 33 | 34 | @Override 35 | public String getName() { 36 | return "KeyValuesConfigSource"; 37 | } 38 | 39 | public static ConfigSource config(Map properties) { 40 | return new KeyValuesConfigSource(properties); 41 | } 42 | 43 | public static ConfigSource config(String... keyValues) { 44 | if (keyValues.length % 2 != 0) { 45 | throw new IllegalArgumentException("keyValues array must be a multiple of 2"); 46 | } 47 | 48 | Map props = new HashMap<>(); 49 | for (int i = 0; i < keyValues.length; i += 2) { 50 | props.put(keyValues[i], keyValues[i + 1]); 51 | } 52 | return new KeyValuesConfigSource(props); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/mapping/src/main/java/io/smallrye/config/examples/mapping/Server.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import java.time.Duration; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithConverter; 10 | import io.smallrye.config.WithDefault; 11 | import io.smallrye.config.WithName; 12 | 13 | @ConfigMapping(prefix = "server") 14 | public interface Server { 15 | String host(); 16 | 17 | int port(); 18 | 19 | @WithConverter(DurationConverter.class) 20 | Duration timeout(); 21 | 22 | @WithName("io-threads") 23 | int threads(); 24 | 25 | Map form(); 26 | 27 | Optional ssl(); 28 | 29 | Optional proxy(); 30 | 31 | Optional cors(); 32 | 33 | Log log(); 34 | 35 | interface Ssl { 36 | int port(); 37 | 38 | String certificate(); 39 | 40 | @WithDefault("TLSv1.3,TLSv1.2") 41 | List protocols(); 42 | } 43 | 44 | interface Proxy { 45 | boolean enable(); 46 | } 47 | 48 | interface Log { 49 | @WithDefault("false") 50 | boolean enabled(); 51 | 52 | @WithDefault(".log") 53 | String suffix(); 54 | 55 | @WithDefault("true") 56 | boolean rotate(); 57 | 58 | @WithDefault("COMMON") 59 | Pattern pattern(); 60 | 61 | enum Pattern { 62 | COMMON, 63 | SHORT, 64 | COMBINED, 65 | LONG; 66 | } 67 | } 68 | 69 | interface Cors { 70 | List origins(); 71 | 72 | List methods(); 73 | 74 | interface Origin { 75 | String host(); 76 | 77 | int port(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /examples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | io.smallrye.config 22 | smallrye-config-parent 23 | 3.15.1-SNAPSHOT 24 | 25 | 26 | smallrye-config-examples 27 | pom 28 | 29 | SmallRye Config Examples 30 | 31 | 32 | interceptors 33 | expansion 34 | profiles 35 | configmap 36 | mapping 37 | 38 | 39 | 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-install-plugin 44 | 45 | true 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/source/MultiplePropertiesConfigSourceTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.source; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.inject.Inject; 6 | 7 | import org.eclipse.microprofile.config.Config; 8 | import org.jboss.arquillian.container.test.api.Deployment; 9 | import org.jboss.arquillian.junit5.ArquillianExtension; 10 | import org.jboss.shrinkwrap.api.ShrinkWrap; 11 | import org.jboss.shrinkwrap.api.asset.StringAsset; 12 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 13 | import org.jboss.shrinkwrap.api.spec.WebArchive; 14 | import org.junit.jupiter.api.Test; 15 | import org.junit.jupiter.api.extension.ExtendWith; 16 | 17 | @ExtendWith(ArquillianExtension.class) 18 | public class MultiplePropertiesConfigSourceTest { 19 | @Deployment 20 | public static WebArchive deploy() { 21 | JavaArchive sourceOne = ShrinkWrap 22 | .create(JavaArchive.class, "source-one.jar") 23 | .addAsManifestResource(new StringAsset("my.prop.one=1234"), "microprofile-config.properties") 24 | .as(JavaArchive.class); 25 | 26 | JavaArchive sourceTwo = ShrinkWrap 27 | .create(JavaArchive.class, "source-two.jar") 28 | .addAsManifestResource(new StringAsset("my.prop.two=1234"), "microprofile-config.properties") 29 | .as(JavaArchive.class); 30 | 31 | return ShrinkWrap 32 | .create(WebArchive.class, "sources.war") 33 | .addAsLibraries(sourceOne, sourceTwo); 34 | } 35 | 36 | @Inject 37 | Config config; 38 | 39 | @Test 40 | void multiple() { 41 | assertEquals("1234", config.getValue("my.prop.one", String.class)); 42 | assertEquals("1234", config.getValue("my.prop.two", String.class)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/customizer.md: -------------------------------------------------------------------------------- 1 | # Customizer 2 | 3 | A `SmallRyeConfigBuilderCustomizer` allows to customize a `SmallRyeConfigBuilder`, used to create the `SmallRyeConfig` 4 | instance. 5 | 6 | Registration of a `SmallRyeConfigBuilderCustomizer` is done via the `ServiceLoader` mechanism by providing the 7 | implementation classes in a `META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer` file. Alternatively, 8 | customizers may be registered via the Programmatic API in `SmallRyeConfigBuilder#withCustomizers`. 9 | 10 | The `SmallRyeConfigBuilderCustomizer` may also 11 | assign a priority by overriding the default method `int priority()`. Customizers are sorted by ascending priority and 12 | executed in that order, meaning that higher numeric priorities will execute last, possible overriding values set by 13 | previous customizers. 14 | 15 | ```java title="CustomConfigBuilder" 16 | package org.acme.config; 17 | 18 | import io.smallrye.config.SmallRyeConfigBuilder; 19 | import io.smallrye.config.SmallRyeConfigBuilderCustomizer; 20 | 21 | public class CustomConfigBuilder implements SmallRyeConfigBuilderCustomizer { 22 | @Override 23 | public void configBuilder(final SmallRyeConfigBuilder builder) { 24 | builder.withDefaultValue("my.default", "1234"); 25 | } 26 | } 27 | ``` 28 | 29 | And registration in: 30 | 31 | ```properties title="META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer" 32 | org.acme.config.CustomConfigBuilder 33 | ``` 34 | 35 | The `CustomConfigBuilder` will be executed when creating a new `SmallRyeConfig` from a `SmallRyeConfigBuilder`: 36 | 37 | ```java 38 | SmallRyeConfig config = new SmallRyeConfigBuilder().build(); 39 | config.getValue("my.default", int.class); 40 | ``` 41 | 42 | A look up to `my.default` returns the value `1234`, registered by the `CustomConfigBuilder`. 43 | 44 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigurableConfigSource.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | import org.eclipse.microprofile.config.spi.ConfigSource; 11 | 12 | public class ConfigurableConfigSource implements ConfigSource { 13 | private final ConfigSourceFactory factory; 14 | 15 | public ConfigurableConfigSource(ConfigSourceFactory factory) { 16 | this.factory = factory; 17 | } 18 | 19 | @Override 20 | public Map getProperties() { 21 | return new HashMap<>(); 22 | } 23 | 24 | @Override 25 | public Set getPropertyNames() { 26 | return new HashSet<>(); 27 | } 28 | 29 | @Override 30 | public String getValue(final String propertyName) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public String getName() { 36 | return factory.getClass().getName(); 37 | } 38 | 39 | @Override 40 | public int getOrdinal() { 41 | return factory.getPriority().orElse(DEFAULT_ORDINAL); 42 | } 43 | 44 | ConfigSourceFactory getFactory() { 45 | return factory; 46 | } 47 | 48 | List getConfigSources(final ConfigSourceContext context) { 49 | final List configSources = new ArrayList<>(); 50 | for (final ConfigSource configSource : factory.getConfigSources(context)) { 51 | if (configSource instanceof ConfigurableConfigSource) { 52 | configSources.addAll(((ConfigurableConfigSource) configSource).getConfigSources(context)); 53 | } else { 54 | configSources.add(configSource); 55 | } 56 | } 57 | return configSources; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/provider/Email.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source. 3 | * Copyright 2018, Red Hat, Inc., and individual contributors 4 | * as indicated by the @author tags. See the copyright.txt file in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * This is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this software; if not, write to the Free 19 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 | */ 22 | 23 | package io.smallrye.config.test.provider; 24 | 25 | /** 26 | * @author Jeff Mesnil (c) 2018 Red Hat inc. 27 | */ 28 | public class Email { 29 | private String name; 30 | private String domain; 31 | 32 | public Email(String value) { 33 | String[] components = value.split("@"); 34 | if (components.length == 2) { 35 | name = components[0]; 36 | domain = components[1]; 37 | } 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public String getDomain() { 45 | return domain; 46 | } 47 | 48 | public String toString() { 49 | return name + "(at)" + domain; 50 | } 51 | } -------------------------------------------------------------------------------- /cdi/src/main/java/io/smallrye/config/inject/ConfigException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Apache Software Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.smallrye.config.inject; 18 | 19 | import java.io.Serial; 20 | 21 | /** 22 | * A relatively generic Exception that encapsulates the configuration 23 | * property's name. 24 | * 25 | * @author Steve Moyer - The Pennsylvania State University 26 | */ 27 | public class ConfigException extends Exception { 28 | @Serial 29 | private static final long serialVersionUID = 1L; 30 | 31 | private final String configPropertyName; 32 | 33 | /** 34 | * Constructor for {@link InjectionMessages#noConfigValue(String, String)} 35 | */ 36 | public ConfigException(String message, String configPropertyName) { 37 | super(message); 38 | this.configPropertyName = configPropertyName; 39 | } 40 | 41 | /** 42 | * Constructor for {@link InjectionMessages#retrieveConfigFailure(String, String, String, Exception)} 43 | */ 44 | public ConfigException(String message, String configPropertyName, Throwable cause) { 45 | super(message, cause); 46 | this.configPropertyName = configPropertyName; 47 | } 48 | 49 | public String getConfigPropertyName() { 50 | return configPropertyName; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config-sources/filesystem.md: -------------------------------------------------------------------------------- 1 | # FileSystem Config Source 2 | 3 | This Config Source loads configuration values for each file found in a directory. Each file corresponds to a single 4 | property, where the file name is the configuration property name and the file content the configuration value. 5 | 6 | For instance, if a directory structure looks like: 7 | 8 | foo/ 9 | |__num.max 10 | |__num.size 11 | 12 | The `FileSystem` Config Source will provide 2 properties: 13 | 14 | - num.max 15 | - num.size 16 | 17 | !!! warning 18 | 19 | Nested directories are not supported. 20 | 21 | This Config Source can be used to read configuration from 22 | [Kubernetes ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap). Check the 23 | [Kubernetes ConfigMap ConfigSource Example](https://github.com/smallrye/smallrye-config/blob/main/examples/configmap/README.adoc). 24 | 25 | The same mapping rules as defined for environment variables are applied, so the `FileSystem` Config Source will search 26 | for a given property name `num.max`: 27 | 28 | - Exact match (`num.max`) 29 | - Replace each character that is neither alphanumeric nor \_ with \_ (`num_max`) 30 | - Replace each character that is neither alphanumeric nor \_ with \_; then convert the name to upper case (`NUM_MAX`) 31 | 32 | The following dependency is required in the classpath to use the `FileSystem` Config Source: 33 | 34 | ```xml 35 | 36 | io.smallrye.config 37 | smallrye-config-source-file-system 38 | {{attributes['version']}} 39 | 40 | ``` 41 | 42 | The configuration property `smallrye.config.source.file.locations` sets the directory paths to look up the files. It 43 | accepts multiple locations separated by a comma and each must represent a valid URI to a directory. 44 | -------------------------------------------------------------------------------- /documentation/src/main/docs/extensions/fallback.md: -------------------------------------------------------------------------------- 1 | # Fallback 2 | 3 | The `io.smallrye.config.FallbackConfigSourceInterceptor` allows to fall back to another configuration name, by 4 | providing a transformation function or just a simple key value map. 5 | 6 | When a configuration name does not exist, there might be another configuration name that the config can 7 | fall back to provide the same expected behavior. The fallback function is only applied if the original resolved 8 | configuration name is not found and resolved to the fallback name. 9 | 10 | ```java 11 | package org.acme.config; 12 | 13 | import io.smallrye.config.FallbackConfigSourceInterceptor; 14 | 15 | public class MicroProfileConfigFallbackInterceptor extends FallbackConfigSourceInterceptor { 16 | public MicroProfileConfigFallbackInterceptor() { 17 | super(name -> name.startsWith("mp.config") ? 18 | name.replaceAll("mp\\.config", "smallrye.config") : 19 | name); 20 | } 21 | } 22 | ``` 23 | 24 | And registration in: 25 | 26 | ```properties title="META-INF/services/io.smallrye.config.ConfigSourceInterceptor" 27 | org.acme.config.MicroProfileConfigFallbackInterceptor 28 | ``` 29 | 30 | The `MicroProfileConfigFallbackInterceptor` can fallback configuration names in the `mp.config` namespace 31 | to the `smallrye.config` namespace. 32 | 33 | !!! example 34 | 35 | ```properties title="application.properties" 36 | mp.config.profile=test 37 | smallrye.config.profile=prod 38 | ``` 39 | 40 | A lookup to `mp.config.profile` returns the value `test`. 41 | 42 | ```properties title="application.properties" 43 | smallrye.config.profile=prod 44 | ``` 45 | 46 | A lookup to `mp.config.profile` returns the value `prod`. The config is not able to find a value for 47 | `mp.config.profile`, so the interceptor fallbacks and lookups the value of `smallrye.config.profile`. 48 | -------------------------------------------------------------------------------- /examples/configmap/src/main/java/io/smallrye/config/examples/configmap/ConfigMapApp.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.configmap; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.Map; 5 | 6 | import org.eclipse.microprofile.config.Config; 7 | import org.eclipse.microprofile.config.ConfigProvider; 8 | import org.eclipse.microprofile.config.spi.ConfigSource; 9 | 10 | import com.sun.net.httpserver.HttpServer; 11 | 12 | public class ConfigMapApp { 13 | public static void main(String[] args) throws Exception { 14 | Config config = ConfigProvider.getConfig(); 15 | 16 | HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); 17 | server.createContext("/configMap", exchange -> { 18 | boolean responseSent = false; 19 | 20 | final Iterable configSources = config.getConfigSources(); 21 | for (ConfigSource configSource : configSources) { 22 | if (configSource.getName().startsWith("FileSystemConfig")) { 23 | final Map properties = configSource.getProperties(); 24 | final byte[] bytes = properties.toString().getBytes(); 25 | exchange.sendResponseHeaders(200, properties.toString().length()); 26 | exchange.getResponseBody().write(bytes); 27 | exchange.getResponseBody().flush(); 28 | exchange.getResponseBody().close(); 29 | responseSent = true; 30 | break; 31 | } 32 | } 33 | 34 | if (!responseSent) { 35 | exchange.sendResponseHeaders(404, 0); 36 | exchange.getResponseBody().write(new byte[0]); 37 | exchange.getResponseBody().flush(); 38 | exchange.getResponseBody().close(); 39 | } 40 | }); 41 | 42 | server.start(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/ConfigValueConfigSourceWrapperTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | class ConfigValueConfigSourceWrapperTest { 11 | @Test 12 | void getConfigValue() { 13 | ConfigValue configValue = config().getConfigValue("my.prop"); 14 | assertNotNull(configValue); 15 | assertEquals("1234", configValue.getValue()); 16 | assertEquals("1234", configValue.getRawValue()); 17 | } 18 | 19 | @Test 20 | void getConfigValueProperties() { 21 | Map map = config().getConfigValueProperties(); 22 | assertEquals(1, map.size()); 23 | assertTrue(map.containsKey("my.prop")); 24 | assertEquals("1234", map.get("my.prop").getValue()); 25 | } 26 | 27 | @Test 28 | void getProperties() { 29 | final Map map = config().getProperties(); 30 | assertEquals(1, map.size()); 31 | assertTrue(map.containsKey("my.prop")); 32 | } 33 | 34 | @Test 35 | void getValue() { 36 | assertEquals("1234", config().getValue("my.prop")); 37 | } 38 | 39 | @Test 40 | void getPropertyNames() { 41 | final Set names = config().getPropertyNames(); 42 | assertEquals(1, names.size()); 43 | assertEquals("my.prop", names.iterator().next()); 44 | } 45 | 46 | @Test 47 | void getName() { 48 | assertEquals("KeyValuesConfigSource", config().getName()); 49 | } 50 | 51 | @Test 52 | void getOrdinal() { 53 | assertEquals(100, config().getOrdinal()); 54 | } 55 | 56 | private static ConfigValueConfigSource config() { 57 | return SmallRyeConfigSources.ConfigValueConfigSourceWrapper.wrap(KeyValuesConfigSource.config("my.prop", "1234")); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/LoggingConfigSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static io.smallrye.config.SecretKeys.doLocked; 4 | 5 | import java.io.Serial; 6 | 7 | import jakarta.annotation.Priority; 8 | 9 | import io.smallrye.config._private.ConfigLogging; 10 | 11 | @Priority(Priorities.LIBRARY + 250) 12 | public class LoggingConfigSourceInterceptor implements ConfigSourceInterceptor { 13 | @Serial 14 | private static final long serialVersionUID = 367246512037404779L; 15 | 16 | private final boolean enabled; 17 | 18 | public LoggingConfigSourceInterceptor() { 19 | this(true); 20 | } 21 | 22 | public LoggingConfigSourceInterceptor(final boolean enabled) { 23 | this.enabled = enabled; 24 | } 25 | 26 | @Override 27 | public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { 28 | if (!enabled || !ConfigLogging.log.isDebugEnabled()) { 29 | return context.proceed(name); 30 | } 31 | 32 | try { 33 | // Unlocked keys will run here. 34 | ConfigValue configValue = doLocked(() -> context.proceed(name)); 35 | if (configValue != null) { 36 | ConfigLogging.log.lookup(configValue.getName(), configValue.getLocation(), configValue.getValue()); 37 | } else { 38 | ConfigLogging.log.notFound(name); 39 | } 40 | return configValue; 41 | } catch (SecurityException e) { 42 | // Handled next, to omit the values to log from the secret. 43 | } 44 | 45 | // Locked keys here. 46 | final ConfigValue secret = context.proceed(name); 47 | if (secret != null) { 48 | ConfigLogging.log.lookup(secret.getName(), "secret", "secret"); 49 | } else { 50 | ConfigLogging.log.notFound(name); 51 | } 52 | return secret; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/source/MultipleProfilePropertiesConfigSourceTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.source; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import jakarta.inject.Inject; 6 | 7 | import org.eclipse.microprofile.config.Config; 8 | import org.jboss.arquillian.container.test.api.Deployment; 9 | import org.jboss.arquillian.junit5.ArquillianExtension; 10 | import org.jboss.shrinkwrap.api.ShrinkWrap; 11 | import org.jboss.shrinkwrap.api.asset.StringAsset; 12 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 13 | import org.jboss.shrinkwrap.api.spec.WebArchive; 14 | import org.junit.jupiter.api.Test; 15 | import org.junit.jupiter.api.extension.ExtendWith; 16 | 17 | @ExtendWith(ArquillianExtension.class) 18 | class MultipleProfilePropertiesConfigSourceTest { 19 | @Deployment 20 | static WebArchive deploy() { 21 | JavaArchive sourceOne = ShrinkWrap 22 | .create(JavaArchive.class) 23 | .addAsManifestResource(new StringAsset("smallrye.config.profile=prod"), "microprofile-config.properties") 24 | .addAsManifestResource(new StringAsset("my.prop.one=1234"), "microprofile-config-prod.properties") 25 | .as(JavaArchive.class); 26 | 27 | JavaArchive sourceTwo = ShrinkWrap 28 | .create(JavaArchive.class) 29 | .addAsManifestResource(new StringAsset("my.prop.two=1234"), "microprofile-config-prod.properties") 30 | .as(JavaArchive.class); 31 | 32 | return ShrinkWrap 33 | .create(WebArchive.class, "sources.war") 34 | .addAsLibraries(sourceOne, sourceTwo); 35 | } 36 | 37 | @Inject 38 | Config config; 39 | 40 | @Test 41 | void multiple() { 42 | assertEquals("1234", config.getValue("my.prop.one", String.class)); 43 | assertEquals("1234", config.getValue("my.prop.two", String.class)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sources/yaml/src/test/java/io/smallrye/config/source/yaml/BasicTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.source.yaml; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | 6 | import org.eclipse.microprofile.config.spi.ConfigSource; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class BasicTest { 10 | @Test 11 | void basicKeyValue() { 12 | String yaml = "foo:\n" 13 | + " bar:\n" 14 | + " baz: something\n" 15 | + " zap: something else \n"; 16 | 17 | ConfigSource src = new YamlConfigSource("Yaml", yaml); 18 | 19 | assertEquals("something", src.getValue("foo.bar.baz")); 20 | assertEquals("something else", src.getValue("foo.bar.zap")); 21 | } 22 | 23 | @Test 24 | void nullKeyValue() { 25 | String yaml = "foo:\n" 26 | + " ~: something\n"; 27 | 28 | ConfigSource src = new YamlConfigSource("Yaml", yaml); 29 | 30 | assertEquals("something", src.getValue("foo")); 31 | } 32 | 33 | @Test 34 | void listValue() { 35 | String yaml = "foo:\n" 36 | + " bar:\n" 37 | + " ~:\n" 38 | + " - cat\n" 39 | + " - dog\n" 40 | + " - chicken\n"; 41 | 42 | ConfigSource src = new YamlConfigSource("Yaml", yaml); 43 | 44 | assertEquals("cat,dog,chicken", src.getValue("foo.bar")); 45 | } 46 | 47 | @Test 48 | void emptyFile() { 49 | ConfigSource src = new YamlConfigSource("Yaml", ""); 50 | assertNotNull(src, "Should create config source for empty file correctly"); 51 | } 52 | 53 | @Test 54 | void preserveOriginal() { 55 | ConfigSource source = new YamlConfigSource("Yaml", "date: 2010-10-10"); 56 | assertEquals("2010-10-10", source.getValue("date")); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigSourceContext.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.util.HashSet; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import org.eclipse.microprofile.config.spi.ConfigSource; 9 | 10 | /** 11 | * Exposes contextual information on the ConfigSource initialization via {@link ConfigSourceFactory}. 12 | */ 13 | public interface ConfigSourceContext { 14 | ConfigValue getValue(String name); 15 | 16 | Iterator iterateNames(); 17 | 18 | default List getProfiles() { 19 | throw new UnsupportedOperationException(); 20 | } 21 | 22 | default List getConfigSources() { 23 | throw new UnsupportedOperationException(); 24 | } 25 | 26 | class ConfigSourceContextConfigSource implements ConfigSource { 27 | private final ConfigSourceContext context; 28 | 29 | public ConfigSourceContextConfigSource(final ConfigSourceContext context) { 30 | this.context = context; 31 | } 32 | 33 | @Override 34 | public Set getPropertyNames() { 35 | Set names = new HashSet<>(); 36 | Iterator namesIterator = context.iterateNames(); 37 | while (namesIterator.hasNext()) { 38 | names.add(namesIterator.next()); 39 | } 40 | return names; 41 | } 42 | 43 | @Override 44 | public String getValue(final String propertyName) { 45 | ConfigValue value = context.getValue(propertyName); 46 | return value != null && value.getValue() != null ? value.getValue() : null; 47 | } 48 | 49 | @Override 50 | public String getName() { 51 | return ConfigSourceContextConfigSource.class.getName(); 52 | } 53 | 54 | @Override 55 | public int getOrdinal() { 56 | return Integer.MAX_VALUE; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /documentation/src/main/docs/assets/smallrye-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | SmallRye Icon 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/config/MultiValueTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | import java.util.TreeSet; 14 | 15 | import org.junit.jupiter.api.BeforeEach; 16 | import org.junit.jupiter.api.Test; 17 | 18 | class MultiValueTest { 19 | 20 | SmallRyeConfig config; 21 | 22 | @BeforeEach 23 | void setUp() { 24 | config = SmallRyeConfigProviderResolver.instance().getBuilder() 25 | .withSources(new PropertiesConfigSource(Map.of("my.pets", "snake,dog,cat,cat"), "my properties")) 26 | .build() 27 | .unwrap(SmallRyeConfig.class); 28 | } 29 | 30 | @Test 31 | void getValuesAsList() { 32 | List pets = config.getValues("my.pets", String.class, ArrayList::new); 33 | assertNotNull(pets); 34 | assertEquals(4, pets.size()); 35 | assertEquals(Arrays.asList("snake", "dog", "cat", "cat"), pets); 36 | } 37 | 38 | @Test 39 | void getValuesAsSet() { 40 | Set pets = config.getValues("my.pets", String.class, HashSet::new); 41 | assertNotNull(pets); 42 | assertEquals(3, pets.size()); 43 | assertTrue(pets.contains("snake")); 44 | assertTrue(pets.contains("dog")); 45 | assertTrue(pets.contains("cat")); 46 | } 47 | 48 | @Test 49 | void getValuesAsSortedSet() { 50 | Set pets = config.getValues("my.pets", String.class, s -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); 51 | assertNotNull(pets); 52 | assertEquals(3, pets.size()); 53 | assertEquals(Arrays.asList("cat", "dog", "snake"), new ArrayList<>(pets)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/configmap/README.adoc: -------------------------------------------------------------------------------- 1 | = Kubernetes ConfigMap ConfigSource Example 2 | 3 | In this example, the `FileSystemConfigSource` is used to access a Kubernetes ConfigMap configuration. 4 | 5 | == Setup 6 | 7 | Since the `FileSystemConfigSource` is implemented in a separate `SmallRyeConfig` module, it requires an additional 8 | dependency in the project that wants to read configuration from Kubernetes ConfigMap. 9 | 10 | [source,xml,subs="verbatim,attributes"] 11 | ---- 12 | 13 | io.smallrye.config 14 | smallrye-config-source-file-system 15 | {version} 16 | 17 | ---- 18 | 19 | == Registration 20 | 21 | The `smallrye-config-source-file-system` automatically registers a `FileSystemConfigSourceFactory` that accepts the 22 | configuration property `smallrye.config.source.file.location` to set the volume path and read the Kubernetes ConfigMap. 23 | 24 | Usually, an environment variable `SMALLRYE_CONFIG_SOURCE_FILE_LOCATION` sets the ConfigMap location in the Kubernetes 25 | file descriptor. 26 | 27 | == Run 28 | 29 | The example starts a simple http server with a single endpoint im `/configMap`. To deploy the example in a Kubernetes 30 | cluster requires the following steps. 31 | 32 | Set up a local Docker Registry first to store the generated Docker images: 33 | 34 | [source,bash] 35 | ---- 36 | docker run -d -p 5000:5000 --restart=always --name docker-registry registry:2 37 | ---- 38 | 39 | Set up a host in '/etc/hosts' pointing `127.0.0.1` to `docker-registry`. 40 | 41 | Build the example with: 42 | 43 | [source,bash] 44 | ---- 45 | mvn package docker:build docker:push 46 | ---- 47 | 48 | Deploy to Kubernetes with: 49 | 50 | [source,bash] 51 | ---- 52 | kubectl apply -f .kubernetes 53 | ---- 54 | 55 | Call tbe endpoint `curl http://localhost:8080/configMap`. This should list all the configurations set in the Kubernets 56 | Config Map. The Kubernetes and ConfigMap configuration can be found in `.kubernetes/configmap-app.yml`. 57 | -------------------------------------------------------------------------------- /common/src/test/java/io/smallrye/config/common/utils/ConfigSourceUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.smallrye.config.common.utils; 17 | 18 | import static org.junit.jupiter.api.Assertions.assertEquals; 19 | import static org.junit.jupiter.api.Assertions.assertTrue; 20 | 21 | import java.util.Map; 22 | import java.util.Properties; 23 | 24 | import org.junit.jupiter.api.Test; 25 | 26 | class ConfigSourceUtilTest { 27 | @Test 28 | void propertiesToMap() { 29 | Properties properties = new Properties(); 30 | properties.put("my.key1", "my.value1"); 31 | properties.put("my.key2", "my.value2"); 32 | properties.put("my.key3", 2); 33 | 34 | Map map = ConfigSourceUtil.propertiesToMap(properties); 35 | assertEquals("my.value1", map.get("my.key1")); 36 | assertEquals("my.value2", map.get("my.key2")); 37 | assertEquals("2", map.get("my.key3")); 38 | } 39 | 40 | @Test 41 | void unableToConvertToString() { 42 | Properties properties = new Properties(); 43 | properties.put("foo.bar", new UnconvertableString()); 44 | 45 | Map map = ConfigSourceUtil.propertiesToMap(properties); 46 | assertTrue(map.isEmpty()); 47 | } 48 | 49 | private static class UnconvertableString { 50 | @Override 51 | public String toString() { 52 | throw new UnsupportedOperationException(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/mapping/src/test/java/io/smallrye/config/examples/mapping/ServerMappingTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import static java.util.stream.Collectors.toList; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertFalse; 6 | import static org.junit.jupiter.api.Assertions.assertTrue; 7 | 8 | import java.time.Duration; 9 | import java.util.stream.Stream; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | class ServerMappingTest { 14 | @Test 15 | void mapping() { 16 | final Server server = ServerMapping.getServer(); 17 | assertEquals("localhost", server.host()); 18 | assertEquals(8080, server.port()); 19 | assertEquals(Duration.ofSeconds(60), server.timeout()); 20 | assertEquals(200, server.threads()); 21 | 22 | assertEquals("login.html", server.form().get("login-page")); 23 | assertEquals("error.html", server.form().get("error-page")); 24 | assertEquals("index.html", server.form().get("landing-page")); 25 | 26 | assertTrue(server.ssl().isPresent()); 27 | assertEquals(8443, server.ssl().get().port()); 28 | assertEquals(Stream.of("TLSv1.3", "TLSv1.2").collect(toList()), server.ssl().get().protocols()); 29 | 30 | assertFalse(server.proxy().isPresent()); 31 | 32 | assertFalse(server.log().enabled()); 33 | assertEquals(".log", server.log().suffix()); 34 | assertTrue(server.log().rotate()); 35 | assertEquals(Server.Log.Pattern.COMMON, server.log().pattern()); 36 | 37 | assertTrue(server.cors().isPresent()); 38 | assertEquals("some-server", server.cors().get().origins().get(0).host()); 39 | assertEquals(9000, server.cors().get().origins().get(0).port()); 40 | assertEquals("another-server", server.cors().get().origins().get(1).host()); 41 | assertEquals(8000, server.cors().get().origins().get(1).port()); 42 | assertEquals("GET", server.cors().get().methods().get(0)); 43 | assertEquals("POST", server.cors().get().methods().get(1)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sources/keystore/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | smallrye-config-parent 6 | io.smallrye.config 7 | 3.15.1-SNAPSHOT 8 | ../../pom.xml 9 | 10 | 11 | smallrye-config-source-keystore 12 | 13 | SmallRye Config: ConfigSource - KeyStore 14 | 15 | 16 | 17 | io.smallrye.config 18 | smallrye-config 19 | 20 | 21 | 22 | 23 | org.junit.jupiter 24 | junit-jupiter 25 | 26 | 27 | io.smallrye.testing 28 | smallrye-testing-utilities 29 | 30 | 31 | jakarta.annotation 32 | jakarta.annotation-api 33 | test 34 | 35 | 36 | 37 | 38 | 39 | 40 | io.smallrye 41 | jandex-maven-plugin 42 | ${version.org.jboss.jandex} 43 | 44 | 45 | make-index 46 | 47 | jandex 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/ConfigSourceInterceptorFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.util.OptionalInt; 4 | 5 | /** 6 | * This ConfigSourceInterceptorFactory allows to initialize a {@link ConfigSourceInterceptor}, with access to the 7 | * current {@link ConfigSourceInterceptorContext}. 8 | *

9 | * 10 | * Interceptors in the chain are initialized in priority order and the current 11 | * {@link ConfigSourceInterceptorContext} contains the current interceptor, plus all other interceptors already 12 | * initialized. 13 | *

14 | * 15 | * Instances of this interface will be discovered by {@link SmallRyeConfigBuilder#addDiscoveredInterceptors()} via the 16 | * {@link java.util.ServiceLoader} mechanism and can be registered by providing a 17 | * {@code META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory} which contains the fully qualified class 18 | * name of the custom {@link ConfigSourceInterceptor} implementation. 19 | */ 20 | public interface ConfigSourceInterceptorFactory { 21 | /** 22 | * The default priority value, {@link Priorities#APPLICATION}. 23 | */ 24 | int DEFAULT_PRIORITY = Priorities.APPLICATION; 25 | 26 | /** 27 | * Gets the {@link ConfigSourceInterceptor} from the ConfigSourceInterceptorFactory. Implementations of this 28 | * method must provide the instance of the {@link ConfigSourceInterceptor} to add into the Config Interceptor Chain. 29 | * 30 | * @param context the current {@link ConfigSourceInterceptorContext} with the interceptors already initialized. 31 | * @return the {@link ConfigSourceInterceptor} to add to Config Interceptor Chain and initialize. 32 | */ 33 | ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context); 34 | 35 | /** 36 | * Returns the interceptor priority. This is required, because the interceptor priority needs to be sorted 37 | * before doing initialization. 38 | * 39 | * @return the priority value. 40 | */ 41 | default OptionalInt getPriority() { 42 | return OptionalInt.empty(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/WithKeys.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | import java.util.function.Supplier; 9 | 10 | /** 11 | * Provide a list of map keys when populating {@link java.util.Map} types. 12 | *

13 | * When populating a {@link java.util.Map}, {@link SmallRyeConfig} requires the configuration names listed in 14 | * {@link SmallRyeConfig#getPropertyNames()} to be able to find the {@link java.util.Map} keys. The provided list will 15 | * effectively substitute the lookup in {@link SmallRyeConfig#getPropertyNames()}, thus enabling a 16 | * {@link org.eclipse.microprofile.config.spi.ConfigSource} that does not list its properties, to contribute 17 | * configuration to the {@link java.util.Map}. 18 | *

19 | * Each key must exist in the final configuration (relative to the {@link java.util.Map} path segment), or the mapping 20 | * will fail with a {@link ConfigValidationException}. 21 | *

22 | * In the case of {@link java.util.Map} value references a {@link java.util.Collection}, {@link SmallRyeConfig} would 23 | * still require the lookup in {@link SmallRyeConfig#getPropertyNames()}. 24 | */ 25 | @Documented 26 | @Retention(RetentionPolicy.RUNTIME) 27 | @Target({ ElementType.METHOD, ElementType.TYPE_USE }) 28 | public @interface WithKeys { 29 | /** 30 | * A {@link Class} implementing a {@link Supplier} of {@link Iterable} with the {@link java.util.Map} keys to look 31 | * in the configuration. Keys containing a dot are quoted. 32 | *

33 | * The {@link Supplier} is instantiated when mapping the {@link java.util.Map}. It may be instanciated multiple 34 | * times if the {@link Class} is used across multiple {@link WithKeys}. 35 | * 36 | * @return A {@link Class} implementing a {@link Supplier} of {@link Iterable} of {@link String} keys 37 | */ 38 | Class>> value(); 39 | } 40 | -------------------------------------------------------------------------------- /sources/yaml/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | smallrye-config-parent 6 | io.smallrye.config 7 | 3.15.1-SNAPSHOT 8 | ../../pom.xml 9 | 10 | 11 | smallrye-config-source-yaml 12 | 13 | SmallRye Config: ConfigSource - YAML 14 | 15 | 16 | 2.5 17 | 18 | 19 | 20 | 21 | org.yaml 22 | snakeyaml 23 | ${snakeyaml.version} 24 | 25 | 26 | io.smallrye.config 27 | smallrye-config-common 28 | 29 | 30 | io.smallrye.config 31 | smallrye-config 32 | 33 | 34 | io.smallrye.common 35 | smallrye-common-constraint 36 | 37 | 38 | 39 | 40 | org.junit.jupiter 41 | junit-jupiter 42 | 43 | 44 | io.smallrye.testing 45 | smallrye-testing-utilities 46 | 47 | 48 | jakarta.annotation 49 | jakarta.annotation-api 50 | test 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /testsuite/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 4.0.0 21 | 22 | 23 | io.smallrye.config 24 | smallrye-config-parent 25 | 3.15.1-SNAPSHOT 26 | 27 | 28 | smallrye-config-testsuite 29 | pom 30 | 31 | SmallRye Config: Test Suite 32 | 33 | 34 | extra 35 | tck 36 | 37 | 38 | 39 | 40 | 41 | org.apache.maven.plugins 42 | maven-install-plugin 43 | 44 | true 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | io.smallrye.testing 54 | smallrye-testing-bom-tck 55 | ${version.smallrye.testing} 56 | import 57 | pom 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/AbstractMappingConfigSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.io.Serial; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.function.Function; 7 | 8 | public abstract class AbstractMappingConfigSourceInterceptor implements ConfigSourceInterceptor { 9 | @Serial 10 | private static final long serialVersionUID = -3181156290079915301L; 11 | 12 | private final Function mapping; 13 | 14 | public AbstractMappingConfigSourceInterceptor(final Function mapping) { 15 | this.mapping = mapping != null ? mapping : Function.identity(); 16 | } 17 | 18 | public AbstractMappingConfigSourceInterceptor(final Map mappings) { 19 | this(new Function() { 20 | @Override 21 | public String apply(final String name) { 22 | return mappings.getOrDefault(name, name); 23 | } 24 | }); 25 | } 26 | 27 | @Override 28 | public Iterator iterateNames(final ConfigSourceInterceptorContext context) { 29 | return new Iterator<>() { 30 | final Iterator iterator = context.iterateNames(); 31 | String mappedName = null; 32 | 33 | @Override 34 | public boolean hasNext() { 35 | return mappedName != null || iterator.hasNext(); 36 | } 37 | 38 | @Override 39 | public String next() { 40 | if (mappedName != null) { 41 | String mappedName = this.mappedName; 42 | this.mappedName = null; 43 | return mappedName; 44 | } 45 | String name = iterator.next(); 46 | String mappedName = mapping.apply(name); 47 | if (!name.equals(mappedName)) { 48 | this.mappedName = mappedName; 49 | } 50 | return name; 51 | } 52 | }; 53 | } 54 | 55 | protected Function getMapping() { 56 | return mapping; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /utils/crypto/src/main/java/io/smallrye/config/crypto/AESGCMNoPaddingSecretKeysHandler.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.crypto; 2 | 3 | import static java.nio.charset.StandardCharsets.UTF_8; 4 | 5 | import java.nio.ByteBuffer; 6 | import java.security.MessageDigest; 7 | import java.util.Base64; 8 | 9 | import javax.crypto.Cipher; 10 | import javax.crypto.spec.GCMParameterSpec; 11 | import javax.crypto.spec.SecretKeySpec; 12 | 13 | import io.smallrye.config.SecretKeysHandler; 14 | 15 | public class AESGCMNoPaddingSecretKeysHandler implements SecretKeysHandler { 16 | public static final String ENCRYPTION_KEY = "smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key"; 17 | public static final String DECODE_KEY = "smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key-decode"; 18 | 19 | private final SecretKeySpec encryptionKey; 20 | 21 | public AESGCMNoPaddingSecretKeysHandler(final byte[] encryptionKey) { 22 | try { 23 | MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); 24 | sha256.update(encryptionKey); 25 | this.encryptionKey = new SecretKeySpec(sha256.digest(), "AES"); 26 | } catch (Exception e) { 27 | throw new RuntimeException(e); 28 | } 29 | } 30 | 31 | @Override 32 | public String decode(final String secret) { 33 | try { 34 | Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); 35 | ByteBuffer byteBuffer = ByteBuffer.wrap(Base64.getUrlDecoder().decode(secret.getBytes(UTF_8))); 36 | int ivLength = byteBuffer.get(); 37 | byte[] iv = new byte[ivLength]; 38 | byteBuffer.get(iv); 39 | byte[] encrypted = new byte[byteBuffer.remaining()]; 40 | byteBuffer.get(encrypted); 41 | cipher.init(Cipher.DECRYPT_MODE, encryptionKey, new GCMParameterSpec(128, iv)); 42 | return new String(cipher.doFinal(encrypted), UTF_8); 43 | } catch (Exception e) { 44 | throw new RuntimeException(e); 45 | } 46 | } 47 | 48 | @Override 49 | public String getName() { 50 | return "aes-gcm-nopadding"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /examples/mapping/src/test/java/io/smallrye/config/examples/mapping/ServerMappingBeanTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.examples.mapping; 2 | 3 | import static java.util.stream.Collectors.toList; 4 | import static org.junit.jupiter.api.Assertions.*; 5 | 6 | import java.time.Duration; 7 | import java.util.stream.Stream; 8 | 9 | import jakarta.enterprise.context.ApplicationScoped; 10 | import jakarta.inject.Inject; 11 | 12 | import org.jboss.weld.junit5.WeldInitiator; 13 | import org.jboss.weld.junit5.WeldJunit5Extension; 14 | import org.jboss.weld.junit5.WeldSetup; 15 | import org.junit.jupiter.api.Test; 16 | import org.junit.jupiter.api.extension.ExtendWith; 17 | 18 | import io.smallrye.config.inject.ConfigExtension; 19 | 20 | @ExtendWith(WeldJunit5Extension.class) 21 | class ServerMappingBeanTest { 22 | @WeldSetup 23 | WeldInitiator weld = WeldInitiator.from(ConfigExtension.class, ServerMappingBean.class, Server.class) 24 | .addBeans() 25 | .activate(ApplicationScoped.class) 26 | .inject(this) 27 | .build(); 28 | 29 | @Inject 30 | ServerMappingBean bean; 31 | 32 | @Test 33 | void mapping() { 34 | final Server server = bean.getServer(); 35 | assertEquals("localhost", server.host()); 36 | assertEquals(8080, server.port()); 37 | assertEquals(Duration.ofSeconds(60), server.timeout()); 38 | assertEquals(200, server.threads()); 39 | 40 | assertEquals("login.html", server.form().get("login-page")); 41 | assertEquals("error.html", server.form().get("error-page")); 42 | assertEquals("index.html", server.form().get("landing-page")); 43 | 44 | assertTrue(server.ssl().isPresent()); 45 | assertEquals(8443, server.ssl().get().port()); 46 | assertEquals(Stream.of("TLSv1.3", "TLSv1.2").collect(toList()), server.ssl().get().protocols()); 47 | 48 | assertFalse(server.proxy().isPresent()); 49 | 50 | assertFalse(server.log().enabled()); 51 | assertEquals(".log", server.log().suffix()); 52 | assertTrue(server.log().rotate()); 53 | assertEquals(Server.Log.Pattern.COMMON, server.log().pattern()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /testsuite/extra/src/test/java/io/smallrye/config/test/location/DotEnvTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config.test.location; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNull; 5 | 6 | import java.io.FileOutputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.util.Properties; 10 | 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.io.TempDir; 13 | 14 | import io.smallrye.config.DotEnvConfigSourceProvider; 15 | import io.smallrye.config.SmallRyeConfig; 16 | import io.smallrye.config.SmallRyeConfigBuilder; 17 | 18 | public class DotEnvTest { 19 | @Test 20 | void dotEnv(@TempDir Path tempDir) throws Exception { 21 | Properties dotEnv = new Properties(); 22 | dotEnv.setProperty("FOO_BAR", "value"); 23 | try (FileOutputStream out = new FileOutputStream(tempDir.resolve(".env").toFile())) { 24 | dotEnv.store(out, null); 25 | } 26 | 27 | String previousUserDir = System.getProperty("user.dir"); 28 | System.setProperty("user.dir", tempDir.toString()); 29 | 30 | SmallRyeConfig config = new SmallRyeConfigBuilder() 31 | .withSources(new DotEnvConfigSourceProvider()) 32 | .build(); 33 | 34 | assertEquals("value", config.getConfigValue("foo.bar").getValue()); 35 | 36 | System.setProperty("user.dir", previousUserDir); 37 | } 38 | 39 | @Test 40 | void dotEnvFolder(@TempDir Path tempDir) throws Exception { 41 | Path dotEnvFolder = tempDir.resolve(".env"); 42 | Files.createDirectories(dotEnvFolder); 43 | Files.createDirectories(dotEnvFolder.resolve("foo")); 44 | 45 | String previousUserDir = System.getProperty("user.dir"); 46 | System.setProperty("user.dir", tempDir.toString()); 47 | 48 | SmallRyeConfig config = new SmallRyeConfigBuilder() 49 | .withSources(new DotEnvConfigSourceProvider()) 50 | .build(); 51 | 52 | assertNull(config.getConfigValue("foo.bar").getValue()); 53 | 54 | System.setProperty("user.dir", previousUserDir); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /documentation/src/main/docs/config/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration Reference 2 | 3 | | Configuration Property | Type | Default | 4 | |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|-----------| 5 | | `smallrye.config.profile`
The main [Profile](profiles.md) to activate. | String[] | | 6 | | `smallrye.config.profile.parent`
The parent [Profile](profiles.md#parent-profile) to activate. | String | | 7 | | `smallrye.config.locations`
[Additional config locations](../config-sources/locations.md) to be loaded with the Config. The configuration supports multiple locations separated by a comma and each must represent a valid `java.net.URI`. | URI[] | | 8 | | `smallrye.config.mapping.validate-unknown`
[Validates](mappings.md#retrieval) that a `@ConfigMapping` maps every available configuration name contained in the mapping prefix. | boolean | false | 9 | | `smallrye.config.secret-handlers`
The names of the secret handlers to be loaded. A value of `all` loads all available secret handlers and a value of `none` skips the load. | String[] | all | 10 | | `smallrye.config.log.values`
Enable logging of configuration values lookup in DEBUG log level. | boolean | false | 11 | -------------------------------------------------------------------------------- /utils/events/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.config 7 | smallrye-config-parent 8 | 3.15.1-SNAPSHOT 9 | ../../ 10 | 11 | 12 | smallrye-config-events 13 | 14 | SmallRye Config: CDI Events 15 | 16 | 17 | 18 | jakarta.enterprise 19 | jakarta.enterprise.cdi-api 20 | provided 21 | 22 | 23 | jakarta.annotation 24 | jakarta.annotation-api 25 | provided 26 | 27 | 28 | 29 | org.jboss.logging 30 | jboss-logging 31 | 32 | 33 | org.jboss.logging 34 | jboss-logging-annotations 35 | 36 | 37 | org.jboss.logging 38 | jboss-logging-processor 39 | 40 | 41 | 42 | 43 | org.junit.jupiter 44 | junit-jupiter 45 | 46 | 47 | 48 | org.jboss.weld 49 | weld-junit5 50 | 51 | 52 | 53 | io.smallrye.config 54 | smallrye-config 55 | test 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/config/DotEnvConfigSourceProvider.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.config; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.nio.file.Paths; 8 | import java.util.List; 9 | 10 | import org.eclipse.microprofile.config.spi.ConfigSource; 11 | import org.eclipse.microprofile.config.spi.ConfigSourceProvider; 12 | 13 | import io.smallrye.config.common.utils.ConfigSourceUtil; 14 | 15 | public class DotEnvConfigSourceProvider extends AbstractLocationConfigSourceLoader implements ConfigSourceProvider { 16 | private final String location; 17 | 18 | public DotEnvConfigSourceProvider() { 19 | this(getDotEnvFile(".env")); 20 | } 21 | 22 | public DotEnvConfigSourceProvider(final String location) { 23 | this.location = location; 24 | } 25 | 26 | @Override 27 | protected String[] getFileExtensions() { 28 | return new String[] { "" }; 29 | } 30 | 31 | @Override 32 | protected ConfigSource loadConfigSource(final URL url, final int ordinal) throws IOException { 33 | return new EnvConfigSource(ConfigSourceUtil.urlToMap(url), ordinal) { 34 | @Override 35 | public String getName() { 36 | return super.getName() + "[source=" + url + "]"; 37 | } 38 | }; 39 | } 40 | 41 | @Override 42 | public List getConfigSources(final ClassLoader forClassLoader) { 43 | return loadConfigSources(location, 295, forClassLoader); 44 | } 45 | 46 | public static List dotEnvSources(final ClassLoader classLoader) { 47 | return new DotEnvConfigSourceProvider().getConfigSources(classLoader); 48 | } 49 | 50 | public static List dotEnvSources(final String location, final ClassLoader classLoader) { 51 | return new DotEnvConfigSourceProvider(location).getConfigSources(classLoader); 52 | } 53 | 54 | private static String getDotEnvFile(final String filename) { 55 | Path dotEnvFile = Paths.get(System.getProperty("user.dir"), filename); 56 | return Files.isDirectory(dotEnvFile) ? null : dotEnvFile.toUri().toString(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /documentation/src/main/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | - navigation 4 | - toc 5 | --- 6 | 7 | # SmallRye Config 8 | 9 | **SmallRye Config** is a library that provides a way to configure applications, frameworks and containers. It is used 10 | in applications servers like [WildFly](https://wildfly.org/), [Open Liberty](https://openliberty.io) and 11 | [TomEE](https://tomee.apache.org) or frameworks like [Quarkus](https://quarkus.io). It can also be used completely 12 | standalone in any Java application, which makes it a very flexible library. 13 | 14 | It follows the [MicroProfile Config](https://github.com/eclipse/microprofile-config/) specification to provide 15 | the initial config foundations and expands with it own concepts to cover a wide range of use cases observed in the 16 | configuration space. 17 | 18 | ## Use SmallRye Config in a Java application 19 | 20 | Add the _dependency_ to your project using your preferred build tool: 21 | 22 | === "Maven" 23 | 24 | ```xml 25 | 26 | io.smallrye.config 27 | smallrye-config 28 | {{attributes['version']}} 29 | 30 | ``` 31 | 32 | === "Gradle (Groovy)" 33 | 34 | ```groovy 35 | implementation 'io.smallrye.config:smallrye-config:{{attributes['version']}}' 36 | ``` 37 | 38 | === "Gradle (Kotlin)" 39 | 40 | ```kotlin 41 | implementation("io.smallrye.config:smallrye-config:{{attributes['version']}}") 42 | ``` 43 | 44 | === "JBang" 45 | 46 | ```java 47 | //DEPS io.smallrye.config:smallrye-config:{{attributes['version']}} 48 | ``` 49 | 50 | And retrieve a `SmallRyeConfig` instance with: 51 | 52 | ```java 53 | SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); 54 | ``` 55 | 56 | !!! info 57 | 58 | The `SmallRyeConfig` instance will be created and registered to the context class loader if no such configuration 59 | is already created and registered. 60 | 61 | Or build your own: 62 | 63 | ```java 64 | SmallRyeConfig config = new SmallRyeConfigBuilder().build(); 65 | ``` 66 | 67 | !!! info 68 | 69 | `SmallRyeConfig` is the entry point to all the config capabilities provided by SmallRye Config. 70 | --------------------------------------------------------------------------------