From 8e6774282b99027a4574b296d1e2a8c1940e8fba Mon Sep 17 00:00:00 2001 From: "David M. Lloyd" Date: Wed, 17 Jul 2019 11:40:29 -0500 Subject: [PATCH] Move initial configuration setup out of build steps Also fix handling of quarkus.application.* Fixes #3008, groundwork for #3233 --- .../creator/phase/augment/AugmentPhase.java | 5 - .../deployment/ApplicationInfoUtil.java | 37 ----- .../quarkus/deployment/ExtensionLoader.java | 131 ++++++++++++++++++ .../quarkus/deployment/QuarkusAugmentor.java | 17 +-- ...uildTimeConfigurationDefaultBuildItem.java | 47 ------- ...BuildTimeConfigurationSourceBuildItem.java | 43 ------ .../builditem/UnmatchedConfigBuildItem.java | 34 +++++ .../steps/ApplicationInfoBuildStep.java | 54 +------- .../deployment/steps/ConfigurationSetup.java | 118 ++-------------- .../io/quarkus/gradle/tasks/QuarkusBuild.java | 2 + .../io/quarkus/gradle/tasks/QuarkusDev.java | 2 - .../main/java/io/quarkus/maven/BuildMojo.java | 2 + .../main/java/io/quarkus/maven/DevMojo.java | 2 - .../io/quarkus/maven/NativeImageMojo.java | 9 +- 14 files changed, 198 insertions(+), 305 deletions(-) delete mode 100644 core/deployment/src/main/java/io/quarkus/deployment/ApplicationInfoUtil.java delete mode 100644 core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationDefaultBuildItem.java delete mode 100644 core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationSourceBuildItem.java create mode 100644 core/deployment/src/main/java/io/quarkus/deployment/builditem/UnmatchedConfigBuildItem.java diff --git a/core/creator/src/main/java/io/quarkus/creator/phase/augment/AugmentPhase.java b/core/creator/src/main/java/io/quarkus/creator/phase/augment/AugmentPhase.java index abbe22021f566..ebef51df795b6 100644 --- a/core/creator/src/main/java/io/quarkus/creator/phase/augment/AugmentPhase.java +++ b/core/creator/src/main/java/io/quarkus/creator/phase/augment/AugmentPhase.java @@ -51,7 +51,6 @@ import io.quarkus.creator.outcome.OutcomeProviderRegistration; import io.quarkus.creator.phase.curate.CurateOutcome; import io.quarkus.deployment.ApplicationArchive; -import io.quarkus.deployment.ApplicationInfoUtil; import io.quarkus.deployment.ClassOutput; import io.quarkus.deployment.QuarkusAugmentor; import io.quarkus.deployment.QuarkusClassWriter; @@ -72,7 +71,6 @@ public class AugmentPhase implements AppCreationPhase, AugmentOutcome { private static final Logger log = Logger.getLogger(AugmentPhase.class); - private static final String APPLICATION_INFO_PROPERTIES = "application-info.properties"; private static final String META_INF = "META-INF"; private Path outputDir; @@ -219,11 +217,8 @@ public void provideOutcome(AppCreator ctx) throws AppCreatorException { IoUtils.recursiveDelete(metaInf.resolve("maven")); IoUtils.recursiveDelete(metaInf.resolve("INDEX.LIST")); IoUtils.recursiveDelete(metaInf.resolve("MANIFEST.MF")); - IoUtils.recursiveDelete(metaInf.resolve(APPLICATION_INFO_PROPERTIES)); } - ApplicationInfoUtil.writeApplicationInfoProperties(appState.getAppArtifact(), appClassesDir); - //lets default to appClassesDir for now if (configDir == null) configDir = appClassesDir; diff --git a/core/deployment/src/main/java/io/quarkus/deployment/ApplicationInfoUtil.java b/core/deployment/src/main/java/io/quarkus/deployment/ApplicationInfoUtil.java deleted file mode 100644 index 31675942b20aa..0000000000000 --- a/core/deployment/src/main/java/io/quarkus/deployment/ApplicationInfoUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.quarkus.deployment; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Properties; - -import io.quarkus.bootstrap.model.AppArtifact; - -public final class ApplicationInfoUtil { - - public static final String APPLICATION_INFO_PROPERTIES = "application-info.properties"; - public static final String META_INF = "META-INF"; - - public static final String ARTIFACT_ID_KEY = "artifactId"; - public static final String VERSION_KEY = "version"; - - private ApplicationInfoUtil() { - } - - // these properties are used as default values for ApplicationInfoBuildItem - public static void writeApplicationInfoProperties(AppArtifact appArtifact, Path appClassesDir) { - Properties properties = new Properties(); - if (appArtifact != null) { - properties.setProperty("artifactId", appArtifact.getArtifactId()); - properties.setProperty("version", appArtifact.getVersion()); - } - try { - appClassesDir.resolve(META_INF).toFile().mkdirs(); - File file = appClassesDir.resolve(META_INF).resolve(APPLICATION_INFO_PROPERTIES).toFile(); - properties.store(new FileOutputStream(file), "Generated file; do not edit manually"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} 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 48a4c4b589519..73e850378e725 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java @@ -24,8 +24,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Properties; +import java.util.Set; import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -33,6 +37,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import org.jboss.logging.Logger; import org.wildfly.common.function.Functions; import io.quarkus.builder.BuildChainBuilder; @@ -56,14 +61,26 @@ import io.quarkus.deployment.builditem.MainBytecodeRecorderBuildItem; import io.quarkus.deployment.builditem.RunTimeConfigurationBuildItem; import io.quarkus.deployment.builditem.StaticBytecodeRecorderBuildItem; +import io.quarkus.deployment.builditem.UnmatchedConfigBuildItem; +import io.quarkus.deployment.configuration.ConfigDefinition; +import io.quarkus.deployment.configuration.DefaultValuesConfigurationSource; import io.quarkus.deployment.recording.BytecodeRecorderImpl; import io.quarkus.deployment.recording.RecorderContext; import io.quarkus.deployment.util.ReflectUtil; import io.quarkus.deployment.util.ServiceUtil; +import io.quarkus.gizmo.FieldDescriptor; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; import io.quarkus.runtime.annotations.Recorder; import io.quarkus.runtime.annotations.Template; +import io.quarkus.runtime.configuration.ApplicationPropertiesConfigSource; +import io.quarkus.runtime.configuration.ConverterSupport; +import io.quarkus.runtime.configuration.DeploymentProfileConfigSource; +import io.quarkus.runtime.configuration.ExpandingConfigSource; +import io.smallrye.config.PropertiesConfigSource; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; +import io.smallrye.config.SmallRyeConfigProviderResolver; /** * Utility class to load build steps, runtime recorders, and configuration roots from a given extension class. @@ -72,6 +89,20 @@ public final class ExtensionLoader { private ExtensionLoader() { } + private static final Logger cfgLog = Logger.getLogger("io.quarkus.configuration"); + + public static final String BUILD_TIME_CONFIG = "io.quarkus.runtime.generated.BuildTimeConfig"; + public static final String BUILD_TIME_CONFIG_ROOT = "io.quarkus.runtime.generated.BuildTimeConfigRoot"; + public static final String RUN_TIME_CONFIG = "io.quarkus.runtime.generated.RunTimeConfig"; + public static final String RUN_TIME_CONFIG_ROOT = "io.quarkus.runtime.generated.RunTimeConfigRoot"; + + private static final FieldDescriptor RUN_TIME_CONFIG_FIELD = FieldDescriptor.of(RUN_TIME_CONFIG, "runConfig", + RUN_TIME_CONFIG_ROOT); + private static final FieldDescriptor BUILD_TIME_CONFIG_FIELD = FieldDescriptor.of(BUILD_TIME_CONFIG, "buildConfig", + BUILD_TIME_CONFIG_ROOT); + + private static final String CONFIG_ROOTS_LIST = "META-INF/quarkus-config-roots.list"; + private static boolean isRecorder(AnnotatedElement element) { return element.isAnnotationPresent(Recorder.class) || element.isAnnotationPresent(Template.class); } @@ -86,7 +117,107 @@ private static boolean isRecorder(AnnotatedElement element) { */ public static Consumer loadStepsFrom(ClassLoader classLoader) throws IOException, ClassNotFoundException { + return loadStepsFrom(classLoader, new Properties()); + } + + /** + * Load all the build steps from the given class loader. + * + * @param classLoader the class loader + * @return a consumer which adds the steps to the given chain builder + * @throws IOException if the class loader could not load a resource + * @throws ClassNotFoundException if a build step class is not found + */ + public static Consumer loadStepsFrom(ClassLoader classLoader, Map buildSystemProps) + throws IOException, ClassNotFoundException { + final Properties props = new Properties(); + props.putAll(buildSystemProps); + return loadStepsFrom(classLoader, props); + } + + /** + * Load all the build steps from the given class loader. + * + * @param classLoader the class loader + * @param buildSystemProps the build system properties to use + * @return a consumer which adds the steps to the given chain builder + * @throws IOException if the class loader could not load a resource + * @throws ClassNotFoundException if a build step class is not found + */ + public static Consumer loadStepsFrom(ClassLoader classLoader, Properties buildSystemProps) + throws IOException, ClassNotFoundException { + + // set up the configuration definitions + final ConfigDefinition buildTimeConfig = new ConfigDefinition(FieldDescriptor.of("Bogus", "No field", "Nothing")); + final ConfigDefinition buildTimeRunTimeConfig = new ConfigDefinition(BUILD_TIME_CONFIG_FIELD); + final ConfigDefinition runTimeConfig = new ConfigDefinition(RUN_TIME_CONFIG_FIELD, true); + + // populate it with all known types + for (Class clazz : ServiceUtil.classesNamedIn(classLoader, CONFIG_ROOTS_LIST)) { + final ConfigRoot annotation = clazz.getAnnotation(ConfigRoot.class); + if (annotation == null) { + cfgLog.warnf("Ignoring configuration root %s because it has no annotation", clazz); + } else { + final ConfigPhase phase = annotation.phase(); + if (phase == ConfigPhase.RUN_TIME) { + runTimeConfig.registerConfigRoot(clazz); + } else if (phase == ConfigPhase.BUILD_AND_RUN_TIME_FIXED) { + buildTimeRunTimeConfig.registerConfigRoot(clazz); + } else if (phase == ConfigPhase.BUILD_TIME) { + buildTimeConfig.registerConfigRoot(clazz); + } else { + cfgLog.warnf("Unrecognized configuration phase \"%s\" on %s", phase, clazz); + } + } + } + + // now prepare & load the build configuration + final SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder(); + + // expand properties + final ExpandingConfigSource.Cache cache = new ExpandingConfigSource.Cache(); + builder.withWrapper(ExpandingConfigSource.wrapper(cache)); + builder.withWrapper(DeploymentProfileConfigSource.wrapper()); + builder.addDefaultSources(); + final ApplicationPropertiesConfigSource.InJar inJar = new ApplicationPropertiesConfigSource.InJar(); + final DefaultValuesConfigurationSource defaultSource = new DefaultValuesConfigurationSource( + buildTimeConfig.getLeafPatterns()); + final PropertiesConfigSource pcs = new PropertiesConfigSource(buildSystemProps, "Build system"); + + builder.withSources(inJar, defaultSource, pcs); + + // populate builder with all converters loaded from ServiceLoader + ConverterSupport.populateConverters(builder); + + final SmallRyeConfig src = (SmallRyeConfig) builder + .addDefaultSources() + .addDiscoveredSources() + .addDiscoveredConverters() + .build(); + + SmallRyeConfigProviderResolver.instance().registerConfig(src, classLoader); + + Set unmatched = new HashSet<>(); + + ConfigDefinition.loadConfiguration(cache, src, + unmatched, + buildTimeConfig, + buildTimeRunTimeConfig, // this one is only for generating a default-values config source + runTimeConfig); + + unmatched.removeIf(s -> !inJar.getPropertyNames().contains(s) && !s.startsWith("quarkus.")); + Consumer result = Functions.discardingConsumer(); + result = result.andThen(bcb -> bcb.addBuildStep(bc -> { + bc.produce(new BuildTimeConfigurationBuildItem(buildTimeConfig)); + bc.produce(new BuildTimeRunTimeFixedConfigurationBuildItem(buildTimeRunTimeConfig)); + bc.produce(new RunTimeConfigurationBuildItem(runTimeConfig)); + bc.produce(new UnmatchedConfigBuildItem(Collections.unmodifiableSet(unmatched))); + }).produces(BuildTimeConfigurationBuildItem.class) + .produces(BuildTimeRunTimeFixedConfigurationBuildItem.class) + .produces(RunTimeConfigurationBuildItem.class) + .produces(UnmatchedConfigBuildItem.class) + .build()); for (Class clazz : ServiceUtil.classesNamedIn(classLoader, "META-INF/quarkus-build-steps.list")) { result = result.andThen(ExtensionLoader.loadStepsFrom(clazz)); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java b/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java index d203d022ce91f..1774e6e3381fe 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/QuarkusAugmentor.java @@ -22,7 +22,6 @@ import io.quarkus.builder.item.BuildItem; import io.quarkus.deployment.builditem.AdditionalApplicationArchiveBuildItem; import io.quarkus.deployment.builditem.ArchiveRootBuildItem; -import io.quarkus.deployment.builditem.BuildTimeConfigurationSourceBuildItem; import io.quarkus.deployment.builditem.ClassOutputBuildItem; import io.quarkus.deployment.builditem.ExtensionClassLoaderBuildItem; import io.quarkus.deployment.builditem.GeneratedClassBuildItem; @@ -31,7 +30,6 @@ import io.quarkus.deployment.builditem.LiveReloadBuildItem; import io.quarkus.deployment.builditem.ShutdownContextBuildItem; import io.quarkus.runtime.LaunchMode; -import io.smallrye.config.PropertiesConfigSource; public class QuarkusAugmentor { @@ -71,7 +69,11 @@ public BuildResult run() throws Exception { final BuildChainBuilder chainBuilder = BuildChain.builder(); - ExtensionLoader.loadStepsFrom(classLoader).accept(chainBuilder); + if (buildSystemProperties != null) { + ExtensionLoader.loadStepsFrom(classLoader, buildSystemProperties).accept(chainBuilder); + } else { + ExtensionLoader.loadStepsFrom(classLoader).accept(chainBuilder); + } chainBuilder.loadProviders(classLoader); chainBuilder @@ -89,10 +91,6 @@ public BuildResult run() throws Exception { chainBuilder.addFinal(GeneratedClassBuildItem.class) .addFinal(GeneratedResourceBuildItem.class); - if (buildSystemProperties != null) { - chainBuilder.addInitial(BuildTimeConfigurationSourceBuildItem.class); - } - for (Consumer i : buildChainCustomizers) { i.accept(chainBuilder); } @@ -113,11 +111,6 @@ public BuildResult run() throws Exception { for (Path i : additionalApplicationArchives) { execBuilder.produce(new AdditionalApplicationArchiveBuildItem(i)); } - if (buildSystemProperties != null) { - execBuilder.produce( - new BuildTimeConfigurationSourceBuildItem( - new PropertiesConfigSource(buildSystemProperties, "Build system"))); - } BuildResult buildResult = execBuilder .execute(); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationDefaultBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationDefaultBuildItem.java deleted file mode 100644 index 3db4963550d04..0000000000000 --- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationDefaultBuildItem.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.quarkus.deployment.builditem; - -import org.wildfly.common.Assert; - -import io.quarkus.builder.item.MultiBuildItem; -import io.quarkus.runtime.annotations.ConfigItem; - -/** - * A build item which specifies a configuration default value for build time, which is used to establish a default other - * than the one given for {@link ConfigItem#defaultValue()}. - */ -public final class BuildTimeConfigurationDefaultBuildItem extends MultiBuildItem { - private final String key; - private final String value; - - /** - * Construct a new instance. - * - * @param key the configuration key (must not be {@code null} or empty) - * @param value the configuration value (must not be {@code null}) - */ - public BuildTimeConfigurationDefaultBuildItem(final String key, final String value) { - Assert.checkNotNullParam("key", key); - Assert.checkNotEmptyParam("key", key); - Assert.checkNotNullParam("value", value); - this.key = key; - this.value = value; - } - - /** - * Get the configuration key. - * - * @return the configuration key (not {@code null} or empty) - */ - public String getKey() { - return key; - } - - /** - * Get the configuration value. - * - * @return the configuration value (must not be {@code null}) - */ - public String getValue() { - return value; - } -} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationSourceBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationSourceBuildItem.java deleted file mode 100644 index a6a9d26234868..0000000000000 --- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/BuildTimeConfigurationSourceBuildItem.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.quarkus.deployment.builditem; - -import java.util.function.Supplier; - -import org.eclipse.microprofile.config.spi.ConfigSource; -import org.wildfly.common.Assert; - -import io.quarkus.builder.item.MultiBuildItem; - -/** - * Define an additional configuration source which is used at build time. - */ -public final class BuildTimeConfigurationSourceBuildItem extends MultiBuildItem { - private final Supplier configSourceSupplier; - - /** - * Construct a new instance. - * - * @param configSourceSupplier the config source supplier (must not be {@code null}) - */ - public BuildTimeConfigurationSourceBuildItem(final Supplier configSourceSupplier) { - Assert.checkNotNullParam("configSourceSupplier", configSourceSupplier); - this.configSourceSupplier = configSourceSupplier; - } - - /** - * Construct a new instance. - * - * @param configSource the config source (must not be {@code null}) - */ - public BuildTimeConfigurationSourceBuildItem(final ConfigSource configSource) { - this(() -> Assert.checkNotNullParam("configSource", configSource)); - } - - /** - * Get the config source supplier. - * - * @return the config source supplier - */ - public Supplier getConfigSourceSupplier() { - return configSourceSupplier; - } -} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/UnmatchedConfigBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/UnmatchedConfigBuildItem.java new file mode 100644 index 0000000000000..efa0d13064d48 --- /dev/null +++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/UnmatchedConfigBuildItem.java @@ -0,0 +1,34 @@ +package io.quarkus.deployment.builditem; + +import java.util.Set; + +import org.wildfly.common.Assert; + +import io.quarkus.builder.item.SimpleBuildItem; + +/** + * An internal build item which relays the unmatched configuration key set from the extension loader + * to configuration setup stages. + */ +public final class UnmatchedConfigBuildItem extends SimpleBuildItem { + private final Set set; + + /** + * Construct a new instance. + * + * @param set the non-{@code null}, immutable set + */ + public UnmatchedConfigBuildItem(final Set set) { + Assert.checkNotNullParam("set", set); + this.set = set; + } + + /** + * Get the set. + * + * @return the set + */ + public Set getSet() { + return set; + } +} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationInfoBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationInfoBuildStep.java index 5f3c56b0cd930..116a48df28e4d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationInfoBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationInfoBuildStep.java @@ -1,65 +1,13 @@ package io.quarkus.deployment.steps; -import static io.quarkus.deployment.ApplicationInfoUtil.APPLICATION_INFO_PROPERTIES; -import static io.quarkus.deployment.ApplicationInfoUtil.ARTIFACT_ID_KEY; -import static io.quarkus.deployment.ApplicationInfoUtil.META_INF; -import static io.quarkus.deployment.ApplicationInfoUtil.VERSION_KEY; -import static io.quarkus.deployment.builditem.ApplicationInfoBuildItem.UNSET_VALUE; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Enumeration; -import java.util.Properties; - import io.quarkus.deployment.ApplicationConfig; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.ApplicationInfoBuildItem; public class ApplicationInfoBuildStep { - private static final String PROPERTIES_FILE_TO_READ = META_INF + File.separator + APPLICATION_INFO_PROPERTIES; - @BuildStep public ApplicationInfoBuildItem create(ApplicationConfig applicationConfig) { - final String userConfiguredName = applicationConfig.name; - final String userConfiguredVersion = applicationConfig.version; - - final Properties applicationInfoProperties = getApplicationInfoProperties(); - - return new ApplicationInfoBuildItem( - useIfNotEmpty(userConfiguredName, applicationInfoProperties, ARTIFACT_ID_KEY), - useIfNotEmpty(userConfiguredVersion, applicationInfoProperties, VERSION_KEY)); - } - - private Properties getApplicationInfoProperties() { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl == null) { - cl = ApplicationInfoBuildStep.class.getClassLoader(); - } - try { - final Properties p = new Properties(); - // work around #1477 - final Enumeration resources = cl == null ? ClassLoader.getSystemResources(PROPERTIES_FILE_TO_READ) - : cl.getResources(PROPERTIES_FILE_TO_READ); - if (resources.hasMoreElements()) { - final URL url = resources.nextElement(); - try (InputStream is = url.openStream()) { - try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8)) { - p.load(isr); - } - } - } - return p; - } catch (IOException e) { - throw new IllegalStateException("Cannot read application-info.properties", e); - } - } - - private String useIfNotEmpty(String value, Properties properties, String key) { - return (value != null) && !value.isEmpty() ? value : properties.getProperty(key, UNSET_VALUE); + return new ApplicationInfoBuildItem(applicationConfig.name, applicationConfig.version); } } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigurationSetup.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigurationSetup.java index ed4e3ae8dfac3..359ed5f9433a0 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigurationSetup.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigurationSetup.java @@ -21,6 +21,7 @@ import java.util.function.UnaryOperator; import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.spi.ConfigBuilder; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.eclipse.microprofile.config.spi.ConfigSource; @@ -36,9 +37,6 @@ import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem; import io.quarkus.deployment.builditem.ArchiveRootBuildItem; -import io.quarkus.deployment.builditem.BuildTimeConfigurationBuildItem; -import io.quarkus.deployment.builditem.BuildTimeConfigurationDefaultBuildItem; -import io.quarkus.deployment.builditem.BuildTimeConfigurationSourceBuildItem; import io.quarkus.deployment.builditem.BuildTimeRunTimeFixedConfigurationBuildItem; import io.quarkus.deployment.builditem.BytecodeRecorderObjectLoaderBuildItem; import io.quarkus.deployment.builditem.ExtensionClassLoaderBuildItem; @@ -47,12 +45,12 @@ import io.quarkus.deployment.builditem.RunTimeConfigurationBuildItem; import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem; import io.quarkus.deployment.builditem.RunTimeConfigurationSourceBuildItem; +import io.quarkus.deployment.builditem.UnmatchedConfigBuildItem; import io.quarkus.deployment.builditem.substrate.RuntimeInitializedClassBuildItem; import io.quarkus.deployment.builditem.substrate.ServiceProviderBuildItem; import io.quarkus.deployment.builditem.substrate.SubstrateResourceBuildItem; import io.quarkus.deployment.configuration.ConfigDefinition; import io.quarkus.deployment.configuration.ConfigPatternMap; -import io.quarkus.deployment.configuration.DefaultValuesConfigurationSource; import io.quarkus.deployment.configuration.LeafConfigType; import io.quarkus.deployment.recording.ObjectLoader; import io.quarkus.deployment.util.ServiceUtil; @@ -64,7 +62,6 @@ import io.quarkus.gizmo.MethodCreator; import io.quarkus.gizmo.MethodDescriptor; import io.quarkus.gizmo.ResultHandle; -import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; import io.quarkus.runtime.configuration.AbstractRawDefaultConfigSource; import io.quarkus.runtime.configuration.ApplicationPropertiesConfigSource; @@ -77,10 +74,8 @@ import io.quarkus.runtime.configuration.NameIterator; import io.quarkus.runtime.configuration.ProfileManager; import io.quarkus.runtime.configuration.SimpleConfigurationProviderResolver; -import io.smallrye.config.PropertiesConfigSource; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigBuilder; -import io.smallrye.config.SmallRyeConfigProviderResolver; /** * Setup steps for configuration purposes. @@ -162,121 +157,39 @@ public class ConfigurationSetup { private static final MethodDescriptor SET_RUNTIME_DEFAULT_PROFILE = MethodDescriptor.ofMethod(ProfileManager.class, "setRuntimeDefaultProfile", void.class, String.class); - private static final String CONFIG_ROOTS_LIST = "META-INF/quarkus-config-roots.list"; private static final String[] NO_STRINGS = new String[0]; public ConfigurationSetup() { } - /** - * Calculate the build-time default values. - * - * @param defaultItems default values items - * @return the default values config source - */ - @BuildStep - public BuildTimeConfigurationSourceBuildItem buildTimeDefaults( - List defaultItems) { - Map map = new HashMap<>(); - for (BuildTimeConfigurationDefaultBuildItem item : defaultItems) { - map.put(item.getKey(), item.getValue()); - } - PropertiesConfigSource pcs = new PropertiesConfigSource(map, "Build time supplemental defaults", 0); - return new BuildTimeConfigurationSourceBuildItem(pcs); - } - /** * Run before anything that consumes configuration; sets up the main configuration definition instance. * - * @param runTimeConfigConsumer the run time config consumer - * @param buildTimeConfigConsumer the build time config consumer - * @param buildTimeRunTimeConfigConsumer the build time/run time fixed config consumer + * @param runTimeConfigItem the run time config item + * @param buildTimeRunTimeConfigItem the build time/run time fixed config item * @param resourceConsumer * @param niResourceConsumer * @param runTimeDefaultConsumer - * @param configSourceItems the build-time config source build items + * @param unmatchedConfigBuildItem the build item holding the unmatched config keys * @param extensionClassLoaderBuildItem the extension class loader build item * @param archiveRootBuildItem the application archive root * @throws IOException - * @throws ClassNotFoundException */ @BuildStep public void initializeConfiguration( - Consumer runTimeConfigConsumer, - Consumer buildTimeConfigConsumer, - Consumer buildTimeRunTimeConfigConsumer, + RunTimeConfigurationBuildItem runTimeConfigItem, + BuildTimeRunTimeFixedConfigurationBuildItem buildTimeRunTimeConfigItem, Consumer resourceConsumer, Consumer niResourceConsumer, Consumer runTimeDefaultConsumer, - List configSourceItems, - List buildTimeDefaultItems, + UnmatchedConfigBuildItem unmatchedConfigBuildItem, ExtensionClassLoaderBuildItem extensionClassLoaderBuildItem, - ArchiveRootBuildItem archiveRootBuildItem) throws IOException, ClassNotFoundException { - - // set up the configuration definitions - final ConfigDefinition buildTimeConfig = new ConfigDefinition(FieldDescriptor.of("Bogus", "No field", "Nothing")); - final ConfigDefinition buildTimeRunTimeConfig = new ConfigDefinition(BUILD_TIME_CONFIG_FIELD); - final ConfigDefinition runTimeConfig = new ConfigDefinition(RUN_TIME_CONFIG_FIELD, true); - - // populate it with all known types - for (Class clazz : ServiceUtil.classesNamedIn(extensionClassLoaderBuildItem.getExtensionClassLoader(), - CONFIG_ROOTS_LIST)) { - final ConfigRoot annotation = clazz.getAnnotation(ConfigRoot.class); - if (annotation == null) { - log.warnf("Ignoring configuration root %s because it has no annotation", clazz); - } else { - final ConfigPhase phase = annotation.phase(); - if (phase == ConfigPhase.RUN_TIME) { - runTimeConfig.registerConfigRoot(clazz); - } else if (phase == ConfigPhase.BUILD_AND_RUN_TIME_FIXED) { - buildTimeRunTimeConfig.registerConfigRoot(clazz); - } else if (phase == ConfigPhase.BUILD_TIME) { - buildTimeConfig.registerConfigRoot(clazz); - } else { - log.warnf("Unrecognized configuration phase \"%s\" on %s", phase, clazz); - } - } - } - - // now prepare & load the build configuration - final SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder(); - - // expand properties - final ExpandingConfigSource.Cache cache = new ExpandingConfigSource.Cache(); - builder.withWrapper(ExpandingConfigSource.wrapper(cache)); - builder.withWrapper(DeploymentProfileConfigSource.wrapper()); - builder.addDefaultSources(); - final ApplicationPropertiesConfigSource.InJar inJar = new ApplicationPropertiesConfigSource.InJar(); - final DefaultValuesConfigurationSource defaultSource = new DefaultValuesConfigurationSource( - buildTimeConfig.getLeafPatterns()); - builder.withSources(inJar, defaultSource); - final int cnt = configSourceItems.size(); - final ConfigSource[] configSources = new ConfigSource[cnt]; - int i = 0; - for (BuildTimeConfigurationSourceBuildItem item : configSourceItems) { - configSources[i++] = item.getConfigSourceSupplier().get(); - } - builder.withSources(configSources); + ArchiveRootBuildItem archiveRootBuildItem) throws IOException { - // populate builder with all converters loaded from ServiceLoader - ConverterSupport.populateConverters(builder); + SmallRyeConfig src = (SmallRyeConfig) ConfigProvider.getConfig(); - final SmallRyeConfig src = (SmallRyeConfig) builder - .addDefaultSources() - .addDiscoveredSources() - .addDiscoveredConverters() - .build(); - - SmallRyeConfigProviderResolver.instance().registerConfig(src, Thread.currentThread().getContextClassLoader()); - - final Set unmatched = new HashSet<>(); - ConfigDefinition.loadConfiguration(cache, src, unmatched, - buildTimeConfig, - buildTimeRunTimeConfig, // this one is only for generating a default-values config source - runTimeConfig); - // exclude any default config property names that aren't part of application.properties - final Set inJarPropertyNames = inJar.getPropertyNames(); - unmatched.removeIf(s -> !inJarPropertyNames.contains(s) && !s.startsWith("quarkus.")); + final ConfigDefinition runTimeConfig = runTimeConfigItem.getConfigDefinition(); + final ConfigDefinition buildTimeRunTimeConfig = buildTimeRunTimeConfigItem.getConfigDefinition(); // store the expanded values from the build final byte[] bytes; @@ -295,6 +208,9 @@ public void initializeConfiguration( new SubstrateResourceBuildItem(BuildTimeConfigFactory.BUILD_TIME_CONFIG_NAME)); // produce defaults for user-provided config + + final Set unmatched = new HashSet<>(); + unmatched.addAll(unmatchedConfigBuildItem.getSet()); unmatched.addAll(runTimeConfig.getLoadedProperties().keySet()); final boolean old = ExpandingConfigSource.setExpanding(false); try { @@ -306,10 +222,6 @@ public void initializeConfiguration( ExpandingConfigSource.setExpanding(old); } - // produce the config objects - runTimeConfigConsumer.accept(new RunTimeConfigurationBuildItem(runTimeConfig)); - buildTimeRunTimeConfigConsumer.accept(new BuildTimeRunTimeFixedConfigurationBuildItem(buildTimeRunTimeConfig)); - buildTimeConfigConsumer.accept(new BuildTimeConfigurationBuildItem(buildTimeConfig)); } @BuildStep diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java index 1e99ab38c0f92..caa26c0d60694 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java @@ -152,6 +152,8 @@ public void buildQuarkus() { realProperties.setProperty(key, (String) value); } } + realProperties.putIfAbsent("quarkus.application.name", appArtifact.getArtifactId()); + realProperties.putIfAbsent("quarkus.application.version", appArtifact.getVersion()); try (AppCreator appCreator = AppCreator.builder() // configure the build phases we want the app to go through diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java index 5698492838968..f50ff77ca662a 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java @@ -50,7 +50,6 @@ import io.quarkus.bootstrap.model.AppModel; import io.quarkus.bootstrap.resolver.AppModelResolver; import io.quarkus.bootstrap.resolver.AppModelResolverException; -import io.quarkus.deployment.ApplicationInfoUtil; import io.quarkus.dev.DevModeContext; import io.quarkus.dev.DevModeMain; import io.quarkus.gradle.QuarkusPluginExtension; @@ -289,7 +288,6 @@ public void startDev() { } extension.outputDirectory().mkdirs(); - ApplicationInfoUtil.writeApplicationInfoProperties(appModel.getAppArtifact(), extension.outputDirectory().toPath()); args.add("-jar"); args.add(tempFile.getAbsolutePath()); diff --git a/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java index 188e4c4f4918d..30625a98350ed 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java @@ -183,6 +183,8 @@ public void execute() throws MojoExecutionException { realProperties.setProperty(name, projectProperties.getProperty(name)); } } + realProperties.putIfAbsent("quarkus.application.name", project.getArtifactId()); + realProperties.putIfAbsent("quarkus.application.version", project.getVersion()); try (AppCreator appCreator = AppCreator.builder() // configure the build phases we want the app to go through .addPhase(new AugmentPhase() diff --git a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java index 656d958f532be..ac9978d42423b 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java @@ -48,7 +48,6 @@ import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver; import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver; import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject; -import io.quarkus.deployment.ApplicationInfoUtil; import io.quarkus.dev.DevModeContext; import io.quarkus.dev.DevModeMain; import io.quarkus.maven.components.MavenVersionEnforcer; @@ -331,7 +330,6 @@ public void execute() throws MojoFailureException, MojoExecutionException { } outputDirectory.mkdirs(); - ApplicationInfoUtil.writeApplicationInfoProperties(appModel.getAppArtifact(), outputDirectory.toPath()); args.add("-jar"); args.add(tempFile.getAbsolutePath()); diff --git a/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java index bd90fbc772f48..fc6792c1a1fb7 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import org.apache.maven.artifact.Artifact; @@ -274,10 +275,16 @@ public void execute() throws MojoExecutionException, MojoFailureException { throw new MojoExecutionException("Failed to resolve application model dependencies for " + appCoords, e); } + final Properties buildSystemProperties = project.getProperties(); + final Properties projectProperties = new Properties(); + projectProperties.putAll(buildSystemProperties); + projectProperties.putIfAbsent("quarkus.application.name", project.getArtifactId()); + projectProperties.putIfAbsent("quarkus.application.version", project.getVersion()); + creatorBuilder.addPhase(new AugmentPhase() .setAppClassesDir(new File(outputDirectory, "classes").toPath()) .setWiringClassesDir(wiringClassesDirectory.toPath()) - .setBuildSystemProperties(project.getProperties())) + .setBuildSystemProperties(projectProperties)) .addPhase(new RunnerJarPhase() .setFinalName(finalName)) .setWorkDir(buildDir.toPath());