diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 83a4d773d4754..c952ca8629700 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -51,7 +51,7 @@ 2.0 3.1.1 2.1.2 - 3.3.4 + 3.4.0 4.0.4 4.0.0 3.5.2 diff --git a/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java b/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java index b51b14c0481d2..d4076b42abab7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java @@ -47,7 +47,6 @@ import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.jboss.logging.Logger; import org.wildfly.common.function.Functions; @@ -136,16 +135,8 @@ public static Consumer loadStepsFrom(ClassLoader classLoader, final BuildTimeConfigurationReader reader = new BuildTimeConfigurationReader(classLoader); final SmallRyeConfig src = reader.initConfiguration(launchMode, buildSystemProps, appModel.getPlatformProperties()); - // install globally QuarkusConfigFactory.setConfig(src); - final ConfigProviderResolver cpr = ConfigProviderResolver.instance(); - try { - cpr.releaseConfig(cpr.getConfig()); - } catch (IllegalStateException ignored) { - // just means no config was installed, which is fine - } - final BuildTimeConfigurationReader.ReadResult readResult = reader.readConfiguration(src); final BooleanSupplierFactoryBuildItem bsf = new BooleanSupplierFactoryBuildItem(readResult, launchMode, devModeType); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/ConfigMappingBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/ConfigMappingBuildItem.java index 78639aaccc718..45274f49eb20a 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/ConfigMappingBuildItem.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/ConfigMappingBuildItem.java @@ -4,6 +4,7 @@ import io.quarkus.builder.item.MultiBuildItem; import io.quarkus.runtime.annotations.StaticInitSafe; +import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix; public final class ConfigMappingBuildItem extends MultiBuildItem { private final Class configClass; @@ -26,6 +27,10 @@ public boolean isStaticInitSafe() { return configClass.isAnnotationPresent(StaticInitSafe.class); } + public ConfigClassWithPrefix toConfigClassWithPrefix() { + return new ConfigClassWithPrefix(configClass, prefix); + } + @Override public boolean equals(final Object o) { if (this == o) { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java index 326fd9c0b924a..24e2225342d3b 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java @@ -470,7 +470,6 @@ final class ReadOperation { final SmallRyeConfig config; final ConfigTrackingInterceptor buildConfigTracker; final Set processedNames = new HashSet<>(); - final Map, Object> objectsByClass = new HashMap<>(); final Map allBuildTimeValues = new TreeMap<>(); final Map buildTimeRunTimeValues = new TreeMap<>(); @@ -510,6 +509,7 @@ ReadResult run() { allBuildTimeValues.putAll(getDefaults(buildTimePatternMap)); buildTimeRunTimeValues.putAll(getDefaults(buildTimeRunTimePatternMap)); + runTimeDefaultValues.putAll(getDefaults(runTimePatternMap)); SmallRyeConfig runtimeDefaultsConfig = getConfigForRuntimeDefaults(); Set registeredRoots = allRoots.stream().map(RootDefinition::getName).collect(toSet()); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java index 65a31c9132ad3..3617c0a0a1b31 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java @@ -1,5 +1,6 @@ package io.quarkus.deployment.configuration; +import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix; import static org.jboss.jandex.AnnotationTarget.Kind.CLASS; import java.util.ArrayList; @@ -32,6 +33,7 @@ import io.smallrye.config.ConfigMappingInterface.Property; import io.smallrye.config.ConfigMappingLoader; import io.smallrye.config.ConfigMappingMetadata; +import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix; public class ConfigMappingUtils { @@ -58,33 +60,42 @@ public static void processConfigClasses( Class configClass = toClass(target.asClass().name()); String prefix = Optional.ofNullable(annotationPrefix).map(AnnotationValue::asString).orElse(""); Kind configClassKind = getConfigClassType(instance); - processConfigClass(configClass, configClassKind, prefix, true, combinedIndex, generatedClasses, reflectiveClasses, - configClasses); + processConfigClass(configClassWithPrefix(configClass, prefix), configClassKind, true, combinedIndex, + generatedClasses, reflectiveClasses, configClasses); } } + public static void processConfigMapping( + CombinedIndexBuildItem combinedIndex, + BuildProducer generatedClasses, + BuildProducer reflectiveClasses, + BuildProducer configClasses) { + processConfigClasses(combinedIndex, generatedClasses, reflectiveClasses, configClasses, CONFIG_MAPPING_NAME); + } + public static void processExtensionConfigMapping( - Class configClass, - String prefix, + ConfigClassWithPrefix configClass, CombinedIndexBuildItem combinedIndex, BuildProducer generatedClasses, BuildProducer reflectiveClasses, BuildProducer configClasses) { - processConfigClass(configClass, Kind.MAPPING, prefix, false, combinedIndex, generatedClasses, reflectiveClasses, + processConfigClass(configClass, Kind.MAPPING, false, combinedIndex, generatedClasses, reflectiveClasses, configClasses); } private static void processConfigClass( - Class configClass, + ConfigClassWithPrefix configClassWithPrefix, Kind configClassKind, - String prefix, boolean isApplicationClass, CombinedIndexBuildItem combinedIndex, BuildProducer generatedClasses, BuildProducer reflectiveClasses, BuildProducer configClasses) { + Class configClass = configClassWithPrefix.getKlass(); + String prefix = configClassWithPrefix.getPrefix(); + List configMappingsMetadata = ConfigMappingLoader.getConfigMappingsMetadata(configClass); Set generatedClassesNames = new HashSet<>(); configMappingsMetadata.forEach(mappingMetadata -> { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java index ea46e31c3a26a..145e95cdd6eb9 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java @@ -6,8 +6,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -26,7 +24,6 @@ import org.eclipse.microprofile.config.spi.ConfigBuilder; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.eclipse.microprofile.config.spi.ConfigSource; -import org.eclipse.microprofile.config.spi.ConfigSourceProvider; import org.eclipse.microprofile.config.spi.Converter; import org.objectweb.asm.Opcodes; import org.wildfly.common.Assert; @@ -61,18 +58,15 @@ import io.quarkus.gizmo.TryBlock; import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.annotations.ConfigPhase; -import io.quarkus.runtime.configuration.AbstractRawDefaultConfigSource; +import io.quarkus.runtime.configuration.AbstractConfigBuilder; import io.quarkus.runtime.configuration.ConfigDiagnostic; -import io.quarkus.runtime.configuration.ConfigSourceFactoryProvider; import io.quarkus.runtime.configuration.ConfigUtils; import io.quarkus.runtime.configuration.ConfigurationException; import io.quarkus.runtime.configuration.HyphenateEnumConverter; import io.quarkus.runtime.configuration.NameIterator; import io.quarkus.runtime.configuration.PropertiesUtil; import io.quarkus.runtime.configuration.QuarkusConfigFactory; -import io.quarkus.runtime.configuration.RuntimeConfigSource; -import io.quarkus.runtime.configuration.RuntimeConfigSourceFactory; -import io.quarkus.runtime.configuration.RuntimeConfigSourceProvider; +import io.quarkus.runtime.configuration.RuntimeOverrideConfigSource; import io.smallrye.config.ConfigMappings; import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix; import io.smallrye.config.Converters; @@ -86,14 +80,13 @@ public final class RunTimeConfigurationGenerator { public static final String CONFIG_CLASS_NAME = "io.quarkus.runtime.generated.Config"; - static final String RTDVCS_CLASS_NAME = "io.quarkus.runtime.generated.RunTimeDefaultValuesConfigSource"; + public static final String CONFIG_STATIC_NAME = "io.quarkus.runtime.generated.StaticInitConfig"; + public static final String CONFIG_RUNTIME_NAME = "io.quarkus.runtime.generated.RunTimeConfig"; public static final MethodDescriptor C_CREATE_RUN_TIME_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "createRunTimeConfig", void.class); public static final MethodDescriptor C_ENSURE_INITIALIZED = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "ensureInitialized", void.class); - static final FieldDescriptor C_RUN_TIME_DEFAULTS_CONFIG_SOURCE = FieldDescriptor.of(CONFIG_CLASS_NAME, - "runTimeDefaultsConfigSource", ConfigSource.class); public static final MethodDescriptor REINIT = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "reinit", void.class); public static final MethodDescriptor C_READ_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "readConfig", void.class); @@ -145,28 +138,6 @@ public final class RunTimeConfigurationGenerator { IntFunction.class); static final MethodDescriptor CU_SORTED_SET_FACTORY = MethodDescriptor.ofMethod(ConfigUtils.class, "sortedSetFactory", IntFunction.class); - static final MethodDescriptor CU_CONFIG_BUILDER = MethodDescriptor.ofMethod(ConfigUtils.class, "configBuilder", - SmallRyeConfigBuilder.class, boolean.class, LaunchMode.class); - static final MethodDescriptor CU_CONFIG_BUILDER_WITH_ADD_DISCOVERED = MethodDescriptor.ofMethod(ConfigUtils.class, - "configBuilder", - SmallRyeConfigBuilder.class, boolean.class, boolean.class, LaunchMode.class); - static final MethodDescriptor CU_CONFIG_BUILDER_LIST = MethodDescriptor.ofMethod(ConfigUtils.class, "configBuilder", - SmallRyeConfigBuilder.class, SmallRyeConfigBuilder.class, List.class); - static final MethodDescriptor CU_ADD_SOURCE_PROVIDER = MethodDescriptor.ofMethod(ConfigUtils.class, "addSourceProvider", - void.class, SmallRyeConfigBuilder.class, ConfigSourceProvider.class); - static final MethodDescriptor CU_ADD_SOURCE_PROVIDERS = MethodDescriptor.ofMethod(ConfigUtils.class, "addSourceProviders", - void.class, SmallRyeConfigBuilder.class, Collection.class); - static final MethodDescriptor CU_ADD_SOURCE_FACTORY_PROVIDER = MethodDescriptor.ofMethod(ConfigUtils.class, - "addSourceFactoryProvider", - void.class, SmallRyeConfigBuilder.class, ConfigSourceFactoryProvider.class); - - static final MethodDescriptor RCS_NEW = MethodDescriptor.ofConstructor(RuntimeConfigSource.class, String.class); - static final MethodDescriptor RCSP_NEW = MethodDescriptor.ofConstructor(RuntimeConfigSourceProvider.class, String.class); - static final MethodDescriptor RCSF_NEW = MethodDescriptor.ofConstructor(RuntimeConfigSourceFactory.class, String.class); - - static final MethodDescriptor AL_NEW = MethodDescriptor.ofConstructor(ArrayList.class); - static final MethodDescriptor AL_ADD = MethodDescriptor.ofMethod(ArrayList.class, "add", boolean.class, Object.class); - static final MethodDescriptor ITRA_ITERATOR = MethodDescriptor.ofMethod(Iterable.class, "iterator", Iterator.class); static final MethodDescriptor ITR_HAS_NEXT = MethodDescriptor.ofMethod(Iterator.class, "hasNext", boolean.class); @@ -209,8 +180,6 @@ public final class RunTimeConfigurationGenerator { static final MethodDescriptor QCF_SET_CONFIG = MethodDescriptor.ofMethod(QuarkusConfigFactory.class, "setConfig", void.class, SmallRyeConfig.class); - static final MethodDescriptor RTDVCS_NEW = MethodDescriptor.ofConstructor(RTDVCS_CLASS_NAME); - static final MethodDescriptor SRC_GET_CONVERTER = MethodDescriptor.ofMethod(SmallRyeConfig.class, "getConverter", Converter.class, Class.class); static final MethodDescriptor SRC_GET_PROPERTY_NAMES = MethodDescriptor.ofMethod(SmallRyeConfig.class, "getPropertyNames", @@ -218,15 +187,17 @@ public final class RunTimeConfigurationGenerator { static final MethodDescriptor SRC_GET_VALUE = MethodDescriptor.ofMethod(SmallRyeConfig.class, "getValue", Object.class, String.class, Converter.class); + static final MethodDescriptor SRCB_NEW = MethodDescriptor.ofConstructor(SmallRyeConfigBuilder.class); + static final MethodDescriptor SRCB_WITH_CONVERTER = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, "withConverter", ConfigBuilder.class, Class.class, int.class, Converter.class); static final MethodDescriptor SRCB_WITH_SOURCES = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, "withSources", ConfigBuilder.class, ConfigSource[].class); + static final MethodDescriptor SRCB_WITH_CUSTOMIZER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withCustomizer", void.class, SmallRyeConfigBuilder.class, String.class); static final MethodDescriptor SRCB_BUILD = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, "build", SmallRyeConfig.class); - static final MethodDescriptor PU_IS_PROPERTY_IN_ROOT = MethodDescriptor.ofMethod(PropertiesUtil.class, - "isPropertyInRoot", boolean.class, Set.class, NameIterator.class); static final MethodDescriptor PU_FILTER_PROPERTIES_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class, "filterPropertiesInRoots", Iterable.class, Iterable.class, Set.class); @@ -272,16 +243,6 @@ public static final class GenerateOperation implements AutoCloseable { final ResultHandle clinitConfig; final Map> convertersToRegister = new HashMap<>(); final List> additionalTypes; - final Set staticConfigSources; - final Set staticConfigSourceProviders; - final Set staticConfigSourceFactories; - final Set staticConfigBuilders; - final Set runtimeConfigSources; - final Set runtimeConfigSourceProviders; - final Set runtimeConfigSourceFactories; - final Set staticConfigMappings; - final Set runtimeConfigMappings; - final Set runtimeConfigBuilders; /** * Regular converters organized by type. Each converter is stored in a separate field. Some are used * only at build time, some only at run time, and some at both times. @@ -312,16 +273,6 @@ public static final class GenerateOperation implements AutoCloseable { classOutput = Assert.checkNotNullParam("classOutput", builder.getClassOutput()); roots = Assert.checkNotNullParam("builder.roots", builder.getBuildTimeReadResult().getAllRoots()); additionalTypes = Assert.checkNotNullParam("additionalTypes", builder.getAdditionalTypes()); - staticConfigSources = builder.getStaticConfigSources(); - staticConfigSourceProviders = builder.getStaticConfigSourceProviders(); - staticConfigSourceFactories = builder.getStaticConfigSourceFactories(); - staticConfigBuilders = builder.getStaticConfigBuilders(); - runtimeConfigSources = builder.getRuntimeConfigSources(); - runtimeConfigSourceProviders = builder.getRuntimeConfigSourceProviders(); - runtimeConfigSourceFactories = builder.getRuntimeConfigSourceFactories(); - staticConfigMappings = builder.getStaticConfigMappings(); - runtimeConfigMappings = builder.getRuntimeConfigMappings(); - runtimeConfigBuilders = builder.getRuntimeConfigBuilders(); cc = ClassCreator.builder().classOutput(classOutput).className(CONFIG_CLASS_NAME).setFinal(true).build(); generateEmptyParsers(); generateUnknownFilter(); @@ -350,40 +301,13 @@ public static final class GenerateOperation implements AutoCloseable { clinitNameBuilder = clinit.newInstance(SB_NEW); - // the run time default values config source - cc.getFieldCreator(C_RUN_TIME_DEFAULTS_CONFIG_SOURCE) - .setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL); - clinit.writeStaticField(C_RUN_TIME_DEFAULTS_CONFIG_SOURCE, clinit.newInstance(RTDVCS_NEW)); - // the build time config, which is for user use only (not used by us other than for loading converters) - final ResultHandle buildTimeBuilder = clinit.invokeStaticMethod(CU_CONFIG_BUILDER_WITH_ADD_DISCOVERED, - clinit.load(true), clinit.load(false), clinit.load(launchMode)); - - // add safe static sources - for (String runtimeConfigSource : staticConfigSources) { - clinit.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, buildTimeBuilder, - clinit.newInstance(RCS_NEW, clinit.load(runtimeConfigSource))); - } - // add safe static source providers - for (String runtimeConfigSourceProvider : staticConfigSourceProviders) { - clinit.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, buildTimeBuilder, - clinit.newInstance(RCSP_NEW, clinit.load(runtimeConfigSourceProvider))); - } - // add safe static source factories - for (String discoveredConfigSourceFactory : staticConfigSourceFactories) { - clinit.invokeStaticMethod(CU_ADD_SOURCE_FACTORY_PROVIDER, buildTimeBuilder, - clinit.newInstance(RCSF_NEW, clinit.load(discoveredConfigSourceFactory))); - } + ResultHandle buildTimeBuilder = clinit.newInstance(SRCB_NEW); - // additional config builders - ResultHandle configBuilders = clinit.newInstance(AL_NEW); - for (String configBuilder : staticConfigBuilders) { - clinit.invokeVirtualMethod(AL_ADD, configBuilders, clinit.load(configBuilder)); - } - clinit.invokeStaticMethod(CU_CONFIG_BUILDER_LIST, buildTimeBuilder, configBuilders); + // static config builder + clinit.invokeStaticMethod(SRCB_WITH_CUSTOMIZER, buildTimeBuilder, clinit.load(CONFIG_STATIC_NAME)); - clinitConfig = clinit.checkCast(clinit.invokeVirtualMethod(SRCB_BUILD, buildTimeBuilder), - SmallRyeConfig.class); + clinitConfig = clinit.checkCast(clinit.invokeVirtualMethod(SRCB_BUILD, buildTimeBuilder), SmallRyeConfig.class); // block for converter setup converterSetup = clinit.createScope(); @@ -403,29 +327,9 @@ public void run() { installConfiguration(clinitConfig, clinit); if (liveReloadPossible) { // the build time config, which is for user use only (not used by us other than for loading converters) - final ResultHandle buildTimeBuilder = reinit.invokeStaticMethod(CU_CONFIG_BUILDER, reinit.load(true), - reinit.load(launchMode)); - // add safe static sources - for (String runtimeConfigSource : staticConfigSources) { - reinit.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, buildTimeBuilder, - reinit.newInstance(RCS_NEW, reinit.load(runtimeConfigSource))); - } - // add safe static source providers - for (String runtimeConfigSourceProvider : staticConfigSourceProviders) { - reinit.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, buildTimeBuilder, - reinit.newInstance(RCSP_NEW, reinit.load(runtimeConfigSourceProvider))); - } - // add safe static source factories - for (String discoveredConfigSourceFactory : staticConfigSourceFactories) { - reinit.invokeStaticMethod(CU_ADD_SOURCE_FACTORY_PROVIDER, buildTimeBuilder, - reinit.newInstance(RCSF_NEW, reinit.load(discoveredConfigSourceFactory))); - } - // additional config builders - ResultHandle configBuilders = reinit.newInstance(AL_NEW); - for (String configBuilder : staticConfigBuilders) { - reinit.invokeVirtualMethod(AL_ADD, configBuilders, reinit.load(configBuilder)); - } - reinit.invokeStaticMethod(CU_CONFIG_BUILDER_LIST, buildTimeBuilder, configBuilders); + final ResultHandle buildTimeBuilder = reinit.newInstance(SRCB_NEW); + // static config builder + reinit.invokeStaticMethod(SRCB_WITH_CUSTOMIZER, buildTimeBuilder, reinit.load(CONFIG_STATIC_NAME)); ResultHandle clinitConfig = reinit.checkCast(reinit.invokeVirtualMethod(SRCB_BUILD, buildTimeBuilder), SmallRyeConfig.class); @@ -457,16 +361,7 @@ public void run() { new StringBuilder("rtParseKey"), false, Type.RUNTIME); // create the run time config - final ResultHandle runTimeBuilder = readConfig.invokeStaticMethod( - CU_CONFIG_BUILDER_WITH_ADD_DISCOVERED, readConfig.load(true), - readConfig.load(false), - readConfig.load(launchMode)); - - // add in our custom sources - final ResultHandle runtimeConfigSourcesArray = readConfig.newArray(ConfigSource[].class, 1); - // run time config default values - readConfig.writeArrayValue(runtimeConfigSourcesArray, 0, - readConfig.readStaticField(C_RUN_TIME_DEFAULTS_CONFIG_SOURCE)); + final ResultHandle runTimeBuilder = readConfig.newInstance(SRCB_NEW); // add in known converters for (Class additionalType : additionalTypes) { @@ -493,33 +388,16 @@ public void run() { } } - // put sources in the builder - readConfig.invokeVirtualMethod(SRCB_WITH_SOURCES, runTimeBuilder, runtimeConfigSourcesArray); - - // add discovered sources - for (String runtimeConfigSource : runtimeConfigSources) { - readConfig.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, runTimeBuilder, - readConfig.newInstance(RCS_NEW, readConfig.load(runtimeConfigSource))); - } - - // add discovered source providers - for (String runtimeConfigSourceProvider : runtimeConfigSourceProviders) { - readConfig.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, runTimeBuilder, - readConfig.newInstance(RCSP_NEW, readConfig.load(runtimeConfigSourceProvider))); - } - - // add discovered source factories - for (String discoveredConfigSourceFactory : runtimeConfigSourceFactories) { - readConfig.invokeStaticMethod(CU_ADD_SOURCE_FACTORY_PROVIDER, runTimeBuilder, - readConfig.newInstance(RCSF_NEW, readConfig.load(discoveredConfigSourceFactory))); - } + // runtime config builder + readConfig.invokeStaticMethod(SRCB_WITH_CUSTOMIZER, runTimeBuilder, readConfig.load(CONFIG_RUNTIME_NAME)); - // additional config builders - ResultHandle configBuilders = readConfig.newInstance(AL_NEW); - for (String configBuilder : runtimeConfigBuilders) { - readConfig.invokeVirtualMethod(AL_ADD, configBuilders, readConfig.load(configBuilder)); + // add in our custom sources + if (launchMode.isDevOrTest()) { + MethodDescriptor registerRuntimeOverrideConfigSource = MethodDescriptor.ofMethod( + RuntimeOverrideConfigSource.class, "registerRuntimeOverrideConfigSource", void.class, + SmallRyeConfigBuilder.class); + readConfig.invokeStaticMethod(registerRuntimeOverrideConfigSource, runTimeBuilder); } - readConfig.invokeStaticMethod(CU_CONFIG_BUILDER_LIST, runTimeBuilder, configBuilders); final ResultHandle runTimeConfig = readConfig.invokeVirtualMethod(SRCB_BUILD, runTimeBuilder); installConfiguration(runTimeConfig, readConfig); @@ -664,9 +542,6 @@ public void run() { clinit.returnValue(null); clinit.close(); cc.close(); - - // generate run time default values config source class - generateDefaultValuesConfigSourceClass(runTimePatternMap, RTDVCS_CLASS_NAME); } private void configSweepLoop(MethodDescriptor parserBody, MethodCreator method, ResultHandle config, @@ -745,28 +620,6 @@ private void installConfiguration(ResultHandle config, MethodCreator methodCreat } } - private void generateDefaultValuesConfigSourceClass(ConfigPatternMap patternMap, String className) { - try (ClassCreator dvcc = ClassCreator.builder().classOutput(classOutput).className(className) - .superClass(AbstractRawDefaultConfigSource.class).setFinal(true).build()) { - // implements abstract method AbstractRawDefaultConfigSource#getValue(NameIterator) - try (MethodCreator mc = dvcc.getMethodCreator("getValue", String.class, NameIterator.class)) { - final ResultHandle keyIter = mc.getMethodParam(0); - final MethodDescriptor md = generateDefaultValueParse(dvcc, patternMap, - new StringBuilder("getDefaultFor")); - if (md != null) { - // there is at least one default value - final BranchResult if1 = mc.ifNonZero(mc.invokeVirtualMethod(NI_HAS_NEXT, keyIter)); - try (BytecodeCreator true1 = if1.trueBranch()) { - final ResultHandle result = true1.invokeVirtualMethod(md, mc.getThis(), keyIter); - true1.returnValue(result); - } - } - - mc.returnValue(mc.loadNull()); - } - } - } - private MethodDescriptor generateInitGroup(ClassDefinition definition) { final Class clazz = definition.getConfigurationClass(); MethodDescriptor methodDescriptor = groupInitMethods.get(clazz); @@ -1512,13 +1365,13 @@ private void reportUnknown(final MethodCreator mc) { private void generateUnknownFilter() { Set mappedProperties = new HashSet<>(); - for (ConfigClassWithPrefix buildTimeMapping : buildTimeConfigResult.buildTimeMappings) { + for (ConfigClassWithPrefix buildTimeMapping : buildTimeConfigResult.getBuildTimeMappings()) { mappedProperties.addAll(ConfigMappings.getProperties(buildTimeMapping).keySet()); } - for (ConfigClassWithPrefix staticConfigMapping : staticConfigMappings) { + for (ConfigClassWithPrefix staticConfigMapping : buildTimeConfigResult.getBuildTimeRunTimeMappings()) { mappedProperties.addAll(ConfigMappings.getProperties(staticConfigMapping).keySet()); } - for (ConfigClassWithPrefix runtimeConfigMapping : runtimeConfigMappings) { + for (ConfigClassWithPrefix runtimeConfigMapping : buildTimeConfigResult.getRunTimeMappings()) { mappedProperties.addAll(ConfigMappings.getProperties(runtimeConfigMapping).keySet()); } @@ -1572,17 +1425,6 @@ public static final class Builder { private ClassOutput classOutput; private BuildTimeConfigurationReader.ReadResult buildTimeReadResult; private List> additionalTypes; - private Set staticConfigSources; - private Set staticConfigSourceProviders; - private Set staticConfigSourceFactories; - private Set staticConfigBuilders; - private Set runtimeConfigSources; - private Set runtimeConfigSourceProviders; - private Set runtimeConfigSourceFactories; - private Set runtimeConfigBuilders; - - private Set staticConfigMappings; - private Set runtimeConfigMappings; Builder() { } @@ -1628,96 +1470,6 @@ public Builder setLaunchMode(LaunchMode launchMode) { return this; } - Set getStaticConfigSources() { - return staticConfigSources; - } - - public Builder setStaticConfigSources(final Set staticConfigSources) { - this.staticConfigSources = staticConfigSources; - return this; - } - - Set getStaticConfigSourceProviders() { - return staticConfigSourceProviders; - } - - public Builder setStaticConfigSourceProviders(final Set staticConfigSourceProviders) { - this.staticConfigSourceProviders = staticConfigSourceProviders; - return this; - } - - Set getStaticConfigSourceFactories() { - return staticConfigSourceFactories; - } - - public Builder setStaticConfigSourceFactories(final Set staticConfigSourceFactories) { - this.staticConfigSourceFactories = staticConfigSourceFactories; - return this; - } - - Set getStaticConfigBuilders() { - return staticConfigBuilders; - } - - public Builder setStaticConfigBuilders(final Set staticConfigBuilders) { - this.staticConfigBuilders = staticConfigBuilders; - return this; - } - - Set getRuntimeConfigSources() { - return runtimeConfigSources; - } - - public Builder setRuntimeConfigSources(final Set runtimeConfigSources) { - this.runtimeConfigSources = runtimeConfigSources; - return this; - } - - Set getRuntimeConfigSourceProviders() { - return runtimeConfigSourceProviders; - } - - public Builder setRuntimeConfigSourceProviders(final Set runtimeConfigSourceProviders) { - this.runtimeConfigSourceProviders = runtimeConfigSourceProviders; - return this; - } - - Set getRuntimeConfigSourceFactories() { - return runtimeConfigSourceFactories; - } - - public Builder setRuntimeConfigSourceFactories(final Set runtimeConfigSourceFactories) { - this.runtimeConfigSourceFactories = runtimeConfigSourceFactories; - return this; - } - - Set getStaticConfigMappings() { - return staticConfigMappings; - } - - public Builder setStaticConfigMappings(final Set staticConfigMappings) { - this.staticConfigMappings = staticConfigMappings; - return this; - } - - Set getRuntimeConfigMappings() { - return runtimeConfigMappings; - } - - public Builder setRuntimeConfigMappings(final Set runtimeConfigMappings) { - this.runtimeConfigMappings = runtimeConfigMappings; - return this; - } - - Set getRuntimeConfigBuilders() { - return runtimeConfigBuilders; - } - - public Builder setRuntimeConfigBuilders(final Set runtimeConfigBuilders) { - this.runtimeConfigBuilders = runtimeConfigBuilders; - return this; - } - public GenerateOperation build() { return new GenerateOperation(this); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java index 743582f056a7d..9258f6b7834c3 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java @@ -1,11 +1,11 @@ package io.quarkus.deployment.steps; -import static io.quarkus.deployment.configuration.ConfigMappingUtils.CONFIG_MAPPING_NAME; -import static io.quarkus.deployment.configuration.ConfigMappingUtils.processConfigClasses; +import static io.quarkus.deployment.configuration.ConfigMappingUtils.processConfigMapping; import static io.quarkus.deployment.configuration.ConfigMappingUtils.processExtensionConfigMapping; +import static io.quarkus.deployment.configuration.RunTimeConfigurationGenerator.CONFIG_RUNTIME_NAME; +import static io.quarkus.deployment.configuration.RunTimeConfigurationGenerator.CONFIG_STATIC_NAME; import static io.quarkus.deployment.steps.ConfigBuildSteps.SERVICES_PREFIX; import static io.quarkus.deployment.util.ServiceUtil.classNamesNamedIn; -import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix; import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; @@ -32,8 +32,10 @@ import org.eclipse.microprofile.config.ConfigValue; import org.eclipse.microprofile.config.spi.ConfigSource; import org.eclipse.microprofile.config.spi.ConfigSourceProvider; +import org.eclipse.microprofile.config.spi.Converter; import org.objectweb.asm.Opcodes; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.GeneratedClassGizmoAdaptor; import io.quarkus.deployment.IsNormal; import io.quarkus.deployment.annotations.BuildProducer; @@ -71,18 +73,25 @@ import io.quarkus.gizmo.ResultHandle; import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.annotations.StaticInitSafe; +import io.quarkus.runtime.configuration.AbstractConfigBuilder; import io.quarkus.runtime.configuration.ConfigBuilder; import io.quarkus.runtime.configuration.ConfigDiagnostic; import io.quarkus.runtime.configuration.ConfigRecorder; -import io.quarkus.runtime.configuration.DefaultsConfigSource; import io.quarkus.runtime.configuration.DisableableConfigSource; -import io.quarkus.runtime.configuration.MappingsConfigBuilder; import io.quarkus.runtime.configuration.QuarkusConfigValue; +import io.quarkus.runtime.configuration.RuntimeConfigBuilder; import io.quarkus.runtime.configuration.RuntimeOverrideConfigSource; +import io.quarkus.runtime.configuration.StaticInitConfigBuilder; import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix; import io.smallrye.config.ConfigSourceFactory; +import io.smallrye.config.ConfigSourceInterceptor; +import io.smallrye.config.ConfigSourceInterceptorFactory; +import io.smallrye.config.DefaultValuesConfigSource; +import io.smallrye.config.SecretKeysHandler; +import io.smallrye.config.SecretKeysHandlerFactory; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; public class ConfigGenerationBuildStep { private static final MethodDescriptor CONFIG_BUILDER = MethodDescriptor.ofMethod( @@ -100,11 +109,7 @@ void buildTimeRunTimeConfig( BuildProducer staticInitConfigBuilder, BuildProducer runTimeConfigBuilder) { - String className = "io.quarkus.runtime.generated.BuildTimeRunTimeFixedConfigSource"; - generateDefaultsConfigSource(generatedClass, reflectiveClass, configItem.getReadResult().getBuildTimeRunTimeValues(), - className, "BuildTime RunTime Fixed", Integer.MAX_VALUE); - - String builderClassName = className + "Builder"; + String builderClassName = "io.quarkus.runtime.generated.BuildTimeRunTimeFixedConfigSourceBuilder"; try (ClassCreator classCreator = ClassCreator.builder() .classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true)) .className(builderClassName) @@ -117,10 +122,20 @@ void buildTimeRunTimeConfig( MethodCreator clinit = classCreator.getMethodCreator("", void.class); clinit.setModifiers(Opcodes.ACC_STATIC); - ResultHandle buildTimeRunTimeConfigSource = clinit.newInstance(MethodDescriptor.ofConstructor(className)); + + ResultHandle map = clinit.newInstance(MethodDescriptor.ofConstructor(HashMap.class)); + MethodDescriptor put = MethodDescriptor.ofMethod(Map.class, "put", Object.class, Object.class, Object.class); + for (Map.Entry entry : configItem.getReadResult().getBuildTimeRunTimeValues().entrySet()) { + clinit.invokeInterfaceMethod(put, map, clinit.load(entry.getKey()), clinit.load(entry.getValue())); + } + + ResultHandle defaultValuesSource = clinit.newInstance( + MethodDescriptor.ofConstructor(DefaultValuesConfigSource.class, Map.class, String.class, int.class), map, + clinit.load("BuildTime RunTime Fixed"), clinit.load(Integer.MAX_VALUE)); + ResultHandle disableableConfigSource = clinit.newInstance( MethodDescriptor.ofConstructor(DisableableConfigSource.class, ConfigSource.class), - buildTimeRunTimeConfigSource); + defaultValuesSource); clinit.writeStaticField(source, disableableConfigSource); clinit.returnVoid(); @@ -135,120 +150,103 @@ void buildTimeRunTimeConfig( method.returnValue(configBuilder); } - reflectiveClass.produce( - ReflectiveClassBuildItem.builder(builderClassName).build()); + reflectiveClass.produce(ReflectiveClassBuildItem.builder(builderClassName).build()); staticInitConfigBuilder.produce(new StaticInitConfigBuilderBuildItem(builderClassName)); runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(builderClassName)); } @BuildStep - void runtimeDefaultsConfig( + void generateMappings( ConfigurationBuildItem configItem, - List runTimeDefaults, - BuildProducer generatedClass, - BuildProducer reflectiveClass, - BuildProducer staticInitConfigBuilder, - BuildProducer runTimeConfigBuilder) { - - Map defaults = new HashMap<>(); - for (RunTimeConfigurationDefaultBuildItem e : runTimeDefaults) { - defaults.put(e.getKey(), e.getValue()); - } - defaults.putAll(configItem.getReadResult().getRunTimeDefaultValues()); - - String className = "io.quarkus.runtime.generated.RunTimeDefaultsConfigSource"; - generateDefaultsConfigSource(generatedClass, reflectiveClass, defaults, - className, "RunTime Defaults", Integer.MIN_VALUE + 100); - - String builderClassName = className + "Builder"; - try (ClassCreator classCreator = ClassCreator.builder() - .classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true)) - .className(builderClassName) - .interfaces(ConfigBuilder.class) - .setFinal(true) - .build()) { - - FieldDescriptor source = FieldDescriptor.of(classCreator.getClassName(), "source", ConfigSource.class); - classCreator.getFieldCreator(source).setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL); - - MethodCreator clinit = classCreator.getMethodCreator("", void.class); - clinit.setModifiers(Opcodes.ACC_STATIC); - ResultHandle runtimeDefaultsConfigSource = clinit.newInstance(MethodDescriptor.ofConstructor(className)); - clinit.writeStaticField(source, runtimeDefaultsConfigSource); - clinit.returnVoid(); - - MethodCreator method = classCreator.getMethodCreator(CONFIG_BUILDER); - ResultHandle configBuilder = method.getMethodParam(0); - - ResultHandle configSources = method.newArray(ConfigSource.class, 1); - method.writeArrayValue(configSources, 0, method.readStaticField(source)); - - method.invokeVirtualMethod(WITH_SOURCES, configBuilder, configSources); - - method.returnValue(configBuilder); - } - - reflectiveClass.produce( - ReflectiveClassBuildItem.builder(builderClassName).build()); - staticInitConfigBuilder.produce(new StaticInitConfigBuilderBuildItem(builderClassName)); - runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(builderClassName)); - } - - @BuildStep - void mappings( CombinedIndexBuildItem combinedIndex, BuildProducer generatedClasses, BuildProducer reflectiveClasses, BuildProducer configClasses) { - processConfigClasses(combinedIndex, generatedClasses, reflectiveClasses, configClasses, CONFIG_MAPPING_NAME); - } - - @BuildStep - void extensionMappings(ConfigurationBuildItem configItem, - CombinedIndexBuildItem combinedIndex, - BuildProducer generatedClasses, - BuildProducer reflectiveClasses, - BuildProducer configClasses) { + processConfigMapping(combinedIndex, generatedClasses, reflectiveClasses, configClasses); List buildTimeRunTimeMappings = configItem.getReadResult().getBuildTimeRunTimeMappings(); for (ConfigClassWithPrefix buildTimeRunTimeMapping : buildTimeRunTimeMappings) { - processExtensionConfigMapping(buildTimeRunTimeMapping.getKlass(), buildTimeRunTimeMapping.getPrefix(), - combinedIndex, generatedClasses, reflectiveClasses, configClasses); + processExtensionConfigMapping(buildTimeRunTimeMapping, combinedIndex, generatedClasses, reflectiveClasses, + configClasses); } - final List runTimeMappings = configItem.getReadResult().getRunTimeMappings(); + List runTimeMappings = configItem.getReadResult().getRunTimeMappings(); for (ConfigClassWithPrefix runTimeMapping : runTimeMappings) { - processExtensionConfigMapping(runTimeMapping.getKlass(), runTimeMapping.getPrefix(), combinedIndex, - generatedClasses, reflectiveClasses, configClasses); + processExtensionConfigMapping(runTimeMapping, combinedIndex, generatedClasses, reflectiveClasses, configClasses); } } @BuildStep - void builderMappings( + void generateBuilders( ConfigurationBuildItem configItem, List configMappings, + List runTimeDefaults, + List staticInitConfigBuilders, + List runTimeConfigBuilders, BuildProducer generatedClass, - BuildProducer reflectiveClass, - BuildProducer staticInitConfigBuilder, - BuildProducer runTimeConfigBuilder) { + BuildProducer reflectiveClass) throws Exception { + + // Default Values collected from mappings / roots and build item + Map defaultValues = new HashMap<>(configItem.getReadResult().getRunTimeDefaultValues()); + for (RunTimeConfigurationDefaultBuildItem e : runTimeDefaults) { + defaultValues.put(e.getKey(), e.getValue()); + } + + Set converters = discoverService(Converter.class, reflectiveClass); + Set interceptors = discoverService(ConfigSourceInterceptor.class, reflectiveClass); + Set interceptorFactories = discoverService(ConfigSourceInterceptorFactory.class, reflectiveClass); + Set configSources = discoverService(ConfigSource.class, reflectiveClass); + Set configSourceProviders = discoverService(ConfigSourceProvider.class, reflectiveClass); + Set configSourceFactories = discoverService(ConfigSourceFactory.class, reflectiveClass); + Set secretKeyHandlers = discoverService(SecretKeysHandler.class, reflectiveClass); + Set secretKeyHandlerFactories = discoverService(SecretKeysHandlerFactory.class, reflectiveClass); + Set configCustomizers = discoverService(SmallRyeConfigBuilderCustomizer.class, reflectiveClass); // For Static Init Config Set staticMappings = new HashSet<>(); staticMappings.addAll(staticSafeConfigMappings(configMappings)); staticMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings()); - String staticInitMappingsConfigBuilder = "io.quarkus.runtime.generated.StaticInitMappingsConfigBuilder"; - generateMappingsConfigBuilder(generatedClass, reflectiveClass, staticInitMappingsConfigBuilder, staticMappings); - staticInitConfigBuilder.produce(new StaticInitConfigBuilderBuildItem(staticInitMappingsConfigBuilder)); + Set staticCustomizers = new HashSet<>(staticSafeServices(configCustomizers)); + staticCustomizers.add(StaticInitConfigBuilder.class.getName()); + + generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_STATIC_NAME, + defaultValues, + converters, + interceptors, + staticSafeServices(interceptorFactories), + staticSafeServices(configSources), + staticSafeServices(configSourceProviders), + staticSafeServices(configSourceFactories), + secretKeyHandlers, + staticSafeServices(secretKeyHandlerFactories), + staticMappings, + staticCustomizers, + staticInitConfigBuilders.stream().map(StaticInitConfigBuilderBuildItem::getBuilderClassName).collect(toSet())); + reflectiveClass.produce(ReflectiveClassBuildItem.builder(CONFIG_STATIC_NAME).build()); // For RunTime Config Set runTimeMappings = new HashSet<>(); runTimeMappings.addAll(runtimeConfigMappings(configMappings)); runTimeMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings()); runTimeMappings.addAll(configItem.getReadResult().getRunTimeMappings()); - String runTimeMappingsConfigBuilder = "io.quarkus.runtime.generated.RunTimeMappingsConfigBuilder"; - generateMappingsConfigBuilder(generatedClass, reflectiveClass, runTimeMappingsConfigBuilder, runTimeMappings); - runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(runTimeMappingsConfigBuilder)); + Set runtimeCustomizers = new HashSet<>(configCustomizers); + runtimeCustomizers.add(RuntimeConfigBuilder.class.getName()); + + generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_RUNTIME_NAME, + defaultValues, + converters, + interceptors, + interceptorFactories, + configSources, + configSourceProviders, + configSourceFactories, + secretKeyHandlers, + secretKeyHandlerFactories, + runTimeMappings, + runtimeCustomizers, + runTimeConfigBuilders.stream().map(RunTimeConfigBuilderBuildItem::getBuilderClassName).collect(toSet())); + reflectiveClass.produce(ReflectiveClassBuildItem.builder(CONFIG_RUNTIME_NAME).build()); } /** @@ -260,43 +258,16 @@ void generateConfigClass( List typeItems, LaunchModeBuildItem launchModeBuildItem, BuildProducer generatedClass, - BuildProducer reflectiveClass, - LiveReloadBuildItem liveReloadBuildItem, - List configMappings, - List staticInitConfigBuilders, - List runTimeConfigBuilders) - throws IOException { + LiveReloadBuildItem liveReloadBuildItem) { reportUnknownBuildProperties(launchModeBuildItem.getLaunchMode(), configItem.getReadResult().getUnknownBuildProperties()); + // TODO - Test live reload with ConfigSource if (liveReloadBuildItem.isLiveReload()) { return; } - Set discoveredConfigSources = discoverService(ConfigSource.class, reflectiveClass); - Set discoveredConfigSourceProviders = discoverService(ConfigSourceProvider.class, reflectiveClass); - Set discoveredConfigSourceFactories = discoverService(ConfigSourceFactory.class, reflectiveClass); - - Set staticConfigSourceProviders = staticSafeServices(discoveredConfigSourceProviders); - Set staticConfigSourceFactories = staticSafeServices(discoveredConfigSourceFactories); - - // TODO - duplicated now builderMappings. Still required to filter the unknown properties - Set staticMappings = new HashSet<>(); - staticMappings.addAll(staticSafeConfigMappings(configMappings)); - staticMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings()); - - Set runtimeMappings = new HashSet<>(); - runtimeMappings.addAll(runtimeConfigMappings(configMappings)); - runtimeMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings()); - runtimeMappings.addAll(configItem.getReadResult().getRunTimeMappings()); - - Set runtimeConfigBuilderClassNames = runTimeConfigBuilders.stream() - .map(RunTimeConfigBuilderBuildItem::getBuilderClassName).collect(toSet()); - reflectiveClass - .produce(ReflectiveClassBuildItem.builder(runtimeConfigBuilderClassNames.toArray(new String[0])) - .build()); - RunTimeConfigurationGenerator.GenerateOperation .builder() .setBuildTimeReadResult(configItem.getReadResult()) @@ -305,17 +276,6 @@ void generateConfigClass( .setLiveReloadPossible(launchModeBuildItem.getLaunchMode() == LaunchMode.DEVELOPMENT || launchModeBuildItem.isAuxiliaryApplication()) .setAdditionalTypes(typeItems.stream().map(ConfigurationTypeBuildItem::getValueType).collect(toList())) - .setStaticConfigSources(staticSafeServices(discoveredConfigSources)) - .setStaticConfigSourceProviders(staticConfigSourceProviders) - .setStaticConfigSourceFactories(staticConfigSourceFactories) - .setStaticConfigMappings(staticMappings) - .setStaticConfigBuilders(staticInitConfigBuilders.stream() - .map(StaticInitConfigBuilderBuildItem::getBuilderClassName).collect(toSet())) - .setRuntimeConfigSources(discoveredConfigSources) - .setRuntimeConfigSourceProviders(discoveredConfigSourceProviders) - .setRuntimeConfigSourceFactories(discoveredConfigSourceFactories) - .setRuntimeConfigMappings(runtimeMappings) - .setRuntimeConfigBuilders(runtimeConfigBuilderClassNames) .build() .run(); } @@ -490,73 +450,150 @@ private static String getPathWithoutExtension(Path path) { return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex); } - private static void generateDefaultsConfigSource( + private static final MethodDescriptor BUILDER_CUSTOMIZER = MethodDescriptor.ofMethod(SmallRyeConfigBuilderCustomizer.class, + "configBuilder", + void.class, SmallRyeConfigBuilder.class); + + private static final MethodDescriptor WITH_DEFAULT = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withDefaultValue", + void.class, SmallRyeConfigBuilder.class, String.class, String.class); + private static final MethodDescriptor WITH_CONVERTER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withConverter", void.class, SmallRyeConfigBuilder.class, Converter.class); + private static final MethodDescriptor WITH_INTERCEPTOR = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withInterceptor", + void.class, SmallRyeConfigBuilder.class, ConfigSourceInterceptor.class); + private static final MethodDescriptor WITH_INTERCEPTOR_FACTORY = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withInterceptorFactory", + void.class, SmallRyeConfigBuilder.class, ConfigSourceInterceptorFactory.class); + private static final MethodDescriptor WITH_SOURCE = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withSource", + void.class, SmallRyeConfigBuilder.class, ConfigSource.class); + private static final MethodDescriptor WITH_SOURCE_PROVIDER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withSource", + void.class, SmallRyeConfigBuilder.class, ConfigSourceProvider.class); + private static final MethodDescriptor WITH_SOURCE_FACTORY = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withSource", + void.class, SmallRyeConfigBuilder.class, ConfigSourceFactory.class); + private static final MethodDescriptor WITH_SECRET_HANDLER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withSecretKeyHandler", void.class, SmallRyeConfigBuilder.class, SecretKeysHandler.class); + private static final MethodDescriptor WITH_SECRET_HANDLER_FACTORY = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withSecretKeyHandler", void.class, SmallRyeConfigBuilder.class, SecretKeysHandlerFactory.class); + private static final MethodDescriptor WITH_MAPPING = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withMapping", + void.class, SmallRyeConfigBuilder.class, String.class, String.class); + private static final MethodDescriptor WITH_CUSTOMIZER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withCustomizer", + void.class, SmallRyeConfigBuilder.class, SmallRyeConfigBuilderCustomizer.class); + private static final MethodDescriptor WITH_BUILDER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, + "withBuilder", + void.class, SmallRyeConfigBuilder.class, ConfigBuilder.class); + + private static void generateConfigBuilder( BuildProducer generatedClass, BuildProducer reflectiveClass, - Map defaults, String className, - String sourceName, - int sourceOrdinal) { - + Map defaultValues, + Set converters, + Set interceptors, + Set interceptorFactories, + Set configSources, + Set configSourceProviders, + Set configSourceFactories, + Set secretKeyHandlers, + Set secretKeyHandlerFactories, + Set mappings, + Set configCustomizers, + Set configBuilders) { + + // First generate a customizer with all components to ensure order try (ClassCreator classCreator = ClassCreator.builder() .classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true)) - .className(className) - .superClass(DefaultsConfigSource.class) + .className(className + "Customizer") + .superClass(AbstractConfigBuilder.class) + .interfaces(SmallRyeConfigBuilderCustomizer.class) .setFinal(true) .build()) { - FieldDescriptor properties = FieldDescriptor.of(classCreator.getClassName(), "properties", Map.class); - classCreator.getFieldCreator(properties).setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL); + MethodCreator method = classCreator.getMethodCreator(BUILDER_CUSTOMIZER); + ResultHandle configBuilder = method.getMethodParam(0); - MethodCreator clinit = classCreator.getMethodCreator("", void.class); - clinit.setModifiers(Opcodes.ACC_STATIC); - clinit.writeStaticField(properties, clinit.newInstance(MethodDescriptor.ofConstructor(HashMap.class))); + for (Map.Entry entry : defaultValues.entrySet()) { + method.invokeStaticMethod(WITH_DEFAULT, configBuilder, method.load(entry.getKey()), + method.load(entry.getValue())); + } - ResultHandle map = clinit.readStaticField(properties); - MethodDescriptor put = MethodDescriptor.ofMethod(Map.class, "put", Object.class, Object.class, Object.class); - for (Map.Entry entry : defaults.entrySet()) { - clinit.invokeInterfaceMethod(put, map, clinit.load(entry.getKey()), clinit.load(entry.getValue())); + for (String converter : converters) { + method.invokeStaticMethod(WITH_CONVERTER, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(converter))); } - clinit.returnVoid(); - MethodCreator ctor = classCreator.getMethodCreator("", void.class); - MethodDescriptor superCtor = MethodDescriptor.ofConstructor(DefaultsConfigSource.class, Map.class, String.class, - int.class); - ctor.invokeSpecialMethod(superCtor, ctor.getThis(), ctor.readStaticField(properties), - ctor.load(sourceName), ctor.load(sourceOrdinal)); - ctor.returnVoid(); - } + for (String interceptor : interceptors) { + method.invokeStaticMethod(WITH_INTERCEPTOR, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(interceptor))); + } - reflectiveClass - .produce(ReflectiveClassBuildItem.builder(className).build()); - } + for (String interceptorFactory : interceptorFactories) { + method.invokeStaticMethod(WITH_INTERCEPTOR_FACTORY, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(interceptorFactory))); + } - private static void generateMappingsConfigBuilder( - BuildProducer generatedClass, - BuildProducer reflectiveClass, - String className, - Set mappings) { + for (String configSource : configSources) { + method.invokeStaticMethod(WITH_SOURCE, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(configSource))); + } + + for (String configSourceProvider : configSourceProviders) { + method.invokeStaticMethod(WITH_SOURCE_PROVIDER, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(configSourceProvider))); + } + + for (String configSourceFactory : configSourceFactories) { + method.invokeStaticMethod(WITH_SOURCE_FACTORY, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(configSourceFactory))); + } + + for (String secretKeyHandler : secretKeyHandlers) { + method.invokeStaticMethod(WITH_SECRET_HANDLER, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(secretKeyHandler))); + } + + for (String secretKeyHandlerFactory : secretKeyHandlerFactories) { + method.invokeStaticMethod(WITH_SECRET_HANDLER_FACTORY, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(secretKeyHandlerFactory))); + } + + for (ConfigClassWithPrefix mapping : mappings) { + method.invokeStaticMethod(WITH_MAPPING, configBuilder, method.load(mapping.getKlass().getName()), + method.load(mapping.getPrefix())); + } + + method.returnVoid(); + } + + configCustomizers.add(className + "Customizer"); try (ClassCreator classCreator = ClassCreator.builder() .classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true)) .className(className) - .interfaces(ConfigBuilder.class) - .superClass(MappingsConfigBuilder.class) + .superClass(AbstractConfigBuilder.class) + .interfaces(SmallRyeConfigBuilderCustomizer.class) .setFinal(true) .build()) { - MethodCreator method = classCreator.getMethodCreator(CONFIG_BUILDER); + MethodCreator method = classCreator.getMethodCreator(BUILDER_CUSTOMIZER); ResultHandle configBuilder = method.getMethodParam(0); - MethodDescriptor addMapping = MethodDescriptor.ofMethod(MappingsConfigBuilder.class, "addMapping", void.class, - SmallRyeConfigBuilder.class, String.class, String.class); + for (String configCustomizer : configCustomizers) { + method.invokeStaticMethod(WITH_CUSTOMIZER, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(configCustomizer))); + } - for (ConfigClassWithPrefix mapping : mappings) { - method.invokeStaticMethod(addMapping, configBuilder, method.load(mapping.getKlass().getName()), - method.load(mapping.getPrefix())); + for (String builder : configBuilders) { + method.invokeStaticMethod(WITH_BUILDER, configBuilder, + method.newInstance(MethodDescriptor.ofConstructor(builder))); } - method.returnValue(configBuilder); + method.returnVoid(); } reflectiveClass.produce(ReflectiveClassBuildItem.builder(className).build()); @@ -568,15 +605,16 @@ private static Set discoverService( ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Set services = new HashSet<>(); for (String service : classNamesNamedIn(classLoader, SERVICES_PREFIX + serviceClass.getName())) { - services.add(service); - reflectiveClass - .produce(ReflectiveClassBuildItem.builder(service).build()); + // The discovery includes deployment modules, so we only include services available at runtime + if (QuarkusClassLoader.isClassPresentAtRuntime(service)) { + services.add(service); + reflectiveClass.produce(ReflectiveClassBuildItem.builder(service).build()); + } } return services; } private static Set staticSafeServices(Set services) { - // TODO - Replace with Jandex? The issue is that the sources may not be in the index... ClassLoader classloader = Thread.currentThread().getContextClassLoader(); Set staticSafe = new HashSet<>(); for (String service : services) { @@ -595,13 +633,13 @@ private static Set staticSafeServices(Set services) { private static Set staticSafeConfigMappings(List configMappings) { return configMappings.stream() .filter(ConfigMappingBuildItem::isStaticInitSafe) - .map(configMapping -> configClassWithPrefix(configMapping.getConfigClass(), configMapping.getPrefix())) + .map(ConfigMappingBuildItem::toConfigClassWithPrefix) .collect(toSet()); } private static Set runtimeConfigMappings(List configMappings) { return configMappings.stream() - .map(configMapping -> configClassWithPrefix(configMapping.getConfigClass(), configMapping.getPrefix())) + .map(ConfigMappingBuildItem::toConfigClassWithPrefix) .collect(toSet()); } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/ConfigConfig.java b/core/runtime/src/main/java/io/quarkus/runtime/ConfigConfig.java index 9f73f81cfc768..cfc366e24b565 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/ConfigConfig.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/ConfigConfig.java @@ -7,7 +7,6 @@ import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; import io.smallrye.config.ConfigMapping; -import io.smallrye.config.WithDefault; import io.smallrye.config.WithName; /** @@ -23,7 +22,6 @@ public interface ConfigConfig { /** * Profile that will be active when Quarkus launches. */ - @WithDefault("prod") Optional profile(); /** diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java new file mode 100644 index 0000000000000..84f9336c4ad61 --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java @@ -0,0 +1,98 @@ +package io.quarkus.runtime.configuration; + +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.ConfigSourceProvider; +import org.eclipse.microprofile.config.spi.Converter; + +import io.smallrye.config.ConfigSourceFactory; +import io.smallrye.config.ConfigSourceInterceptor; +import io.smallrye.config.ConfigSourceInterceptorFactory; +import io.smallrye.config.SecretKeysHandler; +import io.smallrye.config.SecretKeysHandlerFactory; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +/** + * Convenience helper to generate the {@link SmallRyeConfigBuilderCustomizer} bytecode, by wrapping methods that + * require varargs or collections as parameters. + */ +public abstract class AbstractConfigBuilder implements SmallRyeConfigBuilderCustomizer { + protected static void withDefaultValue(SmallRyeConfigBuilder builder, String name, String value) { + builder.withDefaultValue(name, value); + } + + // TODO - radcortez - Can be improved by avoiding introspection work in the Converter class. + // Not a big issue, because registering Converters via ServiceLoader is not a common case + protected static void withConverter(SmallRyeConfigBuilder builder, Converter converter) { + builder.withConverters(new Converter[] { converter }); + } + + protected static void withInterceptor(SmallRyeConfigBuilder builder, ConfigSourceInterceptor interceptor) { + builder.withInterceptors(interceptor); + } + + protected static void withInterceptorFactory( + SmallRyeConfigBuilder builder, + ConfigSourceInterceptorFactory interceptorFactory) { + builder.withInterceptorFactories(interceptorFactory); + } + + protected static void withSource(SmallRyeConfigBuilder builder, ConfigSource configSource) { + builder.withSources(configSource); + } + + protected static void withSource(SmallRyeConfigBuilder builder, ConfigSourceProvider configSourceProvider) { + builder.withSources(configSourceProvider); + } + + protected static void withSource(SmallRyeConfigBuilder builder, ConfigSourceFactory configSourceFactory) { + builder.withSources(configSourceFactory); + } + + protected static void withSecretKeyHandler(SmallRyeConfigBuilder builder, SecretKeysHandler secretKeysHandler) { + builder.withSecretKeysHandlers(secretKeysHandler); + } + + protected static void withSecretKeyHandler(SmallRyeConfigBuilder builder, + SecretKeysHandlerFactory secretKeysHandlerFactory) { + builder.withSecretKeyHandlerFactories(secretKeysHandlerFactory); + } + + protected static void withMapping(SmallRyeConfigBuilder builder, String mappingClass, String prefix) { + try { + // To support mappings that are not public + builder.withMapping(builder.getClassLoader().loadClass(mappingClass), prefix); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + protected static void withBuilder(SmallRyeConfigBuilder builder, ConfigBuilder configBuilder) { + builder.withCustomizers(new SmallRyeConfigBuilderCustomizer() { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + configBuilder.configBuilder(builder); + } + + @Override + public int priority() { + return configBuilder.priority(); + } + }); + } + + protected static void withCustomizer(SmallRyeConfigBuilder builder, SmallRyeConfigBuilderCustomizer customizer) { + builder.withCustomizers(customizer); + } + + @SuppressWarnings("unchecked") + public static void withCustomizer(SmallRyeConfigBuilder builder, String customizer) { + try { + Class customizerClass = (Class) builder + .getClassLoader().loadClass(customizer); + customizerClass.getDeclaredConstructor().newInstance().configBuilder(builder); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractRawDefaultConfigSource.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractRawDefaultConfigSource.java deleted file mode 100644 index 5f9c624ef1988..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractRawDefaultConfigSource.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.quarkus.runtime.configuration; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import org.eclipse.microprofile.config.spi.ConfigSource; - -/** - * The base class for the config source that yields the 'raw' default values. - */ -public abstract class AbstractRawDefaultConfigSource implements ConfigSource, Serializable { - private static final long serialVersionUID = 2524612253582530249L; - - public static final String NAME = "default values"; - - protected AbstractRawDefaultConfigSource() { - } - - public Map getProperties() { - return Collections.emptyMap(); - } - - public Set getPropertyNames() { - return Collections.emptySet(); - } - - public String getValue(final String propertyName) { - return getValue(new NameIterator(propertyName)); - } - - protected abstract String getValue(final NameIterator nameIterator); - - public String getName() { - return NAME; - } - - public int getOrdinal() { - return Integer.MIN_VALUE; - } -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigSourceFactoryProvider.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigSourceFactoryProvider.java deleted file mode 100644 index 15090cf88cba0..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigSourceFactoryProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.quarkus.runtime.configuration; - -import io.smallrye.config.ConfigSourceFactory; - -public interface ConfigSourceFactoryProvider { - ConfigSourceFactory getConfigSourceFactory(final ClassLoader forClassLoader); -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java index 8b8c229111102..6b80e16ba3dde 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java @@ -1,42 +1,22 @@ package io.quarkus.runtime.configuration; -import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS; -import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOG_VALUES; -import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_MAPPING_VALIDATE_UNKNOWN; -import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE; -import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE_PARENT; - -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.OptionalInt; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.UUID; -import java.util.function.Function; import java.util.function.IntFunction; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.spi.ConfigSource; -import org.eclipse.microprofile.config.spi.ConfigSourceProvider; import io.quarkus.runtime.LaunchMode; -import io.smallrye.config.ConfigSourceInterceptor; -import io.smallrye.config.ConfigSourceInterceptorContext; -import io.smallrye.config.ConfigSourceInterceptorFactory; import io.smallrye.config.DotEnvConfigSourceProvider; -import io.smallrye.config.FallbackConfigSourceInterceptor; -import io.smallrye.config.NameIterator; -import io.smallrye.config.Priorities; -import io.smallrye.config.RelocateConfigSourceInterceptor; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigBuilder; @@ -81,96 +61,21 @@ public static SmallRyeConfigBuilder configBuilder(final boolean runTime, final b SmallRyeConfigBuilder builder = emptyConfigBuilder(); if (launchMode.isDevOrTest() && runTime) { - builder.withSources(new RuntimeOverrideConfigSource(Thread.currentThread().getContextClassLoader())); + builder.withSources(new RuntimeOverrideConfigSource(builder.getClassLoader())); } if (runTime) { builder.withDefaultValue(UUID_KEY, UUID.randomUUID().toString()); } if (addDiscovered) { - builder.addDiscoveredSources(); + builder.addDiscoveredCustomizers().addDiscoveredSources(); } return builder; } public static SmallRyeConfigBuilder emptyConfigBuilder() { - SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder(); - LaunchMode launchMode = ProfileManager.getLaunchMode(); - builder.withDefaultValue(launchMode.getProfileKey(), launchMode.getDefaultProfile()); - - builder.withInterceptorFactories(new ConfigSourceInterceptorFactory() { - @Override - public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { - return new RelocateConfigSourceInterceptor(Map.of(SMALLRYE_CONFIG_PROFILE, launchMode.getProfileKey())); - } - - @Override - public OptionalInt getPriority() { - return OptionalInt.of(Priorities.LIBRARY + 200 - 10); - } - }); - - builder.withInterceptorFactories(new ConfigSourceInterceptorFactory() { - @Override - public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { - Map relocations = new HashMap<>(); - relocations.put(SMALLRYE_CONFIG_LOCATIONS, "quarkus.config.locations"); - relocations.put(SMALLRYE_CONFIG_PROFILE_PARENT, "quarkus.config.profile.parent"); - relocations.put(SMALLRYE_CONFIG_MAPPING_VALIDATE_UNKNOWN, "quarkus.config.mapping.validate-unknown"); - relocations.put(SMALLRYE_CONFIG_LOG_VALUES, "quarkus.config.log.values"); - - // Also adds relocations to all profiles - return new RelocateConfigSourceInterceptor(new Function() { - @Override - public String apply(final String name) { - String relocate = relocations.get(name); - if (relocate != null) { - return relocate; - } - - if (name.startsWith("%") && name.endsWith(SMALLRYE_CONFIG_LOCATIONS)) { - io.smallrye.config.NameIterator ni = new io.smallrye.config.NameIterator(name); - return ni.getNextSegment() + "." + "quarkus.config.locations"; - } - - if (name.startsWith("%") && name.endsWith(SMALLRYE_CONFIG_PROFILE_PARENT)) { - io.smallrye.config.NameIterator ni = new NameIterator(name); - return ni.getNextSegment() + "." + "quarkus.config.profile.parent"; - } - - return name; - } - }); - } - - @Override - public OptionalInt getPriority() { - // So it executes before the ProfileConfigSourceInterceptor and applies the profile relocation - return OptionalInt.of(Priorities.LIBRARY + 200 - 5); - } - }); - - builder.withInterceptorFactories(new ConfigSourceInterceptorFactory() { - @Override - public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { - Map fallbacks = new HashMap<>(); - fallbacks.put("quarkus.profile", SMALLRYE_CONFIG_PROFILE); - fallbacks.put("quarkus.config.locations", SMALLRYE_CONFIG_LOCATIONS); - fallbacks.put("quarkus.config.profile.parent", SMALLRYE_CONFIG_PROFILE_PARENT); - fallbacks.put("quarkus.config.mapping.validate-unknown", SMALLRYE_CONFIG_MAPPING_VALIDATE_UNKNOWN); - fallbacks.put("quarkus.config.log.values", SMALLRYE_CONFIG_LOG_VALUES); - return new FallbackConfigSourceInterceptor(fallbacks); - } - - @Override - public OptionalInt getPriority() { - return OptionalInt.of(Priorities.LIBRARY + 600 - 5); - } - }); - - // Ignore unmapped quarkus properties, because properties in the same root may be split between build / runtime - builder.withMappingIgnore("quarkus.**"); - - builder.forClassLoader(Thread.currentThread().getContextClassLoader()) + return new SmallRyeConfigBuilder() + .forClassLoader(Thread.currentThread().getContextClassLoader()) + .withCustomizers(new QuarkusConfigBuilderCustomizer()) .addDiscoveredConverters() .addDefaultInterceptors() .addDiscoveredInterceptors() @@ -179,63 +84,6 @@ public OptionalInt getPriority() { .withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem()) .withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath()) .withSources(new DotEnvConfigSourceProvider()); - - return builder; - } - - @SuppressWarnings("unchecked") - public static SmallRyeConfigBuilder configBuilder(SmallRyeConfigBuilder builder, List configBuildersNames) { - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - try { - List configBuilders = new ArrayList<>(); - for (String configBuilderName : configBuildersNames) { - Class configBuilderClass = (Class) contextClassLoader - .loadClass(configBuilderName); - configBuilders.add(configBuilderClass.getDeclaredConstructor().newInstance()); - } - configBuilders.sort(ConfigBuilderComparator.INSTANCE); - - for (ConfigBuilder configBuilder : configBuilders) { - builder = configBuilder.configBuilder(builder); - if (builder == null) { - throw new ConfigurationException(configBuilder.getClass().getName() + " returned a null builder"); - } - } - - } catch (ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException - | IllegalAccessException e) { - throw new ConfigurationException(e); - } - return builder; - } - - /** - * Add a configuration source provider to the builder. - * - * @param builder the builder - * @param provider the provider to add - */ - public static void addSourceProvider(SmallRyeConfigBuilder builder, ConfigSourceProvider provider) { - final Iterable sources = provider.getConfigSources(Thread.currentThread().getContextClassLoader()); - for (ConfigSource source : sources) { - builder.withSources(source); - } - } - - /** - * Add a configuration source providers to the builder. - * - * @param builder the builder - * @param providers the providers to add - */ - public static void addSourceProviders(SmallRyeConfigBuilder builder, Collection providers) { - for (ConfigSourceProvider provider : providers) { - addSourceProvider(builder, provider); - } - } - - public static void addSourceFactoryProvider(SmallRyeConfigBuilder builder, ConfigSourceFactoryProvider provider) { - builder.withSources(provider.getConfigSourceFactory(Thread.currentThread().getContextClassLoader())); } public static List getProfiles() { @@ -304,13 +152,4 @@ public static Optional getFirstOptionalValue(List propertyNames, } return Optional.empty(); } - - private static class ConfigBuilderComparator implements Comparator { - private static final ConfigBuilderComparator INSTANCE = new ConfigBuilderComparator(); - - @Override - public int compare(ConfigBuilder o1, ConfigBuilder o2) { - return Integer.compare(o1.priority(), o2.priority()); - } - } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/DefaultsConfigSource.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/DefaultsConfigSource.java deleted file mode 100644 index 1445e25bf3ad3..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/DefaultsConfigSource.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.quarkus.runtime.configuration; - -import java.util.HashMap; -import java.util.Map; - -import io.quarkus.runtime.annotations.StaticInitSafe; -import io.smallrye.config.KeyMap; -import io.smallrye.config.common.MapBackedConfigSource; - -@StaticInitSafe -public class DefaultsConfigSource extends MapBackedConfigSource { - private final KeyMap wildcards; - - public DefaultsConfigSource(final Map properties, final String name, final int ordinal) { - // Defaults may contain wildcards, but we don't want to expose them in getPropertyNames, so we need to filter - // them - super(name, filterWildcards(properties), ordinal); - this.wildcards = new KeyMap<>(); - for (Map.Entry entry : properties.entrySet()) { - if (entry.getKey().contains("*")) { - this.wildcards.findOrAdd(entry.getKey()).putRootValue(entry.getValue()); - } - } - } - - @Override - public String getValue(final String propertyName) { - String value = super.getValue(propertyName); - return value == null ? wildcards.findRootValue(propertyName) : value; - } - - private static Map filterWildcards(final Map properties) { - Map filtered = new HashMap<>(); - for (Map.Entry entry : properties.entrySet()) { - if (entry.getKey().contains("*")) { - continue; - } - filtered.put(entry.getKey(), entry.getValue()); - } - return filtered; - } -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/MappingsConfigBuilder.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/MappingsConfigBuilder.java deleted file mode 100644 index 24d1b607074be..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/MappingsConfigBuilder.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.quarkus.runtime.configuration; - -import io.smallrye.config.SmallRyeConfigBuilder; - -/** - * To support mappings that are not public - */ -public abstract class MappingsConfigBuilder implements ConfigBuilder { - protected static void addMapping(SmallRyeConfigBuilder builder, String mappingClass, String prefix) { - // TODO - Ideally should use the classloader passed to Config, but the method is not public. Requires a change in SmallRye Config. - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - try { - builder.withMapping(contextClassLoader.loadClass(mappingClass), prefix); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java index 4a87c6b0f191a..c2d6b78f1e275 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java @@ -11,6 +11,10 @@ public class PropertiesUtil { private PropertiesUtil() { } + /** + * @deprecated Use {@link PropertiesUtil#filterPropertiesInRoots(Iterable, Set)} instead. + */ + @Deprecated(forRemoval = true) public static boolean isPropertyInRoot(Set roots, NameIterator propertyName) { for (String root : roots) { // match everything diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigBuilderCustomizer.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigBuilderCustomizer.java new file mode 100644 index 0000000000000..6d9e82852aa30 --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigBuilderCustomizer.java @@ -0,0 +1,104 @@ +package io.quarkus.runtime.configuration; + +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS; +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOG_VALUES; +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_MAPPING_VALIDATE_UNKNOWN; +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE; +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE_PARENT; + +import java.util.HashMap; +import java.util.Map; +import java.util.OptionalInt; +import java.util.function.Function; + +import io.quarkus.runtime.LaunchMode; +import io.smallrye.config.ConfigSourceInterceptor; +import io.smallrye.config.ConfigSourceInterceptorContext; +import io.smallrye.config.ConfigSourceInterceptorFactory; +import io.smallrye.config.FallbackConfigSourceInterceptor; +import io.smallrye.config.NameIterator; +import io.smallrye.config.Priorities; +import io.smallrye.config.RelocateConfigSourceInterceptor; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +public class QuarkusConfigBuilderCustomizer implements SmallRyeConfigBuilderCustomizer { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + LaunchMode launchMode = ProfileManager.getLaunchMode(); + builder.withDefaultValue(launchMode.getProfileKey(), launchMode.getDefaultProfile()); + + builder.withInterceptorFactories(new ConfigSourceInterceptorFactory() { + @Override + public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { + return new RelocateConfigSourceInterceptor(Map.of(SMALLRYE_CONFIG_PROFILE, launchMode.getProfileKey())); + } + + @Override + public OptionalInt getPriority() { + return OptionalInt.of(Priorities.LIBRARY + 200 - 10); + } + }); + + builder.withInterceptorFactories(new ConfigSourceInterceptorFactory() { + @Override + public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { + Map relocations = new HashMap<>(); + relocations.put(SMALLRYE_CONFIG_LOCATIONS, "quarkus.config.locations"); + relocations.put(SMALLRYE_CONFIG_PROFILE_PARENT, "quarkus.config.profile.parent"); + relocations.put(SMALLRYE_CONFIG_MAPPING_VALIDATE_UNKNOWN, "quarkus.config.mapping.validate-unknown"); + relocations.put(SMALLRYE_CONFIG_LOG_VALUES, "quarkus.config.log.values"); + + // Also adds relocations to all profiles + return new RelocateConfigSourceInterceptor(new Function() { + @Override + public String apply(final String name) { + String relocate = relocations.get(name); + if (relocate != null) { + return relocate; + } + + if (name.startsWith("%") && name.endsWith(SMALLRYE_CONFIG_LOCATIONS)) { + io.smallrye.config.NameIterator ni = new io.smallrye.config.NameIterator(name); + return ni.getNextSegment() + "." + "quarkus.config.locations"; + } + + if (name.startsWith("%") && name.endsWith(SMALLRYE_CONFIG_PROFILE_PARENT)) { + io.smallrye.config.NameIterator ni = new NameIterator(name); + return ni.getNextSegment() + "." + "quarkus.config.profile.parent"; + } + + return name; + } + }); + } + + @Override + public OptionalInt getPriority() { + // So it executes before the ProfileConfigSourceInterceptor and applies the profile relocation + return OptionalInt.of(Priorities.LIBRARY + 200 - 5); + } + }); + + builder.withInterceptorFactories(new ConfigSourceInterceptorFactory() { + @Override + public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) { + Map fallbacks = new HashMap<>(); + fallbacks.put("quarkus.profile", SMALLRYE_CONFIG_PROFILE); + fallbacks.put("quarkus.config.locations", SMALLRYE_CONFIG_LOCATIONS); + fallbacks.put("quarkus.config.profile.parent", SMALLRYE_CONFIG_PROFILE_PARENT); + fallbacks.put("quarkus.config.mapping.validate-unknown", SMALLRYE_CONFIG_MAPPING_VALIDATE_UNKNOWN); + fallbacks.put("quarkus.config.log.values", SMALLRYE_CONFIG_LOG_VALUES); + return new FallbackConfigSourceInterceptor(fallbacks); + } + + @Override + public OptionalInt getPriority() { + return OptionalInt.of(Priorities.LIBRARY + 600 - 5); + } + }); + + // Ignore unmapped quarkus properties, because properties in the same root may be split between build / runtime + builder.withMappingIgnore("quarkus.**"); + } +} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java index 9f168ae907e6f..ec8d0ff775fd9 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java @@ -1,7 +1,6 @@ package io.quarkus.runtime.configuration; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; - +import io.quarkus.runtime.LaunchMode; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigFactory; import io.smallrye.config.SmallRyeConfigProviderResolver; @@ -23,18 +22,18 @@ public QuarkusConfigFactory() { public SmallRyeConfig getConfigFor(final SmallRyeConfigProviderResolver configProviderResolver, final ClassLoader classLoader) { if (config == null) { - //TODO: this code path is only hit when start fails in dev mode very early in the process - //the recovery code will fail without this as it cannot read any properties such as - //the HTTP port or logging info - return ConfigUtils.emptyConfigBuilder().addDiscoveredSources().build(); + return ConfigUtils.configBuilder(true, true, LaunchMode.NORMAL).build(); } return config; } public static void setConfig(SmallRyeConfig config) { + SmallRyeConfigProviderResolver configProviderResolver = (SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver + .instance(); + configProviderResolver.releaseConfig(Thread.currentThread().getContextClassLoader()); + QuarkusConfigFactory.config = config; if (QuarkusConfigFactory.config != null) { - ConfigProviderResolver.instance().releaseConfig(QuarkusConfigFactory.config); + configProviderResolver.registerConfig(config, Thread.currentThread().getContextClassLoader()); } - QuarkusConfigFactory.config = config; } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigBuilder.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigBuilder.java new file mode 100644 index 0000000000000..4b37d9b268a3f --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigBuilder.java @@ -0,0 +1,31 @@ +package io.quarkus.runtime.configuration; + +import java.util.UUID; + +import io.smallrye.config.DotEnvConfigSourceProvider; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +/** + * The initial configuration for Runtime. + */ +public class RuntimeConfigBuilder implements SmallRyeConfigBuilderCustomizer { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + new QuarkusConfigBuilderCustomizer().configBuilder(builder); + + builder.withDefaultValue("quarkus.uuid", UUID.randomUUID().toString()); + + builder.forClassLoader(Thread.currentThread().getContextClassLoader()) + .addDefaultInterceptors() + .addDefaultSources() + .withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem()) + .withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath()) + .withSources(new DotEnvConfigSourceProvider()); + } + + @Override + public int priority() { + return Integer.MIN_VALUE; + } +} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSource.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSource.java deleted file mode 100644 index eeb2f1117618f..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSource.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.quarkus.runtime.configuration; - -import java.lang.reflect.InvocationTargetException; -import java.util.Collections; - -import org.eclipse.microprofile.config.spi.ConfigSource; -import org.eclipse.microprofile.config.spi.ConfigSourceProvider; - -public class RuntimeConfigSource implements ConfigSourceProvider { - private final String configSourceClassName; - - public RuntimeConfigSource(final String configSourceClassName) { - this.configSourceClassName = configSourceClassName; - } - - @Override - public Iterable getConfigSources(final ClassLoader forClassLoader) { - try { - Class configSourceClass = (Class) forClassLoader.loadClass(configSourceClassName); - ConfigSource configSource = configSourceClass.getDeclaredConstructor().newInstance(); - return Collections.singleton(configSource); - } catch (ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException - | IllegalAccessException e) { - throw new ConfigurationException(e); - } - } -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSourceFactory.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSourceFactory.java deleted file mode 100644 index 355f22edd5baf..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSourceFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.quarkus.runtime.configuration; - -import java.lang.reflect.InvocationTargetException; - -import io.smallrye.config.ConfigSourceFactory; - -public class RuntimeConfigSourceFactory implements ConfigSourceFactoryProvider { - private final String configSourceFactoryClassName; - - public RuntimeConfigSourceFactory(final String configSourceFactoryClassName) { - this.configSourceFactoryClassName = configSourceFactoryClassName; - } - - @Override - public ConfigSourceFactory getConfigSourceFactory(final ClassLoader forClassLoader) { - try { - Class configSourceFactoryClass = (Class) forClassLoader - .loadClass(configSourceFactoryClassName); - return configSourceFactoryClass.getDeclaredConstructor().newInstance(); - } catch (ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException - | IllegalAccessException e) { - throw new ConfigurationException(e); - } - } -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSourceProvider.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSourceProvider.java deleted file mode 100644 index 54e6e33290dee..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeConfigSourceProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.quarkus.runtime.configuration; - -import java.lang.reflect.InvocationTargetException; - -import org.eclipse.microprofile.config.spi.ConfigSource; -import org.eclipse.microprofile.config.spi.ConfigSourceProvider; - -public class RuntimeConfigSourceProvider implements ConfigSourceProvider { - private final String configSourceProviderClassName; - - public RuntimeConfigSourceProvider(final String configSourceProviderClassName) { - this.configSourceProviderClassName = configSourceProviderClassName; - } - - @Override - public Iterable getConfigSources(final ClassLoader forClassLoader) { - try { - Class configSourceProviderClass = (Class) forClassLoader - .loadClass(configSourceProviderClassName); - ConfigSourceProvider configSourceProvider = configSourceProviderClass.getDeclaredConstructor().newInstance(); - return configSourceProvider.getConfigSources(forClassLoader); - } catch (ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException - | IllegalAccessException e) { - throw new ConfigurationException(e); - } - } -} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeOverrideConfigSource.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeOverrideConfigSource.java index 02bd3d0d17d4d..db6cd6bc3bc5c 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeOverrideConfigSource.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/RuntimeOverrideConfigSource.java @@ -7,6 +7,8 @@ import org.eclipse.microprofile.config.spi.ConfigSource; +import io.smallrye.config.SmallRyeConfigBuilder; + /** * Config source that is used to handle {@code io.quarkus.bootstrap.app.StartupAction#overrideConfig(java.util.Map)} * @@ -62,4 +64,7 @@ public String getName() { return "Config Override Config Source"; } + public static void registerRuntimeOverrideConfigSource(SmallRyeConfigBuilder builder) { + builder.withSources(new RuntimeOverrideConfigSource(builder.getClassLoader())); + } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/StaticInitConfigBuilder.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/StaticInitConfigBuilder.java new file mode 100644 index 0000000000000..d27c3bbb1e2e2 --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/StaticInitConfigBuilder.java @@ -0,0 +1,27 @@ +package io.quarkus.runtime.configuration; + +import io.smallrye.config.DotEnvConfigSourceProvider; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +/** + * The initial configuration for Static Init. + */ +public class StaticInitConfigBuilder implements SmallRyeConfigBuilderCustomizer { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + new QuarkusConfigBuilderCustomizer().configBuilder(builder); + + builder.forClassLoader(Thread.currentThread().getContextClassLoader()) + .addDefaultInterceptors() + .addDefaultSources() + .withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem()) + .withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath()) + .withSources(new DotEnvConfigSourceProvider()); + } + + @Override + public int priority() { + return Integer.MIN_VALUE; + } +} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/init/InitRuntimeConfig.java b/core/runtime/src/main/java/io/quarkus/runtime/init/InitRuntimeConfig.java index c7cfc32998cb9..7e174cc0cfd3c 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/init/InitRuntimeConfig.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/init/InitRuntimeConfig.java @@ -1,18 +1,53 @@ package io.quarkus.runtime.init; -import io.quarkus.runtime.annotations.ConfigItem; +import static io.smallrye.config.Converters.newEmptyValueConverter; + +import org.eclipse.microprofile.config.spi.Converter; + import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.Converters; +import io.smallrye.config.WithConverter; +import io.smallrye.config.WithDefault; -@ConfigRoot(name = ConfigItem.PARENT, phase = ConfigPhase.RUN_TIME) -public class InitRuntimeConfig { +@ConfigMapping(prefix = "quarkus") +@ConfigRoot(phase = ConfigPhase.RUN_TIME) +public interface InitRuntimeConfig { /** * true to quit exit right after the initialization. * The option is not meant be used directly by users. * */ - @ConfigItem - public boolean initAndExit; + @WithDefault("false") + @WithConverter(BooleanConverter.class) + boolean initAndExit(); + + // Because of https://github.com/eclipse/microprofile-config/issues/708 + // TODO - radcortez - Make SR Config built-in converters public to be used directly + class BooleanConverter implements Converter { + static final Converter BOOLEAN_CONVERTER = Converters + .newTrimmingConverter(newEmptyValueConverter(new Converter() { + @Override + public Boolean convert(final String value) throws IllegalArgumentException, NullPointerException { + return Boolean.valueOf( + "TRUE".equalsIgnoreCase(value) + || "1".equalsIgnoreCase(value) + || "YES".equalsIgnoreCase(value) + || "Y".equalsIgnoreCase(value) + || "ON".equalsIgnoreCase(value) + || "JA".equalsIgnoreCase(value) + || "J".equalsIgnoreCase(value) + || "SI".equalsIgnoreCase(value) + || "SIM".equalsIgnoreCase(value) + || "OUI".equalsIgnoreCase(value)); + } + })); + @Override + public Boolean convert(final String value) throws IllegalArgumentException, NullPointerException { + return BOOLEAN_CONVERTER.convert(value); + } + } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/init/InitializationTaskRecorder.java b/core/runtime/src/main/java/io/quarkus/runtime/init/InitializationTaskRecorder.java index ba1e713f4e65b..a17a5ea7482c5 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/init/InitializationTaskRecorder.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/init/InitializationTaskRecorder.java @@ -3,38 +3,26 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import java.util.stream.StreamSupport; - -import org.eclipse.microprofile.config.ConfigProvider; import io.quarkus.runtime.PreventFurtherStepsException; import io.quarkus.runtime.Quarkus; -import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; -import io.smallrye.config.common.utils.StringUtil; /** * A {@link Recorder} that is used to check if the application should exit once all initialization tasks are completed. */ @Recorder public class InitializationTaskRecorder { + private final InitRuntimeConfig initRuntimeConfig; - private static final String QUARKUS_INIT_AND_EXIT = "quarkus.init-and-exit"; - private final RuntimeValue config; - - public InitializationTaskRecorder(RuntimeValue config) { - this.config = config; + public InitializationTaskRecorder(InitRuntimeConfig initRuntimeConfig) { + this.initRuntimeConfig = initRuntimeConfig; } public void exitIfNeeded() { - //The tcks CustomConverTest is broken: It always returns true for boolean values. - //To workaround this issue, we need to check if `init-and-exit` is explicitly defined. - boolean initAndExitConfigured = propertyConfigured(QUARKUS_INIT_AND_EXIT); - if (initAndExitConfigured && config.getValue().initAndExit) { - if (ConfigProvider.getConfig().getValue(QUARKUS_INIT_AND_EXIT, boolean.class)) { - preventFurtherRecorderSteps(5, "Error attempting to gracefully shutdown after initialization", - () -> new PreventFurtherStepsException("Gracefully exiting after initialization.", 0)); - } + if (initRuntimeConfig.initAndExit()) { + preventFurtherRecorderSteps(5, "Error attempting to gracefully shutdown after initialization", + () -> new PreventFurtherStepsException("Gracefully exiting after initialization.", 0)); } } @@ -55,13 +43,4 @@ public void run() { } throw supplier.get(); } - - private static String propertyToEnvVar(String property) { - return StringUtil.replaceNonAlphanumericByUnderscores(property).toUpperCase(); - } - - private static boolean propertyConfigured(String property) { - return StreamSupport.stream(ConfigProvider.getConfig().getPropertyNames().spliterator(), false) - .anyMatch(n -> property.equals(n) || propertyToEnvVar(property).equals(n)); - } } diff --git a/extensions/picocli/deployment/src/test/java/io/quarkus/picocli/deployment/AvailableConfigSourcesTest.java b/extensions/picocli/deployment/src/test/java/io/quarkus/picocli/deployment/AvailableConfigSourcesTest.java index eafb136eb7512..bbf6e13437fd0 100644 --- a/extensions/picocli/deployment/src/test/java/io/quarkus/picocli/deployment/AvailableConfigSourcesTest.java +++ b/extensions/picocli/deployment/src/test/java/io/quarkus/picocli/deployment/AvailableConfigSourcesTest.java @@ -27,7 +27,7 @@ public class AvailableConfigSourcesTest { void sources() { ConfigValue value = config.getConfigValue("my.prop"); assertEquals("1234", value.getValue()); - assertEquals("RunTime Defaults", value.getConfigSourceName()); + assertEquals("DefaultValuesConfigSource", value.getConfigSourceName()); for (final ConfigSource configSource : config.getConfigSources()) { if (configSource.getName().contains("application.properties")) { diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java index 9d6672277432e..06f92ecfa218f 100644 --- a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientOverrideRuntimeConfigTest.java @@ -39,7 +39,7 @@ public class RestClientOverrideRuntimeConfigTest { @Test void overrideConfig() { // Build time property recording - Optional specifiedDefaultValues = config.getConfigSource("RunTime Defaults"); + Optional specifiedDefaultValues = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(specifiedDefaultValues.isPresent()); assertTrue(specifiedDefaultValues.get().getPropertyNames() .contains("io.quarkus.restclient.configuration.EchoClient/mp-rest/url")); diff --git a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientRunTimeConfigSource.java b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientRunTimeConfigSource.java index 6564cb70de796..648022852df66 100644 --- a/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientRunTimeConfigSource.java +++ b/extensions/resteasy-classic/rest-client/deployment/src/test/java/io/quarkus/restclient/configuration/RestClientRunTimeConfigSource.java @@ -41,7 +41,7 @@ public int getOrdinal() { private static boolean isRuntime() { for (ConfigSource configSource : ConfigProvider.getConfig().getConfigSources()) { - if (configSource.getName().equals("RunTime Defaults")) { + if (configSource.getName().equals("DefaultValuesConfigSource")) { return true; } } diff --git a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ConfigBuilderCustomizer.java b/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ConfigBuilderCustomizer.java new file mode 100644 index 0000000000000..243fff08eb312 --- /dev/null +++ b/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ConfigBuilderCustomizer.java @@ -0,0 +1,13 @@ +package io.quarkus.it.smallrye.config; + +import io.quarkus.runtime.annotations.StaticInitSafe; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +@StaticInitSafe +public class ConfigBuilderCustomizer implements SmallRyeConfigBuilderCustomizer { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + builder.withDefaultValue("exception.message", "This is an exception!"); + } +} diff --git a/integration-tests/smallrye-config/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer b/integration-tests/smallrye-config/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer new file mode 100644 index 0000000000000..9f865d958b21f --- /dev/null +++ b/integration-tests/smallrye-config/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer @@ -0,0 +1 @@ +io.quarkus.it.smallrye.config.ConfigBuilderCustomizer diff --git a/integration-tests/smallrye-config/src/main/resources/config.properties b/integration-tests/smallrye-config/src/main/resources/config.properties index a057d5062f54c..fc031ecfd4767 100644 --- a/integration-tests/smallrye-config/src/main/resources/config.properties +++ b/integration-tests/smallrye-config/src/main/resources/config.properties @@ -1,3 +1 @@ config.properties=1234 - -exception.message=This is an exception! diff --git a/integration-tests/smallrye-config/src/main/resources/fallback.properties b/integration-tests/smallrye-config/src/main/resources/fallback.properties index 5403f0593c38c..a7903ceca7189 100644 --- a/integration-tests/smallrye-config/src/main/resources/fallback.properties +++ b/integration-tests/smallrye-config/src/main/resources/fallback.properties @@ -1,3 +1 @@ locations.fallback=1234 - -exception.message=This is an exception! diff --git a/integration-tests/smallrye-config/src/main/resources/test-profile.properties b/integration-tests/smallrye-config/src/main/resources/test-profile.properties index bcaec8b63ed77..ad05d5b34bc4c 100644 --- a/integration-tests/smallrye-config/src/main/resources/test-profile.properties +++ b/integration-tests/smallrye-config/src/main/resources/test-profile.properties @@ -1,3 +1 @@ test.profile.main=main - -exception.message=This is an exception! diff --git a/integration-tests/test-extension/extension/deployment/src/main/java/io/quarkus/extest/deployment/BuildTimeCustomConfigBuilder.java b/integration-tests/test-extension/extension/deployment/src/main/java/io/quarkus/extest/deployment/BuildTimeCustomConfigBuilder.java new file mode 100644 index 0000000000000..c52d2f5010593 --- /dev/null +++ b/integration-tests/test-extension/extension/deployment/src/main/java/io/quarkus/extest/deployment/BuildTimeCustomConfigBuilder.java @@ -0,0 +1,15 @@ +package io.quarkus.extest.deployment; + +import java.util.Map; + +import io.smallrye.config.PropertiesConfigSource; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +public class BuildTimeCustomConfigBuilder implements SmallRyeConfigBuilderCustomizer { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + builder.withSources( + new PropertiesConfigSource(Map.of("prop.recorded.from.btconfigsource", "1234"), "BuildTimeConfigSource", 100)); + } +} diff --git a/integration-tests/test-extension/extension/deployment/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer b/integration-tests/test-extension/extension/deployment/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer new file mode 100644 index 0000000000000..69636f6169932 --- /dev/null +++ b/integration-tests/test-extension/extension/deployment/src/main/resources/META-INF/services/io.smallrye.config.SmallRyeConfigBuilderCustomizer @@ -0,0 +1 @@ +io.quarkus.extest.deployment.BuildTimeCustomConfigBuilder diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/ConfigBuilderTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/ConfigBuilderTest.java index 5254275f7dec6..41ebada063e1c 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/ConfigBuilderTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/ConfigBuilderTest.java @@ -1,6 +1,7 @@ package io.quarkus.config; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import jakarta.inject.Inject; @@ -30,4 +31,10 @@ void staticConfigBuilder() { void runTimeConfigBuilder() { assertEquals("1234", config.getRawValue("additional.builder.property")); } + + @Test + void buildTimeConfigBuilder() { + assertFalse(config.getConfigSource("BuildTimeConfigSource").isPresent()); + assertEquals("1234", config.getRawValue("prop.recorded.from.btconfigsource")); + } } diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/RecordedBuildProfileInRuntimeTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/RecordedBuildProfileInRuntimeTest.java index dd3c6ceb605ef..b985f22b5cde0 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/RecordedBuildProfileInRuntimeTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/config/RecordedBuildProfileInRuntimeTest.java @@ -31,7 +31,7 @@ void recordedBuildProfileInRuntime() { ConfigValue profile = config.getConfigValue("quarkus.test.profile"); assertEquals("test", profile.getValue()); // Recorded by ProfileBuildStep - assertEquals("RunTime Defaults", profile.getConfigSourceName()); + assertEquals("DefaultValuesConfigSource", profile.getConfigSourceName()); Optional defaultValuesConfigSource = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(defaultValuesConfigSource.isPresent()); diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfigMappingTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfigMappingTest.java index 0203c51396b5b..7ceae79dd2046 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfigMappingTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfigMappingTest.java @@ -35,6 +35,6 @@ void mappingBuildTimeRunTime() { @Test void mappingRunTime() { - assertEquals("value", mappingBuildTimeRunTime.value()); + assertEquals("value", mappingRunTime.value()); } } diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java index 962237d464860..269e8cac7c023 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java @@ -333,10 +333,10 @@ public void testBuiltTimeNamedMapWithProfiles() { @Test public void testConfigDefaultValuesSourceOrdinal() { - Optional source = config.getConfigSource("RunTime Defaults"); + Optional source = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(source.isPresent()); ConfigSource defaultValues = source.get(); - assertEquals(Integer.MIN_VALUE + 100, defaultValues.getOrdinal()); + assertEquals(Integer.MIN_VALUE, defaultValues.getOrdinal()); ConfigSource applicationProperties = null; for (ConfigSource configSource : config.getConfigSources()) { @@ -355,7 +355,7 @@ public void testConfigDefaultValuesSourceOrdinal() { @Test public void testProfileDefaultValuesSource() { - Optional source = config.getConfigSource("RunTime Defaults"); + Optional source = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(source.isPresent()); ConfigSource defaultValues = source.get(); @@ -388,7 +388,7 @@ void prefixConfig() { assertEquals("5678", anotherPrefixConfig.prop); assertEquals("5678", anotherPrefixConfig.map.get("prop")); - Optional runTimeDefaults = config.getConfigSource("RunTime Defaults"); + Optional runTimeDefaults = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(runTimeDefaults.isPresent()); // java.version should not be recorded assertFalse(runTimeDefaults.get().getPropertyNames().contains("java.version")); @@ -402,7 +402,7 @@ void shadowBuildTimeToRunTimeConfig() { assertEquals("quarkus.bt.bt-config-value", btConfigValue.getName()); assertEquals("value", btConfigValue.getValue()); - Optional source = config.getConfigSource("RunTime Defaults"); + Optional source = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(source.isPresent()); ConfigSource defaultValues = source.get(); diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java index db522995ff2b9..e208cbf882e0f 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java @@ -29,14 +29,15 @@ public class RuntimeDefaultsTest { @Test void doNotRecordEnvRuntimeDefaults() { - Optional defaultValues = config.getConfigSource("RunTime Defaults"); + Optional defaultValues = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(defaultValues.isPresent()); + assertEquals("rtStringOptValue", defaultValues.get().getValue("quarkus.rt.rt-string-opt")); assertEquals("properties", defaultValues.get().getValue("bt.do.not.record")); } @Test void doNotRecordActiveUnprofiledPropertiesDefaults() { - Optional defaultValues = config.getConfigSource("RunTime Defaults"); + Optional defaultValues = config.getConfigSource("DefaultValuesConfigSource"); assertTrue(defaultValues.isPresent()); assertEquals("properties", config.getRawValue("bt.profile.record")); assertEquals("properties", defaultValues.get().getValue("%test.bt.profile.record")); diff --git a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/StaticInitSourcesTest.java b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/StaticInitSourcesTest.java index 8c72f140e5579..49c72019e089c 100644 --- a/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/StaticInitSourcesTest.java +++ b/integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/StaticInitSourcesTest.java @@ -5,7 +5,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import io.quarkus.extest.runtime.config.StaticInitNotSafeConfigBuilderCustomizer; import io.quarkus.extest.runtime.config.StaticInitNotSafeConfigSource; +import io.quarkus.extest.runtime.config.StaticInitSafeConfigBuilderCustomizer; import io.quarkus.extest.runtime.config.StaticInitSafeConfigSource; import io.quarkus.test.QuarkusUnitTest; @@ -15,9 +17,9 @@ public class StaticInitSourcesTest { .withApplicationRoot((jar) -> jar .addClasses(ConfiguredBean.class) // Don't change this to types, because of classloader class cast exception. - .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource", - StaticInitSafeConfigSource.class.getName(), - StaticInitNotSafeConfigSource.class.getName()) + .addAsServiceProvider("io.smallrye.config.SmallRyeConfigBuilderCustomizer", + StaticInitSafeConfigBuilderCustomizer.class.getName(), + StaticInitNotSafeConfigBuilderCustomizer.class.getName()) .addAsResource("application.properties")); @Test diff --git a/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java b/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java index ebfc255b2d0e2..27d297ac883e4 100644 --- a/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java +++ b/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java @@ -6,8 +6,9 @@ public class EnvBuildTimeConfigSource extends EnvConfigSource { public EnvBuildTimeConfigSource() { - super(new HashMap() { + super(new HashMap<>() { { + put("QUARKUS_RT_RT_STRING_OPT", "changed"); put("BT_DO_NOT_RECORD", "env-source"); } }, Integer.MAX_VALUE); diff --git a/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/StaticInitNotSafeConfigBuilderCustomizer.java b/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/StaticInitNotSafeConfigBuilderCustomizer.java new file mode 100644 index 0000000000000..a66bd73cd9e10 --- /dev/null +++ b/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/StaticInitNotSafeConfigBuilderCustomizer.java @@ -0,0 +1,11 @@ +package io.quarkus.extest.runtime.config; + +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +public class StaticInitNotSafeConfigBuilderCustomizer implements SmallRyeConfigBuilderCustomizer { + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + builder.withSources(new StaticInitNotSafeConfigSource()); + } +} diff --git a/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/StaticInitSafeConfigBuilderCustomizer.java b/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/StaticInitSafeConfigBuilderCustomizer.java new file mode 100644 index 0000000000000..b2ba81d75c74e --- /dev/null +++ b/integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/StaticInitSafeConfigBuilderCustomizer.java @@ -0,0 +1,17 @@ +package io.quarkus.extest.runtime.config; + +import io.quarkus.runtime.annotations.StaticInitSafe; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigBuilderCustomizer; + +@StaticInitSafe +public class StaticInitSafeConfigBuilderCustomizer implements SmallRyeConfigBuilderCustomizer { + public StaticInitSafeConfigBuilderCustomizer() { + System.out.println("StaticInitSafeConfigBuilderCustomizer.StaticInitSafeConfigBuilderCustomizer"); + } + + @Override + public void configBuilder(final SmallRyeConfigBuilder builder) { + builder.withSources(new StaticInitSafeConfigSource()); + } +} diff --git a/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java b/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java index 72b98a7f9764e..9e088371f3fde 100644 --- a/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java +++ b/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java @@ -25,13 +25,14 @@ import java.util.function.Function; import java.util.function.Predicate; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.IndexView; +import io.smallrye.config.SmallRyeConfigProviderResolver; + public class TestResourceManager implements Closeable { public static final String CLOSEABLE_NAME = TestResourceManager.class.getName() + ".closeable"; @@ -179,8 +180,8 @@ public void close() { } } try { - ConfigProviderResolver cpr = ConfigProviderResolver.instance(); - cpr.releaseConfig(cpr.getConfig()); + ((SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver.instance()) + .releaseConfig(Thread.currentThread().getContextClassLoader()); } catch (Throwable ignored) { } configProperties.clear();