All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.config.MetaConfig Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
/*
 * Copyright (c) 2019, 2020 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.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Function;
import java.util.logging.Logger;

import io.helidon.common.serviceloader.HelidonServiceLoader;
import io.helidon.config.spi.ChangeWatcher;
import io.helidon.config.spi.ConfigParser;
import io.helidon.config.spi.ConfigSource;
import io.helidon.config.spi.OverrideSource;
import io.helidon.config.spi.PollingStrategy;
import io.helidon.config.spi.RetryPolicy;

/**
 * Meta configuration.
 * 

* Configuration allows configuring itself using meta configuration. * Config looks for {@code meta-config.*} files in the current directory and on the classpath, where the {@code *} is * one of the supported media type suffixes (such as {@code yaml} when {@code helidon-config-yaml} module is on the classpath). *

* Meta configuration can define which config sources to load, including possible retry policy, polling strategy and change * watchers. *

* Example of a YAML meta configuration file: *

 * sources:
 *   - type: "environment-variables"
 *   - type: "system-properties"
 *   - type: "file"
 *     properties:
 *       path: "conf/dev.yaml"
 *       optional: true
 *   - type: "file"
 *     properties:
 *       path: "conf/config.yaml"
 *       optional: true
 *   - type: "classpath"
 *     properties:
 *       resource: "default.yaml"
 * 
* This configuration would load the following config sources (in the order specified): *
    *
  • Environment variables config source *
  • System properties config source
  • *
  • File config source from file {@code conf/dev.yaml} that is optional
  • *
  • File config source from file {@code conf/config.yaml} that is optional
  • *
  • Classpath resource config source for resource {@code default.yaml} that is mandatory
  • *
*/ public final class MetaConfig { private static final Logger LOGGER = Logger.getLogger(MetaConfig.class.getName()); private MetaConfig() { } /** * Create configuration from meta configuration (files or classpath resources), or create a default config instance * if meta configuration is not present. * * @return a config instance */ public static Config config() { return metaConfig().map(MetaConfig::config) // if not found, create a default instance .orElseGet(MetaConfig::createDefault); } /** * Create configuration from provided meta configuration. * * @param metaConfig meta configuration * @return a new config instance built from meta configuration */ public static Config config(Config metaConfig) { return Config.builder() .config(metaConfig) .build(); } /** * Find meta configuration (files or classpath resources) and create a meta configuration instance from it. * * @return meta configuration if present, or empty */ public static Optional metaConfig() { return MetaConfigFinder.findMetaConfig(supportedMediaTypes()); } /** * Load a polling strategy based on its meta configuration. * * @param metaConfig meta configuration of a polling strategy * @return a polling strategy instance */ public static PollingStrategy pollingStrategy(Config metaConfig) { return MetaProviders.pollingStrategy(metaConfig.get("type").asString().get(), metaConfig.get("properties")); } /** * Load a change watcher based on its meta configuration. * * @param metaConfig meta configuration of a change watcher * @return a change watcher instance */ public static ChangeWatcher changeWatcher(Config metaConfig) { String type = metaConfig.get("type").asString().get(); ChangeWatcher changeWatcher = MetaProviders.changeWatcher(type, metaConfig.get("properties")); LOGGER.fine(() -> "Loaded change watcher of type \"" + type + "\", class: " + changeWatcher.getClass().getName()); return changeWatcher; } /** * Load a retry policy based on its meta configuration. * * @param metaConfig meta configuration of retry policy * @return retry policy instance */ public static RetryPolicy retryPolicy(Config metaConfig) { String type = metaConfig.get("type").asString().get(); RetryPolicy retryPolicy = MetaProviders.retryPolicy(type, metaConfig.get("properties")); LOGGER.fine(() -> "Loaded retry policy of type \"" + type + "\", class: " + retryPolicy.getClass().getName()); return retryPolicy; } /** * 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 * @param sourceMetaConfig meta configuration of a config source * @return config source instance * @see Config.Builder#config(Config) */ public static List configSource(Config sourceMetaConfig) { String type = sourceMetaConfig.get("type").asString().get(); boolean multiSource = sourceMetaConfig.get("multi-source").asBoolean().orElse(false); Config sourceProperties = sourceMetaConfig.get("properties"); if (multiSource) { List sources = MetaProviders.configSources(type, sourceProperties); LOGGER.fine(() -> "Loaded sources of type \"" + type + "\", values: " + sources); return sources; } else { ConfigSource source = MetaProviders.configSource(type, sourceProperties); LOGGER.fine(() -> "Loaded source of type \"" + type + "\", class: " + source.getClass().getName()); return List.of(source); } } // override config source static OverrideSource overrideSource(Config sourceMetaConfig) { String type = sourceMetaConfig.get("type").asString().get(); OverrideSource source = MetaProviders.overrideSource(type, sourceMetaConfig.get("properties")); LOGGER.fine(() -> "Loaded override source of type \"" + type + "\", class: " + source.getClass().getName()); return source; } static List configSources(Config metaConfig) { List configSources = new LinkedList<>(); metaConfig.get("sources") .asNodeList() .ifPresent(list -> list.forEach(it -> configSources.addAll(MetaConfig.configSource(it)))); return configSources; } // only interested in config source static List configSources(Function supportedMediaType) { Optional metaConfigOpt = metaConfig(); return metaConfigOpt .map(MetaConfig::configSources) .orElseGet(() -> MetaConfigFinder.findConfigSource(supportedMediaType) .map(List::of) .orElseGet(List::of)); } private static Function supportedMediaTypes() { Set supportedMediaTypes = new HashSet<>(); HelidonServiceLoader.create(ServiceLoader.load(ConfigParser.class)) .forEach(parser -> supportedMediaTypes.addAll(parser.supportedMediaTypes())); return supportedMediaTypes::contains; } private static Config createDefault() { // use defaults Config.Builder builder = Config.builder(); MetaConfigFinder.findConfigSource(supportedMediaTypes()).ifPresent(builder::addSource); return builder.build(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy