Skip to content

Commit

Permalink
Allow accessing build time config POJOs from a CodeGenProvider fix qu…
Browse files Browse the repository at this point in the history
  • Loading branch information
ppalaga committed Sep 15, 2023
1 parent 82344e7 commit ad4b6bd
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Function;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigValue;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.eclipse.microprofile.config.spi.Converter;
import org.jboss.logging.Logger;

import io.quarkus.bootstrap.classloading.MemoryClassPathElement;
Expand All @@ -37,6 +41,7 @@
import io.quarkus.paths.PathCollection;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.util.ClassPathUtils;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.SmallRyeConfig;

/**
Expand Down Expand Up @@ -270,7 +275,12 @@ public static void dumpCurrentConfigValues(ApplicationModel appModel, String lau
public static Config getConfig(ApplicationModel appModel, LaunchMode launchMode, Properties buildSystemProps,
QuarkusClassLoader deploymentClassLoader) throws CodeGenException {
return readConfig(appModel, launchMode, buildSystemProps, deploymentClassLoader,
configReader -> configReader.initConfiguration(launchMode, buildSystemProps, appModel.getPlatformProperties()));
configReader -> {
final SmallRyeConfig config = configReader.initConfiguration(launchMode, buildSystemProps,
appModel.getPlatformProperties());
final Map<Class<?>, Object> objectsByClass = configReader.readConfiguration(config).getObjectsByClass();
return new BuildTimeConfig(config, objectsByClass);
});
}

public static <T> T readConfig(ApplicationModel appModel, LaunchMode launchMode, Properties buildSystemProps,
Expand Down Expand Up @@ -402,4 +412,66 @@ private static Path codeGenOutDir(Path generatedSourcesDir,
private interface CodeGenAction<T> {
T fire() throws CodeGenException;
}

/**
* Beyond regular functionality brought by the delegate {@link Config}, this implementation is able to lookup
* root build time configuration POJOs from the {@link #objectsByClass} map.
*/
static class BuildTimeConfig implements Config {

private final Config delegate;
private final Map<Class<?>, Object> objectsByClass;

public BuildTimeConfig(Config delegate, Map<Class<?>, Object> objectsByClass) {
this.delegate = delegate;
this.objectsByClass = objectsByClass;
}

public <T> T getValue(String propertyName, Class<T> propertyType) {
final Object result = objectsByClass.get(propertyType);
if (result != null) {
final ConfigMapping configMapping = propertyType.getAnnotation(ConfigMapping.class);
if (configMapping != null) {
final String prefix = configMapping.prefix();
if (prefix != null && prefix.equals(propertyName)) {
return (T) result;
}
}
}
return delegate.getValue(propertyName, propertyType);
}

public ConfigValue getConfigValue(String propertyName) {
return delegate.getConfigValue(propertyName);
}

public <T> List<T> getValues(String propertyName, Class<T> propertyType) {
return delegate.getValues(propertyName, propertyType);
}

public <T> Optional<T> getOptionalValue(String propertyName, Class<T> propertyType) {
return delegate.getOptionalValue(propertyName, propertyType);
}

public <T> Optional<List<T>> getOptionalValues(String propertyName, Class<T> propertyType) {
return delegate.getOptionalValues(propertyName, propertyType);
}

public Iterable<String> getPropertyNames() {
return delegate.getPropertyNames();
}

public Iterable<ConfigSource> getConfigSources() {
return delegate.getConfigSources();
}

public <T> Optional<Converter<T>> getConverter(Class<T> forType) {
return delegate.getConverter(forType);
}

public <T> T unwrap(Class<T> type) {
return delegate.unwrap(type);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.acme.codegen.deployment;

import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;

@ConfigMapping(prefix = "quarkus.acme")
@ConfigRoot(phase = ConfigPhase.BUILD_TIME)
public interface AcmeBuildTimeConfig {

/** codegen docs */
public CodeGenConfig codegen();

@ConfigGroup
public interface CodeGenConfig {

/** enabled docs */
@WithDefault("true")
public boolean enabled();

/** stringOptional docs */
public Optional<String> stringOptional();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,22 @@ public String inputDirectory() {

@Override
public boolean trigger(CodeGenContext context) throws CodeGenException {
/* Let's test whether getting build time config POJOs from the config works */
final AcmeBuildTimeConfig config = context.config().getValue("quarkus.acme", AcmeBuildTimeConfig.class);
if (config == null) {
throw new AssertionError("context.config().getValue(\"quarkus.acme\", AcmeBuildTimeConfig.class) should return a AcmeBuildTimeConfig instance");
}
if (!config.codegen().enabled()) {
throw new AssertionError("config.codegen().enabled() should have default value \"true\"");
}
if (config.codegen().stringOptional().isPresent()) {
throw new AssertionError("config.codegen().stringOptional() should have no value");
}
generateEndpoint(context, AcmeConstants.ACME_CONFIG_FACTORY_PROP);
generateEndpoint(context, AcmeConstants.ACME_CONFIG_PROVIDER_PROP);
return true;
}

@Override
public boolean shouldRun(Path sourceDir, Config config) {
return !sourceDir.getParent().getFileName().toString().equals("generated-test-sources");
Expand All @@ -50,9 +61,9 @@ private void generateEndpoint(CodeGenContext ctx, String propName) throws CodeGe
throw new CodeGenException("Failed to generate sources", e);
}
}

private static void generateEndpoint(Path outputDir, String name, String value) throws IOException {

final StringBuilder sb = new StringBuilder();
boolean nextUpperCase = true;
for(int i = 0; i < name.length(); ++i) {
Expand All @@ -67,7 +78,7 @@ private static void generateEndpoint(Path outputDir, String name, String value)
}
}
sb.append("Resource");

final String className = sb.toString();
final Path javaFile = outputDir.resolve("org").resolve(ACME).resolve(className + ".java");
Files.createDirectories(javaFile.getParent());
Expand Down

0 comments on commit ad4b6bd

Please sign in to comment.