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

org.apache.deltaspike.core.api.config.ConfigResolver Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 org.apache.deltaspike.core.api.config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.inject.Typed;

import org.apache.deltaspike.core.api.projectstage.ProjectStage;
import org.apache.deltaspike.core.spi.config.ConfigFilter;
import org.apache.deltaspike.core.spi.config.ConfigSource;
import org.apache.deltaspike.core.spi.config.ConfigSourceProvider;
import org.apache.deltaspike.core.util.ClassUtils;
import org.apache.deltaspike.core.util.ProjectStageProducer;
import org.apache.deltaspike.core.util.ServiceUtils;

/**
 * 

Resolve the configuration via their well defined ordinals.

* *

You can provide your own lookup paths by implementing * and registering additional {@link PropertyFileConfig} or * {@link ConfigSource} or {@link ConfigSourceProvider} implementations.

*/ @Typed() public final class ConfigResolver { private static final Logger LOG = Logger.getLogger(ConfigResolver.class.getName()); /** * The content of this map will get lazily initiated and will hold the * sorted List of ConfigSources for each WebApp/EAR, etc (thus the * ClassLoader). */ private static Map configSources = new ConcurrentHashMap(); /** * The content of this map will hold the List of ConfigFilters * for each WebApp/EAR, etc (thus the ClassLoader). */ private static Map> configFilters = new ConcurrentHashMap>(); private static volatile ProjectStage projectStage = null; private ConfigResolver() { // this is a utility class which doesn't get instantiated. } /** * This method can be used for programmatically adding {@link ConfigSource}s. * It is not needed for normal 'usage' by end users, but only for Extension Developers! * * @param configSourcesToAdd the ConfigSources to add */ public static synchronized void addConfigSources(List configSourcesToAdd) { // we first pickup all pre-configured ConfigSources... getConfigSources(); // and now we can easily add our own ClassLoader currentClassLoader = ClassUtils.getClassLoader(null); ConfigSource[] configuredConfigSources = configSources.get(currentClassLoader); List allConfigSources = new ArrayList(); allConfigSources.addAll(Arrays.asList(configuredConfigSources)); allConfigSources.addAll(configSourcesToAdd); // finally put all the configSources back into the map configSources.put(currentClassLoader, sortDescending(allConfigSources)); } /** * Clear all ConfigSources for the current ClassLoader */ public static synchronized void freeConfigSources() { configSources.remove(ClassUtils.getClassLoader(null)); } /** * Add a {@link ConfigFilter} to the ConfigResolver. * This will only affect the current WebApp * (or more precisely the current ClassLoader and it's children). * @param configFilter */ public static void addConfigFilter(ConfigFilter configFilter) { List currentConfigFilters = getConfigFilters(); currentConfigFilters.add(configFilter); } /** * @return the {@link ConfigFilter}s for the current application. */ public static List getConfigFilters() { ClassLoader cl = ClassUtils.getClassLoader(null); List currentConfigFilters = configFilters.get(cl); if (currentConfigFilters == null) { currentConfigFilters = new ArrayList(); configFilters.put(cl, currentConfigFilters); } return currentConfigFilters; } /** * Resolve the property value by going through the list of configured {@link ConfigSource}s * and use the one with the highest priority. If no configured value has been found that * way we will use the defaultValue. * * @param key the property key. * @param defaultValue will be used if no configured value for the key could be found. * @return the configured property value from the {@link ConfigSource} with the highest ordinal or * the defaultValue if there is no value explicitly configured. */ public static String getPropertyValue(String key, String defaultValue) { String value = getPropertyValue(key); return fallbackToDefaultIfEmpty(key, value, defaultValue); } /** * Resolve the property value by going through the list of configured {@link ConfigSource}s * and use the one with the highest priority. * * @param key the property key. * @return the configured property value from the {@link ConfigSource} with the highest ordinal or * null if there is no configured value for it. */ public static String getPropertyValue(String key) { ConfigSource[] appConfigSources = getConfigSources(); String value; for (ConfigSource configSource : appConfigSources) { value = configSource.getPropertyValue(key); if (value != null) { LOG.log(Level.FINE, "found value {0} for key {1} in ConfigSource {2}.", new Object[]{filterConfigValueForLog(key, value), key, configSource.getConfigName()}); return filterConfigValue(key, value); } LOG.log(Level.FINER, "NO value found for key {0} in ConfigSource {1}.", new Object[]{key, configSource.getConfigName()}); } return null; } /** *

Search for the configured value in all {@link ConfigSource}s and take the * current {@link org.apache.deltaspike.core.api.projectstage.ProjectStage} * into account.

* *

It first will search if there is a configured value of the given key prefixed * with the current ProjectStage (e.g. 'myproject.myconfig.Production') and if this didn't * find anything it will lookup the given key without any prefix.

* *

Attention This method must only be used after all ConfigSources * got registered and it also must not be used to determine the ProjectStage itself.

* @param key * @return the configured value or if non found the defaultValue * */ public static String getProjectStageAwarePropertyValue(String key) { ProjectStage ps = getProjectStage(); String value = getPropertyValue(key + '.' + ps); if (value == null) { value = getPropertyValue(key); } return value; } /** * {@link #getProjectStageAwarePropertyValue(String)} which returns the defaultValue * if the property is null or empty. * @param key * @param defaultValue * @return the configured value or if non found the defaultValue * */ public static String getProjectStageAwarePropertyValue(String key, String defaultValue) { String value = getProjectStageAwarePropertyValue(key); return fallbackToDefaultIfEmpty(key, value, defaultValue); } /** *

Search for the configured value in all {@link ConfigSource}s and take the * current {@link org.apache.deltaspike.core.api.projectstage.ProjectStage} * and the value configured for the given property into account.

* *

The first step is to resolve the value of the given property. This will * take the current ProjectStage into account. E.g. given the property is 'dbvendor' * and the ProjectStage is 'UnitTest', the first lookup is *

  • 'dbvendor.UnitTest'
. * If this value is not found then we will do a 2nd lookup for *
  • 'dbvendor'

* *

If a value was found for the given property (e.g. dbvendor = 'mysql' * then we will use this value to lookup in the following order until we * found a non-null value. If there was no value found for the property * we will only do the key+ProjectStage and key lookup. * In the following sample 'dataSource' is used as key parameter: * *

    *
  • 'datasource.mysql.UnitTest'
  • *
  • 'datasource.mysql'
  • *
  • 'datasource.UnitTest'
  • *
  • 'datasource'
  • *
*

* * *

Attention This method must only be used after all ConfigSources * got registered and it also must not be used to determine the ProjectStage itself.

* @param key * @param property the property to look up first * @return the configured value or if non found the defaultValue * */ public static String getPropertyAwarePropertyValue(String key, String property) { String propertyValue = getProjectStageAwarePropertyValue(property); String value = null; if (propertyValue != null && propertyValue.length() > 0) { value = getProjectStageAwarePropertyValue(key + '.' + propertyValue); } if (value == null) { value = getProjectStageAwarePropertyValue(key); } return value; } /* *

Attention This method must only be used after all ConfigSources * got registered and it also must not be used to determine the ProjectStage itself.

* @param key * @param property the property to look up first * @param defaultValue * @return the configured value or if non found the defaultValue * */ public static String getPropertyAwarePropertyValue(String key, String property, String defaultValue) { String value = getPropertyAwarePropertyValue(key, property); return fallbackToDefaultIfEmpty(key, value, defaultValue); } /** * Resolve all values for the given key, from all registered ConfigSources ordered by their * ordinal value in ascending ways. If more {@link ConfigSource}s have the same ordinal, their * order is undefined. * * @param key under which configuration is stored * @return List with all found property values, sorted in ascending order of their ordinal. * @see org.apache.deltaspike.core.spi.config.ConfigSource#getOrdinal() */ public static List getAllPropertyValues(String key) { List appConfigSources = sortAscending(new ArrayList(Arrays.asList(getConfigSources()))); List result = new ArrayList(); String value; for (ConfigSource configSource : appConfigSources) { value = configSource.getPropertyValue(key); if (value != null) { value = filterConfigValue(key, value); if (!result.contains(value)) { result.add(value); } } } return result; } public static Map getAllProperties() { List appConfigSources = sortAscending(new ArrayList(Arrays.asList(getConfigSources()))); Map result = new HashMap(); for (ConfigSource configSource : appConfigSources) { if (configSource.isScannable()) { result.putAll(configSource.getProperties()); } } return Collections.unmodifiableMap(result); } private static synchronized ConfigSource[] getConfigSources() { ClassLoader currentClassLoader = ClassUtils.getClassLoader(null); ConfigSource[] appConfigSources = configSources.get(currentClassLoader); if (appConfigSources == null) { appConfigSources = sortDescending(resolveConfigSources()); if (LOG.isLoggable(Level.FINE)) { for (ConfigSource cs : appConfigSources) { LOG.log(Level.FINE, "Adding ordinal {0} ConfigSource {1}", new Object[]{cs.getOrdinal(), cs.getConfigName()}); } } configSources.put(currentClassLoader, appConfigSources); } return appConfigSources; } private static List resolveConfigSources() { List appConfigSources = ServiceUtils.loadServiceImplementations(ConfigSource.class); List configSourceProviderServiceLoader = ServiceUtils.loadServiceImplementations(ConfigSourceProvider.class); for (ConfigSourceProvider configSourceProvider : configSourceProviderServiceLoader) { appConfigSources.addAll(configSourceProvider.getConfigSources()); } return appConfigSources; } private static ConfigSource[] sortDescending(List configSources) { Collections.sort(configSources, new Comparator() { /** * {@inheritDoc} */ @Override public int compare(ConfigSource configSource1, ConfigSource configSource2) { return (configSource1.getOrdinal() > configSource2.getOrdinal()) ? -1 : 1; } }); return configSources.toArray(new ConfigSource[configSources.size()]); } private static List sortAscending(List configSources) { Collections.sort(configSources, new Comparator() { /** * {@inheritDoc} */ @Override public int compare(ConfigSource configSource1, ConfigSource configSource2) { return (configSource1.getOrdinal() > configSource2.getOrdinal()) ? 1 : -1; } }); return configSources; } private static ProjectStage getProjectStage() { if (projectStage == null) { synchronized (ConfigResolver.class) { projectStage = ProjectStageProducer.getInstance().getProjectStage(); } } return projectStage; } private static String fallbackToDefaultIfEmpty(String key, String value, String defaultValue) { if (value == null || value.length() == 0) { LOG.log(Level.FINE, "no configured value found for key {0}, using default value {1}.", new Object[]{key, defaultValue}); return defaultValue; } return value; } private static String filterConfigValue(String key, String value) { List currentConfigFilters = getConfigFilters(); String filteredValue = value; for (ConfigFilter filter : currentConfigFilters) { filteredValue = filter.filterValue(key, filteredValue); } return filteredValue; } private static String filterConfigValueForLog(String key, String value) { List currentConfigFilters = getConfigFilters(); String logValue = value; for (ConfigFilter filter : currentConfigFilters) { logValue = filter.filterValueForLog(key, logValue); } return logValue; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy