
io.smallrye.config.SmallRyeConfigBuilder Maven / Gradle / Ivy
/*
* Copyright 2017 Red Hat, Inc.
*
* 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.smallrye.config;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Priority;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigBuilder;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.eclipse.microprofile.config.spi.ConfigSourceProvider;
import org.eclipse.microprofile.config.spi.Converter;
/**
* @author Jeff Mesnil (c) 2017 Red Hat inc.
*/
public class SmallRyeConfigBuilder implements ConfigBuilder {
private static final String META_INF_MICROPROFILE_CONFIG_PROPERTIES = "META-INF/microprofile-config.properties";
private static final String WEB_INF_MICROPROFILE_CONFIG_PROPERTIES = "WEB-INF/classes/META-INF/microprofile-config.properties";
// sources are not sorted by their ordinals
private final List sources = new ArrayList<>();
private Function sourceWrappers = UnaryOperator.identity();
private final Map converters = new HashMap<>();
private final List profiles = new ArrayList<>();
private final Set secretKeys = new HashSet<>();
private final List interceptors = new ArrayList<>();
private final KeyMap defaultValues = new KeyMap<>();
private final ConfigMappingProvider.Builder mappingsBuilder = ConfigMappingProvider.builder();
private ClassLoader classLoader = SecuritySupport.getContextClassLoader();
private boolean addDefaultSources = false;
private boolean addDefaultInterceptors = false;
private boolean addDiscoveredSources = false;
private boolean addDiscoveredConverters = false;
private boolean addDiscoveredInterceptors = false;
public SmallRyeConfigBuilder() {
}
@Override
public SmallRyeConfigBuilder addDiscoveredSources() {
addDiscoveredSources = true;
return this;
}
@Override
public SmallRyeConfigBuilder addDiscoveredConverters() {
addDiscoveredConverters = true;
return this;
}
public SmallRyeConfigBuilder addDiscoveredInterceptors() {
addDiscoveredInterceptors = true;
return this;
}
List discoverSources() {
List discoveredSources = new ArrayList<>();
ServiceLoader configSourceLoader = ServiceLoader.load(ConfigSource.class, classLoader);
for (ConfigSource source : configSourceLoader) {
discoveredSources.add(source);
}
// load all ConfigSources from ConfigSourceProviders
ServiceLoader configSourceProviderLoader = ServiceLoader.load(ConfigSourceProvider.class,
classLoader);
for (ConfigSourceProvider configSourceProvider : configSourceProviderLoader) {
for (ConfigSource configSource : configSourceProvider.getConfigSources(classLoader)) {
discoveredSources.add(configSource);
}
}
ServiceLoader configSourceFactoryLoader = ServiceLoader.load(ConfigSourceFactory.class,
classLoader);
for (ConfigSourceFactory factory : configSourceFactoryLoader) {
discoveredSources.add(new ConfigurableConfigSource(factory));
}
return discoveredSources;
}
List> discoverConverters() {
List> discoveredConverters = new ArrayList<>();
for (Converter> converter : ServiceLoader.load(Converter.class, classLoader)) {
discoveredConverters.add(converter);
}
return discoveredConverters;
}
List discoverInterceptors() {
List interceptors = new ArrayList<>();
ServiceLoader interceptorLoader = ServiceLoader.load(ConfigSourceInterceptor.class,
classLoader);
for (ConfigSourceInterceptor configSourceInterceptor : interceptorLoader) {
interceptors.add(new InterceptorWithPriority(configSourceInterceptor));
}
ServiceLoader interceptorFactoryLoader = ServiceLoader
.load(ConfigSourceInterceptorFactory.class, classLoader);
for (ConfigSourceInterceptorFactory interceptor : interceptorFactoryLoader) {
interceptors.add(new InterceptorWithPriority(interceptor));
}
return interceptors;
}
@Override
public SmallRyeConfigBuilder addDefaultSources() {
addDefaultSources = true;
return this;
}
protected List getDefaultSources() {
List defaultSources = new ArrayList<>();
defaultSources.add(new EnvConfigSource());
defaultSources.add(new SysPropConfigSource());
defaultSources.addAll(new PropertiesConfigSourceProvider(META_INF_MICROPROFILE_CONFIG_PROPERTIES, true, classLoader)
.getConfigSources(classLoader));
defaultSources.addAll(new PropertiesConfigSourceProvider(WEB_INF_MICROPROFILE_CONFIG_PROPERTIES, true, classLoader)
.getConfigSources(classLoader));
defaultSources
.addAll(new ProfilePropertiesConfigSourceProvider(META_INF_MICROPROFILE_CONFIG_PROPERTIES, true, classLoader)
.getConfigSources(classLoader));
defaultSources
.addAll(new ProfilePropertiesConfigSourceProvider(WEB_INF_MICROPROFILE_CONFIG_PROPERTIES, true, classLoader)
.getConfigSources(classLoader));
return defaultSources;
}
public SmallRyeConfigBuilder addDefaultInterceptors() {
this.addDefaultInterceptors = true;
return this;
}
List getDefaultInterceptors() {
final List interceptors = new ArrayList<>();
interceptors.add(new InterceptorWithPriority(new ConfigSourceInterceptorFactory() {
@Override
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
return profiles.isEmpty() ? new ProfileConfigSourceInterceptor(context)
: new ProfileConfigSourceInterceptor(profiles);
}
@Override
public OptionalInt getPriority() {
return OptionalInt.of(Priorities.LIBRARY + 600);
}
}));
interceptors.add(new InterceptorWithPriority(new ConfigSourceInterceptorFactory() {
@Override
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
final Map relocations = new HashMap<>();
relocations.put(ProfileConfigSourceInterceptor.SMALLRYE_PROFILE, Config.PROFILE);
return new RelocateConfigSourceInterceptor(relocations);
}
@Override
public OptionalInt getPriority() {
return OptionalInt.of(Priorities.LIBRARY + 600 - 1);
}
}));
interceptors.add(new InterceptorWithPriority(new ConfigSourceInterceptorFactory() {
@Override
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
return new ExpressionConfigSourceInterceptor(context);
}
@Override
public OptionalInt getPriority() {
return OptionalInt.of(Priorities.LIBRARY + 800);
}
}));
interceptors.add(new InterceptorWithPriority(new SecretKeysConfigSourceInterceptor(secretKeys)));
return interceptors;
}
@Override
public SmallRyeConfigBuilder forClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
return this;
}
@Override
public SmallRyeConfigBuilder withSources(ConfigSource... configSources) {
Collections.addAll(sources, configSources);
return this;
}
public SmallRyeConfigBuilder withSources(Collection configSources) {
sources.addAll(configSources);
return this;
}
public SmallRyeConfigBuilder withSources(ConfigSourceFactory... configSourceFactories) {
for (ConfigSourceFactory configSourceFactory : configSourceFactories) {
sources.add(new ConfigurableConfigSource(configSourceFactory));
}
return this;
}
public SmallRyeConfigBuilder withInterceptors(ConfigSourceInterceptor... interceptors) {
for (ConfigSourceInterceptor interceptor : interceptors) {
this.interceptors.add(new InterceptorWithPriority(interceptor));
}
return this;
}
public SmallRyeConfigBuilder withInterceptorFactories(ConfigSourceInterceptorFactory... interceptorFactories) {
for (ConfigSourceInterceptorFactory interceptorFactory : interceptorFactories) {
this.interceptors.add(new InterceptorWithPriority(interceptorFactory));
}
return this;
}
public SmallRyeConfigBuilder withProfile(String profile) {
addDefaultInterceptors();
this.profiles.addAll(ProfileConfigSourceInterceptor.convertProfile(profile));
return this;
}
public SmallRyeConfigBuilder withProfiles(List profiles) {
addDefaultInterceptors();
this.profiles.addAll(profiles);
return this;
}
public SmallRyeConfigBuilder withSecretKeys(String... keys) {
secretKeys.addAll(Stream.of(keys).collect(Collectors.toSet()));
return this;
}
public SmallRyeConfigBuilder withDefaultValue(String name, String value) {
this.defaultValues.findOrAdd(name).putRootValue(value);
return this;
}
public SmallRyeConfigBuilder withDefaultValues(Map defaultValues) {
for (Map.Entry entry : defaultValues.entrySet()) {
this.defaultValues.findOrAdd(entry.getKey()).putRootValue(entry.getValue());
}
return this;
}
public SmallRyeConfigBuilder withMapping(Class> klass) {
return withMapping(klass, ConfigMappings.getPrefix(klass));
}
public SmallRyeConfigBuilder withMapping(Class> klass, String prefix) {
mappingsBuilder.addRoot(prefix, klass);
return this;
}
public SmallRyeConfigBuilder withMappingIgnore(String path) {
mappingsBuilder.addIgnored(path);
return this;
}
public SmallRyeConfigBuilder withValidateUnknown(boolean validateUnknown) {
mappingsBuilder.validateUnknown(validateUnknown);
return this;
}
@Override
public SmallRyeConfigBuilder withConverters(Converter>[] converters) {
for (Converter> converter : converters) {
Type type = Converters.getConverterType(converter.getClass());
if (type == null) {
throw ConfigMessages.msg.unableToAddConverter(converter);
}
addConverter(type, getPriority(converter), converter, this.converters);
}
return this;
}
@Override
public SmallRyeConfigBuilder withConverter(Class type, int priority, Converter converter) {
addConverter(type, priority, converter, converters);
return this;
}
@Deprecated
public SmallRyeConfigBuilder withWrapper(UnaryOperator wrapper) {
sourceWrappers = sourceWrappers.andThen(wrapper);
return this;
}
static void addConverter(Type type, Converter> converter, Map converters) {
addConverter(type, getPriority(converter), converter, converters);
}
static void addConverter(Type type, int priority, Converter> converter,
Map converters) {
// add the converter only if it has a higher priority than another converter for the same type
ConverterWithPriority oldConverter = converters.get(type);
if (oldConverter == null || priority > oldConverter.priority) {
converters.put(type, new ConverterWithPriority(converter, priority));
}
}
private static int getPriority(Converter> converter) {
int priority = 100;
Priority priorityAnnotation = converter.getClass().getAnnotation(Priority.class);
if (priorityAnnotation != null) {
priority = priorityAnnotation.value();
}
return priority;
}
protected List getSources() {
return sources;
}
@Deprecated
Function getSourceWrappers() {
return sourceWrappers;
}
protected Map getConverters() {
return converters;
}
List getInterceptors() {
return interceptors;
}
KeyMap getDefaultValues() {
return defaultValues;
}
protected boolean isAddDefaultSources() {
return addDefaultSources;
}
boolean isAddDefaultInterceptors() {
return addDefaultInterceptors;
}
protected boolean isAddDiscoveredSources() {
return addDiscoveredSources;
}
protected boolean isAddDiscoveredConverters() {
return addDiscoveredConverters;
}
boolean isAddDiscoveredInterceptors() {
return addDiscoveredInterceptors;
}
@Override
public SmallRyeConfig build() {
ConfigMappingProvider mappingProvider = mappingsBuilder.build();
KeyMap mappingProviderDefaultValues = mappingProvider.getDefaultValues();
for (Map.Entry> entry : mappingProviderDefaultValues.entrySet()) {
defaultValues.putIfAbsent(entry.getKey(), entry.getValue());
}
try {
ConfigMappings configMappings = new ConfigMappings();
SmallRyeConfig config = new SmallRyeConfig(this, configMappings);
mappingProvider.mapConfiguration(config);
return config;
} catch (ConfigValidationException e) {
throw new IllegalStateException(e);
}
}
static class ConverterWithPriority {
private final Converter> converter;
private final int priority;
private ConverterWithPriority(Converter> converter, int priority) {
this.converter = converter;
this.priority = priority;
}
Converter> getConverter() {
return converter;
}
}
static class InterceptorWithPriority {
private static final OptionalInt OPTIONAL_DEFAULT_PRIORITY = OptionalInt
.of(ConfigSourceInterceptorFactory.DEFAULT_PRIORITY);
private final ConfigSourceInterceptorFactory factory;
private final int priority;
private InterceptorWithPriority(ConfigSourceInterceptor interceptor) {
this(new ConfigSourceInterceptorFactory() {
@Override
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
return interceptor;
}
@Override
public OptionalInt getPriority() {
final OptionalInt priority = ConfigSourceInterceptorFactory.super.getPriority();
if (priority.isPresent()) {
return priority;
}
final Priority priorityAnnotation = interceptor.getClass().getAnnotation(Priority.class);
return priorityAnnotation != null ? OptionalInt.of(priorityAnnotation.value()) : OPTIONAL_DEFAULT_PRIORITY;
}
});
}
private InterceptorWithPriority(ConfigSourceInterceptorFactory factory) {
this.factory = factory;
this.priority = factory.getPriority().orElse(ConfigSourceInterceptorFactory.DEFAULT_PRIORITY);
}
ConfigSourceInterceptor getInterceptor(ConfigSourceInterceptorContext context) {
return factory.getInterceptor(context);
}
int getPriority() {
return priority;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy