Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2020, 2023 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.mp;
import java.lang.System.Logger.Level;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.helidon.config.mp.spi.MpConfigFilter;
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;
/**
* Implementation of the basic MicroProfile {@link org.eclipse.microprofile.config.Config} API.
*/
class MpConfigImpl implements Config {
private static final System.Logger LOGGER = System.getLogger(MpConfigImpl.class.getName());
// for references resolving
// matches string between ${ } with a negative lookbehind if there is not backslash
private static final String REGEX_REFERENCE = "(?> UNRESOLVED_KEYS = ThreadLocal.withInitial(HashSet::new);
private static final Pattern SPLIT_PATTERN = Pattern.compile("(?, Class>> REPLACED_TYPES = new HashMap<>();
static {
REPLACED_TYPES.put(Byte.TYPE, Byte.class);
REPLACED_TYPES.put(Short.TYPE, Short.class);
REPLACED_TYPES.put(Integer.TYPE, Integer.class);
REPLACED_TYPES.put(Long.TYPE, Long.class);
REPLACED_TYPES.put(Float.TYPE, Float.class);
REPLACED_TYPES.put(Double.TYPE, Double.class);
REPLACED_TYPES.put(Boolean.TYPE, Boolean.class);
REPLACED_TYPES.put(Character.TYPE, Character.class);
}
private final List sources = new LinkedList<>();
private final HashMap, Converter>> converters = new LinkedHashMap<>();
private final boolean valueResolving;
private final List filters = new ArrayList<>();
private final String configProfile;
MpConfigImpl(List sources,
HashMap, Converter>> converters,
List filters,
String profile) {
this.sources.addAll(sources);
this.converters.putAll(converters);
this.converters.putIfAbsent(String.class, value -> value);
this.configProfile = profile;
this.valueResolving = getOptionalValue("mp.config.property.expressions.enabled", Boolean.class)
.or(() -> getOptionalValue("helidon.config.value-resolving.enabled", Boolean.class))
.orElse(true);
// we need to initialize the filters first, before we set up filters
filters.forEach(it -> {
// initialize filter with filters with higher priority already in place
it.init(this);
// and then add it to the list of active filters
// do not do this first, as we would end up in using an uninitialized filter
this.filters.add(it);
});
}
@Override
public ConfigValue getConfigValue(String key) {
if (configProfile == null) {
return findConfigValue(key)
.orElseGet(() -> new ConfigValueImpl(key, null, null, null, 0));
}
return findConfigValue("%" + configProfile + "." + key)
.or(() -> findConfigValue(key))
.orElseGet(() -> new ConfigValueImpl(key, null, null, null, 0));
}
@Override
public T getValue(String propertyName, Class propertyType) {
return getOptionalValue(propertyName, propertyType)
.orElseThrow(() -> new NoSuchElementException("Property \"" + propertyName + "\" is not available in "
+ "configuration"));
}
@SuppressWarnings("unchecked")
@Override
public Optional getOptionalValue(String propertyName, Class propertyType) {
if (configProfile == null) {
return optionalValue(propertyName, propertyType);
}
return optionalValue("%" + configProfile + "." + propertyName, propertyType)
.or(() -> optionalValue(propertyName, propertyType));
}
@SuppressWarnings("unchecked")
private Optional optionalValue(String propertyName, Class propertyType) {
// let's resolve arrays
if (propertyType.isArray()) {
Class> componentType = propertyType.getComponentType();
// first try to see if we have a direct value
Optional optionalValue = getOptionalValue(propertyName, String.class);
if (optionalValue.isPresent()) {
try {
return Optional.of((T) toArray(propertyName, optionalValue.get(), componentType));
} catch (NoSuchElementException e) {
return Optional.empty();
}
}
/*
we also support indexed value
e.g. for key "my.list" you can have both:
my.list=12,13,14
or (not and):
my.list.0=12
my.list.1=13
*/
String indexedConfigKey = propertyName + ".0";
optionalValue = getOptionalValue(indexedConfigKey, String.class);
if (optionalValue.isPresent()) {
List