Skip to content

Commit

Permalink
Fix config provider to honor default config sources when meta configu…
Browse files Browse the repository at this point in the history
…ration is not present.

Added a test to validate it.
  • Loading branch information
tomas-langer committed Dec 17, 2024
1 parent 28823e1 commit cb2a49d
Show file tree
Hide file tree
Showing 38 changed files with 418 additions and 330 deletions.
95 changes: 10 additions & 85 deletions config/config/src/main/java/io/helidon/config/ConfigProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,35 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import io.helidon.common.config.Config;
import io.helidon.common.config.ConfigException;
import io.helidon.common.config.ConfigValue;
import io.helidon.common.config.GlobalConfig;
import io.helidon.config.spi.ConfigFilter;
import io.helidon.config.spi.ConfigMapperProvider;
import io.helidon.config.spi.ConfigParser;
import io.helidon.config.spi.ConfigSource;
import io.helidon.service.registry.Service;

@Service.Singleton
class ConfigProvider implements Config {
class ConfigProvider implements Supplier<Config> {
private final Config config;

@SuppressWarnings("removal")
@Service.Inject
ConfigProvider(Supplier<MetaConfig> metaConfig,
ConfigProvider(Supplier<Optional<MetaConfig>> metaConfig,
Supplier<List<ConfigSource>> configSources,
Supplier<List<ConfigParser>> configParsers,
Supplier<List<ConfigFilter>> configFilters,
Supplier<List<ConfigMapperProvider>> configMappers) {
if (GlobalConfig.configured()) {
config = GlobalConfig.config();
if (io.helidon.common.config.GlobalConfig.configured()) {
config = io.helidon.common.config.GlobalConfig.config();
} else {
config = io.helidon.config.Config.builder()
.config(metaConfig.get().metaConfiguration())
.update(it -> metaConfig.get().ifPresent(metaConfigInstance ->
it.config(metaConfigInstance.metaConfiguration())))
.update(it -> configSources.get()
.forEach(it::addSource))
.update(it -> defaultConfigSources(it, configParsers))
Expand All @@ -69,81 +67,8 @@ class ConfigProvider implements Config {
}

@Override
public Key key() {
return config.key();
}

@Override
public Config root() {
return config.root();
}

@Override
public Config get(String key) throws io.helidon.common.config.ConfigException {
return config.get(key);
}

@Override
public Config detach() throws io.helidon.common.config.ConfigException {
return config.detach();
}

@Override
public boolean exists() {
return config.exists();
}

@Override
public boolean isLeaf() {
return config.isLeaf();
}

@Override
public boolean isObject() {
return config.isObject();
}

@Override
public boolean isList() {
return config.isList();
}

@Override
public boolean hasValue() {
return config.hasValue();
}

@Override
public <T> io.helidon.common.config.ConfigValue<T> as(Class<T> type) {
return config.as(type);
}

@Override
public <T> io.helidon.common.config.ConfigValue<T> map(Function<Config, T> mapper) {
return config.map(mapper);
}

@Override
public <T> io.helidon.common.config.ConfigValue<List<T>> asList(Class<T> type) throws
io.helidon.common.config.ConfigException {
return config.asList(type);
}

@Override
public <T> io.helidon.common.config.ConfigValue<List<T>> mapList(Function<Config, T> mapper) throws
io.helidon.common.config.ConfigException {
return config.mapList(mapper);
}

@Override
public <C extends Config> io.helidon.common.config.ConfigValue<List<C>> asNodeList() throws
io.helidon.common.config.ConfigException {
return config.asNodeList();
}

@Override
public ConfigValue<Map<String, String>> asMap() throws ConfigException {
return config.asMap();
public Config get() {
return config;
}

private void defaultConfigSources(io.helidon.config.Config.Builder configBuilder,
Expand Down
25 changes: 12 additions & 13 deletions config/config/src/main/java/io/helidon/config/MetaConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import io.helidon.config.spi.OverrideSource;
import io.helidon.config.spi.PollingStrategy;
import io.helidon.config.spi.RetryPolicy;
import io.helidon.service.registry.Service;

/**
* Meta configuration.
Expand Down Expand Up @@ -69,7 +68,6 @@
* <li>Classpath resource config source for resource {@code default.yaml} that is mandatory</li>
* </ul>
*/
@Service.Provider
public final class MetaConfig {
private static final System.Logger LOGGER = System.getLogger(MetaConfig.class.getName());
private static final Set<MediaType> SUPPORTED_MEDIA_TYPES;
Expand Down Expand Up @@ -97,7 +95,7 @@ public final class MetaConfig {

/**
* Create configuration from meta configuration (files or classpath resources), or create a default config instance
* if meta configuration is not present.
* if meta configuration is not present.
*
* @return a config instance
*/
Expand Down Expand Up @@ -177,7 +175,8 @@ public static RetryPolicy retryPolicy(Config metaConfig) {
/**
* Load a config source (or config sources) based on its meta configuration.
* The metaConfig must contain a key {@code type} that defines the type of the source to be found via providers, and
* a key {@code properties} with configuration of the config sources
* a key {@code properties} with configuration of the config sources
*
* @param sourceMetaConfig meta configuration of a config source
* @return config source instance
* @see Config.Builder#config(Config)
Expand Down Expand Up @@ -207,15 +206,6 @@ public static List<ConfigSource> configSource(Config sourceMetaConfig) {
}
}

/**
* Meta configuration if provided, or empty config if not.
*
* @return meta configuration
*/
public Config metaConfiguration() {
return this.metaConfig;
}

// override config source
static OverrideSource overrideSource(Config sourceMetaConfig) {
String type = sourceMetaConfig.get("type").asString().get();
Expand All @@ -240,6 +230,15 @@ static List<ConfigSource> configSources(Config metaConfig) {
return configSources;
}

/**
* Meta configuration if provided, or empty config if not.
*
* @return meta configuration
*/
public Config metaConfiguration() {
return this.metaConfig;
}

private static Config createDefault() {
// use defaults
Config.Builder builder = Config.builder();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.config;

import java.util.Optional;
import java.util.function.Supplier;

import io.helidon.service.registry.Service;

/**
* A ServiceRegistry factory that creates the meta config only if it is defined.
*/
@Service.Singleton
class MetaConfigFactory implements Supplier<Optional<MetaConfig>> {
@Override
public Optional<MetaConfig> get() {
return MetaConfig.metaConfig()
.map(it -> new MetaConfig());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,12 @@ private static ServiceSuperType superType(RegistryCodegenContext ctx, TypeInfo s

for (TypeInfo service : services) {
if (service.typeName().equals(superType.typeName())) {
return ServiceSuperType.create(service, "core", superTypeToExtend);
return ServiceSuperType.create(service, superTypeToExtend);
}
}
// if not found in current list, try checking existing types
return ctx.typeInfo(expectedSuperDescriptor)
.map(it -> ServiceSuperType.create(superType, "core", superTypeToExtend))
.map(it -> ServiceSuperType.create(superType, superTypeToExtend))
.orElseGet(ServiceSuperType::create);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,16 @@ public interface DescriptorClassCode {
* Create a new instance.
*
* @param classCode class code that contains necessary information for the generated class.
* @param registryType type of registry that generates the descriptor (core, inject)
* @param weight weight of the service this descriptor describes
* @param contracts contracts of the service (i.e. {@code MyContract})
* @param factoryContracts factory contracts of this service (i.e. {@code Supplier<MyContract>})
* @return a new class code of service descriptor
*/
static DescriptorClassCode create(ClassCode classCode,
String registryType,
double weight,
Set<ResolvedType> contracts,
Set<ResolvedType> factoryContracts) {
return new DescriptorClassCodeImpl(classCode,
registryType,
weight,
contracts,
factoryContracts);
Expand All @@ -54,13 +51,6 @@ static DescriptorClassCode create(ClassCode classCode,
*/
ClassCode classCode();

/**
* Type of registry of this descriptor.
*
* @return registry type
*/
String registryType();

/**
* Weight of the new descriptor.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import io.helidon.common.types.ResolvedType;

record DescriptorClassCodeImpl(ClassCode classCode,
String registryType,
double weight,
Set<ResolvedType> contracts,
Set<ResolvedType> factoryContracts) implements DescriptorClassCode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public interface RegistryRoundContext extends RoundContext {
/**
* Add a new service descriptor.
*
* @param registryType service registry this descriptor is designed for (core is the "top" level)
* @param serviceType type of the service (the implementation class we generate descriptor for)
* @param descriptorType type of the service descriptor
* @param descriptor descriptor class model
Expand All @@ -42,10 +41,7 @@ public interface RegistryRoundContext extends RoundContext {
* @param originatingElements possible originating elements (such as Element in APT, or ClassInfo in classpath scanning)
* @throws java.lang.IllegalStateException if an attempt is done to register a new descriptor for the same type
*/
// all parameters are needed, no sense in creating a builder
@SuppressWarnings("checkstyle:ParameterNumber")
void addDescriptor(String registryType,
TypeName serviceType,
void addDescriptor(TypeName serviceType,
TypeName descriptorType,
ClassModel.Builder descriptor,
double weight,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,13 @@ public void addGeneratedType(TypeName type,
}

@Override
public void addDescriptor(String registryType,
TypeName serviceType,
public void addDescriptor(TypeName serviceType,
TypeName descriptorType,
ClassModel.Builder descriptor,
double weight,
Set<ResolvedType> contracts,
Set<ResolvedType> factoryContracts,
Object... originatingElements) {
Objects.requireNonNull(registryType);
Objects.requireNonNull(serviceType);
Objects.requireNonNull(descriptorType);
Objects.requireNonNull(descriptor);
Expand All @@ -150,7 +148,6 @@ public void addDescriptor(String registryType,

addDescriptorConsumer
.accept(new DescriptorClassCodeImpl(new ClassCode(descriptorType, descriptor, serviceType, originatingElements),
registryType,
weight,
contracts,
factoryContracts));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ public void service(TypeName generator, RegistryRoundContext roundCtx, Collectio
metaInfFactoryContracts.add(ResolvedType.create(serviceTypeName));
}

roundCtx.addDescriptor("core",
serviceTypeName,
roundCtx.addDescriptor(serviceTypeName,
service.descriptorType(),
classModel,
weight(typeInfo).orElse(Weighted.DEFAULT_WEIGHT),
Expand Down Expand Up @@ -386,8 +385,7 @@ void describe(RegistryRoundContext roundCtx, TypeInfo typeInfo, Annotation descr
Set<ResolvedType> serviceContracts = new HashSet<>(contracts);
serviceContracts.add(ResolvedType.create(serviceTypeName));

roundCtx.addDescriptor("core",
serviceTypeName,
roundCtx.addDescriptor(serviceTypeName,
service.descriptorType(),
classModel,
weight(serviceDescriptor.typeInfo()).orElse(Weighted.DEFAULT_WEIGHT),
Expand Down Expand Up @@ -561,22 +559,19 @@ private ServiceSuperType superType(TypeInfo typeInfo, Collection<TypeInfo> servi
return ServiceSuperType.create();
}
TypeInfo superType = superTypeInfoOptional.get();
String serviceType = superType.hasAnnotation(SERVICE_ANNOTATION_PROVIDER)
? "core"
: "inject";

TypeName expectedSuperDescriptor = ctx.descriptorType(superType.typeName());
TypeName superTypeToExtend = TypeName.builder(expectedSuperDescriptor)
.addTypeArgument(TypeName.create("T"))
.build();
for (TypeInfo service : services) {
if (service.typeName().equals(superType.typeName())) {
return ServiceSuperType.create(service, serviceType, superTypeToExtend);
return ServiceSuperType.create(service, superTypeToExtend);
}
}
// if not found in current list, try checking existing types
return ctx.typeInfo(expectedSuperDescriptor)
.map(it -> ServiceSuperType.create(superType, serviceType, superTypeToExtend))
.map(it -> ServiceSuperType.create(superType, superTypeToExtend))
.orElseGet(ServiceSuperType::create);
}

Expand Down Expand Up @@ -1514,7 +1509,7 @@ private void dependenciesMethod(ClassModel.Builder classModel, DescribedService
.returnType(LIST_OF_DEPENDENCIES)
.name("dependencies")
.update(it -> {
if (hasSuperType && !service.superType().serviceType().equals("core")) {
if (hasSuperType) {
it.addContent("return ")
.addContent(SERVICE_G_DEPENDENCY_SUPPORT)
.addContentLine(".combineDependencies(DEPENDENCIES, super.dependencies());");
Expand Down
Loading

0 comments on commit cb2a49d

Please sign in to comment.