Skip to content

Commit

Permalink
Support ConfigMappings in Extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez committed Jan 27, 2022
1 parent f0446fd commit 4375a01
Show file tree
Hide file tree
Showing 32 changed files with 1,019 additions and 384 deletions.
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<microprofile-jwt.version>1.2</microprofile-jwt.version>
<microprofile-lra.version>1.0</microprofile-lra.version>
<smallrye-common.version>1.8.0</smallrye-common.version>
<smallrye-config.version>2.8.2</smallrye-config.version>
<smallrye-config.version>2.8.3-SNAPSHOT</smallrye-config.version>
<smallrye-health.version>3.2.0</smallrye-health.version>
<smallrye-metrics.version>3.0.4</smallrye-metrics.version>
<smallrye-open-api.version>2.1.17</smallrye-open-api.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected BooleanSupplier computeValue(Class<?> type) {
final ConfigRoot annotation = parameterClass.getAnnotation(ConfigRoot.class);
final ConfigPhase phase = annotation.phase();
if (phase.isAvailableAtBuild()) {
paramSuppList.add(() -> readResult.requireRootObjectForClass(parameterClass));
paramSuppList.add(() -> readResult.requireObjectForClass(parameterClass));
} else if (phase.isReadAtMain()) {
throw reportError(parameter, phase + " configuration cannot be consumed here");
} else {
Expand Down Expand Up @@ -82,7 +82,7 @@ protected BooleanSupplier computeValue(Class<?> type) {
final ConfigPhase phase = annotation.phase();
if (phase.isAvailableAtBuild()) {
setup = setup.andThen(o -> ReflectUtil.setFieldVal(field, o,
readResult.requireRootObjectForClass(fieldClass)));
readResult.requireObjectForClass(fieldClass)));
} else if (phase.isReadAtMain()) {
throw reportError(field, phase + " configuration cannot be consumed here");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

import javax.inject.Inject;

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;
Expand Down Expand Up @@ -74,6 +76,7 @@
import io.quarkus.deployment.builditem.RuntimeConfigSetupCompleteBuildItem;
import io.quarkus.deployment.builditem.StaticBytecodeRecorderBuildItem;
import io.quarkus.deployment.configuration.BuildTimeConfigurationReader;
import io.quarkus.deployment.configuration.ConfigMappingUtils;
import io.quarkus.deployment.configuration.DefaultValuesConfigurationSource;
import io.quarkus.deployment.configuration.definition.RootDefinition;
import io.quarkus.deployment.recording.BytecodeRecorderImpl;
Expand All @@ -84,6 +87,7 @@
import io.quarkus.dev.spi.DevModeType;
import io.quarkus.gizmo.BytecodeCreator;
import io.quarkus.gizmo.FieldDescriptor;
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.RuntimeValue;
Expand All @@ -92,6 +96,7 @@
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.configuration.ConfigUtils;
import io.quarkus.runtime.configuration.QuarkusConfigFactory;
import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix;
import io.smallrye.config.KeyMap;
import io.smallrye.config.KeyMapBackedConfigSource;
import io.smallrye.config.NameIterator;
Expand Down Expand Up @@ -165,6 +170,9 @@ public static Consumer<BuildChainBuilder> loadStepsFrom(ClassLoader classLoader,
builder.withSources(ds1, ds2, platformConfigSource, pcs);
}

for (ConfigClassWithPrefix mapping : reader.getBuildTimeVisibleMappings()) {
builder.withMapping(mapping.getKlass(), mapping.getPrefix());
}
final SmallRyeConfig src = builder.build();

// install globally
Expand Down Expand Up @@ -196,24 +204,60 @@ public static Consumer<BuildChainBuilder> loadStepsFrom(ClassLoader classLoader,
}

// this has to be an identity hash map else the recorder will get angry
Map<Object, FieldDescriptor> proxyFields = new IdentityHashMap<>();
Map<Object, FieldDescriptor> rootFields = new IdentityHashMap<>();
Map<Object, ConfigClassWithPrefix> mappingClasses = new IdentityHashMap<>();
for (Map.Entry<Class<?>, Object> entry : proxies.entrySet()) {
final RootDefinition def = readResult.requireRootDefinitionForClass(entry.getKey());
proxyFields.put(entry.getValue(), def.getDescriptor());
// ConfigRoot
RootDefinition root = readResult.getAllRootsByClass().get(entry.getKey());
if (root != null) {
rootFields.put(entry.getValue(), root.getDescriptor());
continue;
}

// ConfigMapping
ConfigClassWithPrefix mapping = readResult.getAllMappings().get(entry.getKey());
if (mapping != null) {
mappingClasses.put(entry.getValue(), mapping);
continue;
}

throw new IllegalStateException("No config found for " + entry.getKey());
}
result = result.andThen(bcb -> bcb.addBuildStep(bc -> {
bc.produce(new ConfigurationBuildItem(readResult));
bc.produce(new RunTimeConfigurationProxyBuildItem(proxies));
final ObjectLoader loader = new ObjectLoader() {

ObjectLoader rootLoader = new ObjectLoader() {
public ResultHandle load(final BytecodeCreator body, final Object obj, final boolean staticInit) {
return body.readStaticField(proxyFields.get(obj));
return body.readStaticField(rootFields.get(obj));
}

public boolean canHandleObject(final Object obj, final boolean staticInit) {
return proxyFields.containsKey(obj);
return rootFields.containsKey(obj);
}
};
bc.produce(new BytecodeRecorderObjectLoaderBuildItem(loader));

ObjectLoader mappingLoader = new ObjectLoader() {
@Override
public ResultHandle load(final BytecodeCreator body, final Object obj, final boolean staticInit) {
ConfigClassWithPrefix mapping = mappingClasses.get(obj);
MethodDescriptor getConfig = MethodDescriptor.ofMethod(ConfigProvider.class, "getConfig", Config.class);
ResultHandle config = body.invokeStaticMethod(getConfig);
MethodDescriptor getMapping = MethodDescriptor.ofMethod(SmallRyeConfig.class, "getConfigMapping",
Object.class, Class.class, String.class);
return body.invokeVirtualMethod(getMapping, config, body.loadClass(mapping.getKlass()),
body.load(mapping.getPrefix()));
}

@Override
public boolean canHandleObject(final Object obj, final boolean staticInit) {
return mappingClasses.containsKey(obj);
}
};

bc.produce(new BytecodeRecorderObjectLoaderBuildItem(rootLoader));
bc.produce(new BytecodeRecorderObjectLoaderBuildItem(mappingLoader));

}).produces(ConfigurationBuildItem.class)
.produces(RunTimeConfigurationProxyBuildItem.class)
.produces(BytecodeRecorderObjectLoaderBuildItem.class)
Expand Down Expand Up @@ -337,9 +381,9 @@ private static Consumer<BuildChainBuilder> loadStepsFromClass(Class<?> clazz,

if (phase.isAvailableAtBuild()) {
ctorParamFns.add(bc -> bc.consume(ConfigurationBuildItem.class).getReadResult()
.requireRootObjectForClass(parameterClass));
.requireObjectForClass(parameterClass));
if (phase == ConfigPhase.BUILD_AND_RUN_TIME_FIXED) {
runTimeProxies.computeIfAbsent(parameterClass, readResult::requireRootObjectForClass);
runTimeProxies.computeIfAbsent(parameterClass, readResult::requireObjectForClass);
}
} else if (phase.isReadAtMain()) {
throw reportError(parameter, phase + " configuration cannot be consumed here");
Expand Down Expand Up @@ -453,10 +497,10 @@ private static Consumer<BuildChainBuilder> loadStepsFromClass(Class<?> clazz,
final ConfigurationBuildItem configurationBuildItem = bc
.consume(ConfigurationBuildItem.class);
ReflectUtil.setFieldVal(field, o,
configurationBuildItem.getReadResult().requireRootObjectForClass(fieldClass));
configurationBuildItem.getReadResult().requireObjectForClass(fieldClass));
});
if (phase == ConfigPhase.BUILD_AND_RUN_TIME_FIXED) {
runTimeProxies.computeIfAbsent(fieldClass, readResult::requireRootObjectForClass);
runTimeProxies.computeIfAbsent(fieldClass, readResult::requireObjectForClass);
}
} else if (phase.isReadAtMain()) {
throw reportError(field, phase + " configuration cannot be consumed here");
Expand Down Expand Up @@ -618,10 +662,10 @@ private static Consumer<BuildChainBuilder> loadStepsFromClass(Class<?> clazz,
methodParamFns.add((bc, bri) -> {
final ConfigurationBuildItem configurationBuildItem = bc
.consume(ConfigurationBuildItem.class);
return configurationBuildItem.getReadResult().requireRootObjectForClass(parameterClass);
return configurationBuildItem.getReadResult().requireObjectForClass(parameterClass);
});
if (isRecorder && phase == ConfigPhase.BUILD_AND_RUN_TIME_FIXED) {
runTimeProxies.computeIfAbsent(parameterClass, readResult::requireRootObjectForClass);
runTimeProxies.computeIfAbsent(parameterClass, readResult::requireObjectForClass);
}
} else if (phase.isReadAtMain()) {
if (isRecorder) {
Expand All @@ -630,7 +674,7 @@ private static Consumer<BuildChainBuilder> loadStepsFromClass(Class<?> clazz,
.consume(RunTimeConfigurationProxyBuildItem.class);
return proxies.getProxyObjectFor(parameterClass);
});
runTimeProxies.computeIfAbsent(parameterClass, ReflectUtil::newInstance);
runTimeProxies.computeIfAbsent(parameterClass, ConfigMappingUtils::newInstance);
} else {
throw reportError(parameter,
phase + " configuration cannot be consumed here unless the method is a @Recorder");
Expand Down Expand Up @@ -673,10 +717,9 @@ private static Consumer<BuildChainBuilder> loadStepsFromClass(Class<?> clazz,
methodConsumingConfigPhases.add(annotation.phase());
}
if (annotation.phase().isReadAtMain()) {
runTimeProxies.computeIfAbsent(theType, ReflectUtil::newInstance);
runTimeProxies.computeIfAbsent(theType, ConfigMappingUtils::newInstance);
} else {
runTimeProxies.computeIfAbsent(theType,
readResult::requireRootObjectForClass);
runTimeProxies.computeIfAbsent(theType, readResult::requireObjectForClass);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,16 @@
* example config files and docs
*/
public final class ConfigDescriptionBuildItem extends MultiBuildItem implements Comparable<ConfigDescriptionBuildItem> {

private final String propertyName;
private final Class<?> type;
private final String defaultValue;
private final String docs;
private final String valueTypeName;
private final List<String> allowedValues;
private final ConfigPhase configPhase;

public ConfigDescriptionBuildItem(String propertyName, Class<?> type, String defaultValue, String docs,
String valueTypeName, List<String> allowedValues, ConfigPhase configPhase) {
public ConfigDescriptionBuildItem(String propertyName, String defaultValue, String docs, String valueTypeName,
List<String> allowedValues, ConfigPhase configPhase) {
this.propertyName = propertyName;
this.type = type;
this.defaultValue = defaultValue;
this.docs = docs;
this.valueTypeName = valueTypeName;
Expand All @@ -34,10 +31,6 @@ public String getPropertyName() {
return propertyName;
}

public Class<?> getType() {
return type;
}

public String getDefaultValue() {
return defaultValue;
}
Expand Down
Loading

0 comments on commit 4375a01

Please sign in to comment.