tamaya-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anat...@apache.org
Subject [6/6] incubator-tamaya git commit: Added full JSR implementation.
Date Sun, 17 Dec 2017 08:00:34 GMT
Added full JSR implementation.

Signed-off-by: Anatole Tresch <anatole@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/063f8ada
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/063f8ada
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/063f8ada

Branch: refs/heads/configjsr
Commit: 063f8adadaaa8ecb650c9f5195ac94ff6d8fae95
Parents: a31af00
Author: Anatole Tresch <anatole@apache.org>
Authored: Sun Dec 17 09:00:16 2017 +0100
Committer: Anatole Tresch <anatole@apache.org>
Committed: Sun Dec 17 09:00:16 2017 +0100

----------------------------------------------------------------------
 .../org/apache/tamaya/base/DefaultConfig.java   | 165 +++++
 .../tamaya/base/DefaultConfigBuilder.java       | 305 +++++++++
 .../tamaya/base/DefaultServiceContext.java      | 225 +++++++
 .../tamaya/base/PriorityServiceComparator.java  |  84 +++
 .../org/apache/tamaya/base/ReflectionUtil.java  |  42 ++
 .../base/configsource/BaseConfigSource.java     | 170 +++++
 .../configsource/BuildableConfigSource.java     | 208 ++++++
 .../BuildableConfigSourceProvider.java          | 113 ++++
 .../base/configsource/CLIConfigSource.java      | 130 ++++
 .../configsource/ConfigSourceComparator.java    | 117 ++++
 .../base/configsource/ConfigSourceManager.java  | 375 +++++++++++
 .../configsource/EnvironmentConfigSource.java   | 281 +++++++++
 .../JavaConfigurationConfigSource.java          | 131 ++++
 .../base/configsource/MapConfigSource.java      |  98 +++
 .../PropertiesResourceConfigSource.java         | 109 ++++
 .../base/configsource/SimpleConfigSource.java   | 282 +++++++++
 .../base/configsource/SystemConfigSource.java   | 186 ++++++
 .../base/configsource/WrappedConfigSource.java  | 117 ++++
 .../tamaya/base/configsource/package-info.java  |  23 +
 .../tamaya/base/convert/ConversionContext.java  | 253 ++++++++
 .../tamaya/base/convert/ConverterManager.java   | 630 +++++++++++++++++++
 .../tamaya/base/convert/EnumConverter.java      |  81 +++
 .../tamaya/base/convert/package-info.java       |  23 +
 .../tamaya/base/filter/FilterComparator.java    |  72 +++
 .../tamaya/base/filter/FilterContext.java       | 144 +++++
 .../tamaya/base/filter/FilterManager.java       | 273 ++++++++
 .../apache/tamaya/base/filter/package-info.java |  23 +
 .../org/apache/tamaya/base/package-info.java    |  23 +
 .../org/apache/tamaya/spi/ConfigContext.java    | 154 +++++
 .../java/org/apache/tamaya/spi/ConfigValue.java | 209 ++++++
 .../apache/tamaya/spi/ConfigValueBuilder.java   | 179 ++++++
 .../org/apache/tamaya/spi/Experimental.java     |  32 +
 .../main/java/org/apache/tamaya/spi/Filter.java |  50 ++
 .../org/apache/tamaya/spi/ServiceContext.java   | 147 +++++
 .../tamaya/spi/ServiceContextManager.java       | 118 ++++
 .../spi/StandaloneConfigContextBuilder.java     | 407 ++++++++++++
 .../apache/tamaya/spi/TamayaConfigBuilder.java  | 333 ++++++++++
 .../java/org/apache/tamaya/spi/TypeLiteral.java | 225 +++++++
 .../org/apache/tamaya/spi/package-info.java     |  23 +
 .../tamaya/base/DefaultConfigBuilderTest.java   | 198 ++++++
 .../apache/tamaya/base/DefaultConfigTest.java   | 130 ++++
 .../tamaya/base/DefaultServiceContextTest.java  | 137 ++++
 .../base/PriorityServiceComparatorTest.java     |  45 ++
 .../tamaya/base/TestConfigurationProvider.java  |  82 +++
 .../base/configsource/BaseConfigSourceTest.java | 124 ++++
 .../BuildableConfigSourceProviderTest.java      |  78 +++
 .../configsource/BuildableConfigSourceTest.java |  89 +++
 .../configsource/CLIPropertySourceTest.java     |  59 ++
 .../base/configsource/EnumConverterTest.java    |  63 ++
 .../EnvironmentPropertySourceTest.java          |  62 ++
 .../JavaConfigurationProviderTest.java          |  46 ++
 .../configsource/MapPropertySourceTest.java     |  76 +++
 .../PropertiesFilePropertySourceTest.java       |  60 ++
 .../configsource/SimplePropertySourceTest.java  |  88 +++
 .../configsource/SystemPropertySourceTest.java  |  92 +++
 .../configsource/TestConfigDefaultSource.java   |  52 ++
 .../java/org/apache/tamaya/base/convert/A.java  |  29 +
 .../java/org/apache/tamaya/base/convert/B.java  |  29 +
 .../java/org/apache/tamaya/base/convert/C.java  |  56 ++
 .../tamaya/base/convert/CTestConverter.java     |  31 +
 .../base/convert/ConverterManagerTest.java      | 184 ++++++
 .../tamaya/base/convert/EnumConverterTest.java  |  53 ++
 .../base/services/DefaultServiceContext.java    | 204 ++++++
 .../tamaya/filter/FilterComparatorTest.java     |  75 +++
 .../resources/META-INF/javaconfig.properties    |  22 +
 .../src/test/resources/META-INF/javaconfig.xml  |  25 +
 .../javax.config.spi.ConfigProviderResolver     |  18 +
 .../services/javax.config.spi.Converter         |  19 +
 ...tServiceContextTest$InvalidPriorityInterface |  18 +
 ...efaultServiceContextTest$MultiImplsInterface |  20 +
 .../org.apache.tamaya.spi.ServiceContext        |  19 +
 .../src/test/resources/invalid-properties.xml   |  25 +
 .../src/test/resources/non-xml-properties.xml   |  18 +
 .../test/resources/overrideOrdinal.properties   |  25 +
 .../base/src/test/resources/testfile.properties |  22 +
 .../src/test/resources/valid-properties.xml     |  25 +
 .../examples/customconfigsource/Main.java       |  91 +++
 .../customconfigsource/SimpleConfigSource.java  |  65 ++
 .../SimpleConfigSourceProvider.java             |  49 ++
 .../customconfigsource/package-info.java        |  19 +
 .../examples/custompropertysource/Main.java     |  91 ---
 .../SimpleConfigSource.java                     |  64 --
 .../SimplePropertySourceProvider.java           |  49 --
 .../custompropertysource/package-info.java      |  19 -
 .../services/javax.config.spi.ConfigSource      |  19 +
 .../javax.config.spi.ConfigSourceProvider       |  19 +
 .../org.apache.tamaya.spi.PropertySource        |  19 -
 ...org.apache.tamaya.spi.PropertySourceProvider |  19 -
 88 files changed, 9220 insertions(+), 261 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java
new file mode 100644
index 0000000..a3762f1
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java
@@ -0,0 +1,165 @@
+/*
+ * 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.tamaya.base;
+
+
+import org.apache.tamaya.base.configsource.ConfigSourceManager;
+import org.apache.tamaya.base.convert.ConverterManager;
+import org.apache.tamaya.spi.ConfigValue;
+import org.apache.tamaya.spi.Filter;
+import org.apache.tamaya.base.filter.FilterManager;
+import org.apache.tamaya.spi.*;
+
+import javax.config.Config;
+import javax.config.spi.ConfigSource;
+import javax.config.spi.Converter;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of the Configuration API.
+ */
+public class DefaultConfig implements Config, ConfigContextSupplier {
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = Logger.getLogger(DefaultConfig.class.getName());
+
+    /**
+     * The current {@link ConverterManager} of the current instance.
+     */
+    private final ConverterManager converterManager = new ConverterManager();
+
+    /**
+     * The current {@link ConverterManager} of the current instance.
+     */
+    private final FilterManager filterManager = new FilterManager();
+
+    /**
+     * The current {@link ConfigSourceManager} of the current instance.
+     */
+    private final ConfigSourceManager configSourceManager = new ConfigSourceManager();
+
+
+    /**
+     * Constructor.
+     * @param configContext The configuration Context to be used.
+     */
+    public DefaultConfig(ConfigContext configContext){
+        this.configSourceManager.addSources(configContext.getSources());
+        this.configSourceManager.setConfigValueCombinationPolicy(configContext.getConfigValueCombinationPolicy());
+        configContext.getConverters().forEach((t,c) -> this.converterManager.addConverter(t, Collection.class.cast(c)));
+        this.filterManager.addFilter(configContext.getFilters());
+    }
+
+    /**
+     * Accesses the current String value for the given key and tries to convert it
+     * using the {@link javax.config.spi.Converter} instances provided by the current
+     * {@link ConfigContext}.
+     *
+     * @param key  the property's absolute, or relative path, e.g. @code
+     *             a/b/c/d.myProperty}, never {@code null}.
+     * @param targetType The target type required, not {@code null}.
+     * @param <T>  the value type
+     * @return the converted value, never {@code null}.
+     */
+    @Override
+    public <T> T getValue(String key, Class<T> targetType) {
+        Objects.requireNonNull(key, "Key must not be null.");
+        Objects.requireNonNull(targetType, "Target type must not be null.");
+
+        ConfigValue value = configSourceManager.evaluteRawValue(key);
+        if(value==null || value.getValue()==null){
+            return null;
+        }
+        value = filterManager.filterValue(value, this);
+        if(value!=null){
+            return (T)converterManager.convertValue(key, value.getValue(), targetType, this);
+        }
+        return null;
+    }
+
+
+    @Override
+    public <T> Optional<T> getOptionalValue(String key, Class<T> type) {
+        Objects.requireNonNull(key, "Key must not be null.");
+        Objects.requireNonNull(type, "Type must not be null.");
+        T val = getValue(key, type);
+        return Optional.ofNullable(val);
+    }
+
+    /**
+     * Get the current properties, composed by the loaded {@link ConfigSource} and filtered
+     * by registered {@link Filter}.
+     *
+     * @return the final properties.
+     */
+    @Override
+    public Set<String> getPropertyNames() {
+        Map<String, ConfigValue> filtered = configSourceManager.evaluateRawValues();
+        return filtered.keySet();
+    }
+
+    @Override
+    public Iterable<ConfigSource> getConfigSources() {
+        return configSourceManager.getSources();
+    }
+
+
+    public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
+        Objects.requireNonNull(key);
+        Objects.requireNonNull(type);
+
+        Optional<T> val = getOptionalValue(key, type);
+        return val.orElse(defaultValue);
+    }
+
+    @Override
+    public ConfigContext getConfigContext() {
+        return new ConfigContext() {
+            @Override
+            public List<ConfigSource> getSources() {
+                return configSourceManager.getSources();
+            }
+
+            @Override
+            public List<Filter> getFilters() {
+                return filterManager.getFilters();
+            }
+
+            @Override
+            public Map<Type, List<Converter>> getConverters() {
+                return converterManager.getConverters();
+            }
+        };
+    }
+
+
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder("Configuration{\n")
+            .append(this.configSourceManager).append('\n')
+            .append(this.filterManager).append('\n')
+            .append(this.converterManager).append('\n')
+            .append('}');
+        return b.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java
new file mode 100644
index 0000000..2eb851a
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java
@@ -0,0 +1,305 @@
+/*
+ * 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.tamaya.base;
+
+import org.apache.tamaya.base.configsource.*;
+import org.apache.tamaya.base.convert.ConverterManager;
+import org.apache.tamaya.base.filter.FilterManager;
+import org.apache.tamaya.spi.TamayaConfigBuilder;
+import org.apache.tamaya.spi.*;
+import org.apache.tamaya.spi.Filter;
+
+import javax.config.Config;
+import javax.config.spi.ConfigSource;
+import javax.config.spi.Converter;
+import java.lang.reflect.Type;
+import java.util.*;
+
+/**
+ * Default implementation of {@link TamayaConfigBuilder}.
+ */
+public class DefaultConfigBuilder implements TamayaConfigBuilder {
+
+    protected final ConfigSourceManager configSourceManager = new ConfigSourceManager();
+    protected final ConverterManager converterManager = new ConverterManager();
+    protected final FilterManager filterManager = new FilterManager();
+
+    /**
+     * Creates a new builder instance.
+     */
+    public DefaultConfigBuilder() {
+    }
+
+    /**
+     * Creates a new builder instance.
+     */
+    public DefaultConfigBuilder(ConfigContext context) {
+        this.configSourceManager.addSources(context.getSources());
+        this.configSourceManager.setConfigValueCombinationPolicy(context.getConfigValueCombinationPolicy());
+        this.filterManager.addFilter(context.getFilters());
+        context.getConverters().forEach((t,c) -> converterManager.addConverter(t, Collection.class.cast(c)));
+    }
+
+    /**
+     * Creates a new builder instance initializing it with the given context.
+     * @param contextSupplier the context supplier to be used, not null.
+     */
+    public DefaultConfigBuilder(ConfigContextSupplier contextSupplier) {
+        this(((ConfigContextSupplier)contextSupplier).getConfigContext());
+    }
+
+//    /**
+//     * Allows to set configuration context during unit tests.
+//     */
+//    @Override
+//    public TamayaConfigBuilder setConfiguration(Config configuration) {
+//        this.contextBuilder.withContext(((DefaultConfig)configuration).getConfigContext());
+//        return this;
+//    }
+
+
+    @Override
+    public TamayaConfigBuilder withSources(ConfigSource... sources){
+        this.configSourceManager.addSources(sources);
+        return this;
+    }
+
+    @Override
+    public <T> TamayaConfigBuilder withConverter(Class<T> type, Converter<T> converter) {
+        this.converterManager.addConverter(type, converter);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder withConverters(Converter<?>... converters) {
+        this.converterManager.addConverters(converters);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder withConverters(Collection<Converter<?>> converters) {
+        this.converterManager.addConverters(Collection.class.cast(converters));
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder withSources(Collection<ConfigSource> sources){
+        this.configSourceManager.addSources(sources);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder addDiscoveredFilters() {
+        this.filterManager.addDefaultFilters();
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder addDefaultSources() {
+        this.configSourceManager.addSources(
+                new EnvironmentConfigSource(),
+                new JavaConfigurationConfigSource(),
+                new CLIConfigSource(),
+                new SystemConfigSource());
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder addDiscoveredSources() {
+        this.configSourceManager.addDiscoveredSources();
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder addDiscoveredConverters() {
+        this.converterManager.addDiscoveredConverters();
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder forClassLoader(ClassLoader loader) {
+        this.configSourceManager.setClassloader(loader);
+        this.filterManager.setClassloader(loader);
+        this.converterManager.setClassloader(loader);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder removeSources(ConfigSource... propertySources) {
+        this.configSourceManager.removeSources(propertySources);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder removeSources(Collection<ConfigSource> propertySources) {
+        this.configSourceManager.removeSources(propertySources);
+        return this;
+    }
+
+    @Override
+    public List<ConfigSource> getSources() {
+        return this.configSourceManager.getSources();
+    }
+
+    @Override
+    public TamayaConfigBuilder increasePriority(ConfigSource propertySource) {
+        this.configSourceManager.increasePriority(propertySource);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder decreasePriority(ConfigSource propertySource) {
+        this.configSourceManager.decreasePriority(propertySource);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder highestPriority(ConfigSource propertySource) {
+        this.configSourceManager.highestPriority(propertySource);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder lowestPriority(ConfigSource propertySource) {
+        this.configSourceManager.lowestPriority(propertySource);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder withFilters(Filter... filters){
+        this.filterManager.addFilter(filters);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder withFilters(Collection<Filter> filters){
+        this.filterManager.addFilter(filters);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder removeFilters(Filter... filters) {
+        this.filterManager.removeFilters(filters);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder removeFilters(Collection<Filter> filters) {
+        this.filterManager.removeFilters(filters);
+        return this;
+    }
+
+
+    @Override
+    public <T> TamayaConfigBuilder removeConverters(Class<T> typeToConvert,
+                                                    Converter<T>... converters) {
+        this.converterManager.removeConverters(typeToConvert, converters);
+        return this;
+    }
+
+    @Override
+    public <T> TamayaConfigBuilder removeConverters(Class<T> typeToConvert,
+                                                    Collection<Converter<T>> converters) {
+        this.converterManager.removeConverters(typeToConvert, Collection.class.cast(converters));
+        return this;
+    }
+
+    @Override
+    public <T> TamayaConfigBuilder removeConverters(Class<T> typeToConvert) {
+        this.converterManager.removeConverters(typeToConvert);
+        return this;
+    }
+
+
+    @Override
+    public TamayaConfigBuilder withPropertyValueCombinationPolicy(ConfigValueCombinationPolicy combinationPolicy){
+        this.configSourceManager.setConfigValueCombinationPolicy(combinationPolicy);
+        return this;
+    }
+
+    @Override
+    public <T> TamayaConfigBuilder withConverters(Class<T> type, Converter<T>... converters){
+        this.converterManager.addConverter(type, converters);
+        return this;
+    }
+
+    @Override
+    public <T> TamayaConfigBuilder withConverters(Class<T> type, Collection<Converter<T>> converters){
+        this.converterManager.addConverter(type, Collection.class.cast(converters));
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder sortFilter(Comparator<Filter> comparator) {
+        this.filterManager.sortFilter(comparator);
+        return this;
+    }
+
+    @Override
+    public TamayaConfigBuilder sortSources(Comparator<ConfigSource> comparator) {
+        this.configSourceManager.sortSources(comparator);
+        return this;
+    }
+
+    @Override
+    public List<Filter> getFilters() {
+        return this.filterManager.getFilters();
+    }
+
+    @Override
+    public Map<Type, List<Converter>> getConverter() {
+        return this.converterManager.getConverters();
+    }
+
+    /**
+     * Builds a new configuration based on the configuration of this builder instance.
+     *
+     * @return a new {@link Config configuration instance},
+     *         never {@code null}.
+     */
+    @Override
+    public Config build() {
+        return new DefaultConfig(getConfigContext());
+    }
+
+    @Override
+    public ConfigContext getConfigContext() {
+        return new ConfigContext() {
+            @Override
+            public List<ConfigSource> getSources() {
+                return configSourceManager.getSources();
+            }
+
+            @Override
+            public List<Filter> getFilters() {
+                return filterManager.getFilters();
+            }
+
+            @Override
+            public Map<Type, List<Converter>> getConverters() {
+                return converterManager.getConverters();
+            }
+
+            @Override
+            public ConfigValueCombinationPolicy getConfigValueCombinationPolicy() {
+                return configSourceManager.getConfigValueCombinationPolicy();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java b/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java
new file mode 100644
index 0000000..752fd3c
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java
@@ -0,0 +1,225 @@
+/*
+ * 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.tamaya.base;
+
+import org.apache.tamaya.spi.ServiceContext;
+
+import javax.annotation.Priority;
+import java.io.IOException;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class implements the (default) {@link ServiceContext} interface and hereby uses the JDK
+ * {@link ServiceLoader} to load the services required.
+ */
+public final class DefaultServiceContext implements ServiceContext {
+    private static final Logger LOG = Logger.getLogger(DefaultServiceContext.class.getName());
+    /**
+     * List current services loaded, per class.
+     */
+    private final ConcurrentHashMap<Class<?>, List<Object>> servicesLoaded = new ConcurrentHashMap<>();
+    /**
+     * Singletons.
+     */
+    private final Map<Class<?>, Object> singletons = new ConcurrentHashMap<>();
+    @SuppressWarnings("rawtypes")
+	private Map<Class, Class> factoryTypes = new ConcurrentHashMap<>();
+
+    @Override
+    public <T> T getService(Class<T> serviceType) {
+        return getService(serviceType, ServiceContext.defaultClassLoader());
+    }
+
+    @Override
+    public <T> T getService(Class<T> serviceType, ClassLoader classLoader) {
+        Object cached = singletons.get(serviceType);
+        if (cached == null) {
+            cached = create(serviceType);
+            if(cached!=null) {
+                singletons.put(serviceType, cached);
+            }
+        }
+        return serviceType.cast(cached);
+    }
+
+    @Override
+    public <T> T create(Class<T> serviceType) {
+        return create(serviceType, ServiceContext.defaultClassLoader());
+    }
+
+    @Override
+    public <T> T create(Class<T> serviceType, ClassLoader classLoader) {
+        @SuppressWarnings("unchecked")
+		Class<? extends T> implType = factoryTypes.get(serviceType);
+        if(implType==null) {
+            Collection<T> services = getServices(serviceType, classLoader);
+            if (services.isEmpty()) {
+                return null;
+            } else {
+                return getServiceWithHighestPriority(services, serviceType);
+            }
+        }
+        try {
+            return implType.newInstance();
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to create instance of " + implType.getName(), e);
+            return  null;
+        }
+    }
+
+    /**
+            * Loads and registers services.
+            *
+            * @param <T>         the concrete type.
+     * @param serviceType The service type.
+            * @return the items found, never {@code null}.
+            */
+    @Override
+    public <T> List<T> getServices(final Class<T> serviceType) {
+        return  getServices(serviceType, ServiceContext.defaultClassLoader());
+    }
+
+    /**
+     * Loads and registers services.
+     *
+     * @param <T>         the concrete type.
+     * @param serviceType The service type.
+     * @return the items found, never {@code null}.
+     */
+    @Override
+    public <T> List<T> getServices(final Class<T> serviceType, ClassLoader classLoader) {
+        @SuppressWarnings("unchecked")
+		List<T> found = (List<T>) servicesLoaded.get(serviceType);
+        if (found != null) {
+            return found;
+        }
+        List<T> services = new ArrayList<>();
+        try {
+            for (T t : ServiceLoader.load(serviceType, classLoader)) {
+                services.add(t);
+            }
+            if(services.isEmpty()) {
+                for (T t : ServiceLoader.load(serviceType, serviceType.getClassLoader())) {
+                    services.add(t);
+                }
+            }
+            Collections.sort(services, org.apache.tamaya.base.PriorityServiceComparator.getInstance());
+            services = Collections.unmodifiableList(services);
+        } catch (ServiceConfigurationError e) {
+            LOG.log(Level.WARNING,
+                    "Error loading services current type " + serviceType, e);
+            if(services==null){
+                services = Collections.emptyList();
+            }
+        }
+        @SuppressWarnings("unchecked")
+		final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>) services));
+        return previousServices != null ? previousServices : services;
+    }
+
+    /**
+     * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
+     * annotation is present, a default priority of {@code 1} is returned.
+     * @param o the instance, not {@code null}.
+     * @return a priority, by default 1.
+     */
+    public static int getPriority(Object o){
+        int prio = 1; //X TODO discuss default priority
+        Priority priority = o.getClass().getAnnotation(Priority.class);
+        if (priority != null) {
+            prio = priority.value();
+        }
+        return prio;
+    }
+
+    /**
+     * @param services to scan
+     * @param <T>      type of the service
+     *
+     * @return the service with the highest {@link Priority#value()}
+     *
+     * @throws IllegalStateException if there are multiple service implementations with the maximum priority
+     */
+    private <T> T getServiceWithHighestPriority(Collection<T> services, Class<T> serviceType) {
+        T highestService = null;
+        // we do not need the priority stuff if the list contains only one element
+        if (services.size() == 1) {
+            highestService = services.iterator().next();
+            this.factoryTypes.put(serviceType, highestService.getClass());
+            return highestService;
+        }
+
+        Integer highestPriority = null;
+        int highestPriorityServiceCount = 0;
+
+        for (T service : services) {
+            int prio = getPriority(service);
+            if (highestPriority == null || highestPriority < prio) {
+                highestService = service;
+                highestPriorityServiceCount = 1;
+                highestPriority = prio;
+            } else if (highestPriority == prio) {
+                highestPriorityServiceCount++;
+            }
+        }
+
+        if (highestPriorityServiceCount > 1) {
+            throw new IllegalStateException(MessageFormat.format("Found {0} implementations for Service {1} with Priority {2}: {3}",
+                                                           highestPriorityServiceCount,
+                                                           serviceType.getName(),
+                                                           highestPriority,
+                                                           services));
+        }
+        this.factoryTypes.put(serviceType, highestService.getClass());
+        return highestService;
+    }
+
+    @Override
+    public int ordinal() {
+        return 1;
+    }
+
+    @Override
+    public Enumeration<URL> getResources(String resource, ClassLoader cl) throws IOException {
+        if(cl==null){
+            cl = Thread.currentThread().getContextClassLoader();
+        }
+        if(cl==null){
+            cl = getClass().getClassLoader();
+        }
+        return cl.getResources(resource);
+    }
+
+    @Override
+    public URL getResource(String resource, ClassLoader cl) {
+        if(cl==null){
+            cl = Thread.currentThread().getContextClassLoader();
+        }
+        if(cl==null){
+            cl = getClass().getClassLoader();
+        }
+        return cl.getResource(resource);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/PriorityServiceComparator.java b/code/base/src/main/java/org/apache/tamaya/base/PriorityServiceComparator.java
new file mode 100644
index 0000000..37f5095
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/PriorityServiceComparator.java
@@ -0,0 +1,84 @@
+/*
+ * 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.tamaya.base;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for odering services loaded based on their increasing priority values.
+ */
+public class PriorityServiceComparator implements Comparator<Object>, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final PriorityServiceComparator INSTANCE = new PriorityServiceComparator();
+
+    /** Singleton constructor. */
+    private PriorityServiceComparator(){}
+
+    /**
+     * Get the shared instance of the comparator.
+     * @return the shared instance, never null.
+     */
+    public static PriorityServiceComparator getInstance(){
+        return INSTANCE;
+    }
+
+    @Override
+    public int compare(Object o1, Object o2) {
+        int prio = getPriority(o1) - getPriority(o2);
+        if (prio < 0) {
+            return 1;
+        } else if (prio > 0) {
+            return -1;
+        } else {
+            return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+        }
+    }
+
+    /**
+     * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
+     * annotation is present, a default priority {@code 1} is returned.
+     *
+     * @param o the instance, not {@code null}.
+     * @return a priority, by default 1.
+     */
+    public static int getPriority(Object o) {
+        return getPriority(o.getClass());
+    }
+
+    /**
+     * Checks the given type optionally annotated with a @Priority. If present the annotation's value is evaluated.
+     * If no such annotation is present, a default priority {@code 1} is returned.
+     *
+     * @param type the type, not {@code null}.
+     * @return a priority, by default 1.
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static int getPriority(Class type) {
+        int prio = 1;
+		Priority priority = (Priority)type.getAnnotation(Priority.class);
+        if (priority != null) {
+            prio = priority.value();
+        }
+        return prio;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/ReflectionUtil.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/ReflectionUtil.java b/code/base/src/main/java/org/apache/tamaya/base/ReflectionUtil.java
new file mode 100644
index 0000000..85d2dc3
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/ReflectionUtil.java
@@ -0,0 +1,42 @@
+/*
+ * 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.tamaya.base;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+
+/**
+ * Small utility class used by other parts.
+ */
+public final class ReflectionUtil {
+
+    private ReflectionUtil(){}
+
+    public static ParameterizedType getParametrizedType(Class<?> clazz) {
+        Type[] genericTypes = clazz.getGenericInterfaces();
+        for (Type type : genericTypes) {
+            if (type instanceof ParameterizedType) {
+                return (ParameterizedType) type;
+            }
+
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/BaseConfigSource.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/BaseConfigSource.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/BaseConfigSource.java
new file mode 100644
index 0000000..12adfaa
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/BaseConfigSource.java
@@ -0,0 +1,170 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import javax.config.spi.ConfigSource;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Abstract {@link ConfigSource} that allows to set a default ordinal that will be used, if no
+ * ordinal is provided with the config.
+ */
+public abstract class BaseConfigSource implements ConfigSource{
+    /** default ordinal that will be used, if no ordinal is provided with the config. */
+    private int defaultOrdinal;
+    /** Used if the ordinal has been set explicitly. */
+    private volatile Integer ordinal;
+    /** The name of the property source. */
+    private String name;
+
+    /**
+     * Constructor.
+     * @param name the (unique) property source name, not {@code null}.
+     */
+    protected BaseConfigSource(String name){
+        this.name = Objects.requireNonNull(name);
+        this.defaultOrdinal = 0;
+    }
+
+    /**
+     * Constructor.
+     * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided with the config.
+     */
+    protected BaseConfigSource(int defaultOrdinal){
+        this.name = getClass().getSimpleName();
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+    /**
+     * Constructor.
+     * @param name the (unique) property source name, not {@code null}.
+     * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided with the config.
+     */
+    protected BaseConfigSource(String name, int defaultOrdinal){
+        this.name = Objects.requireNonNull(name);
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+
+    /**
+     * Constructor, using a default ordinal of 0.
+     */
+    protected BaseConfigSource(){
+        this(0);
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the property source's (unique) name.
+     * @param name the name, not {@code null}.
+     */
+    public void setName(String name){
+        this.name = Objects.requireNonNull(name);
+    }
+
+    /**
+     * Allows to set the ordinal of this property source explcitly. This will override any evaluated
+     * ordinal, or default ordinal. To reset an explcit ordinal call {@code setOrdinal(null);}.
+     * @param ordinal the explicit ordinal, or {@code null}.
+     */
+    public void setOrdinal(Integer ordinal){
+        this.ordinal = ordinal;
+    }
+
+    /**
+     * Allows to set the ordinal of this property source explcitly. This will override any evaluated
+     * ordinal, or default ordinal. To reset an explcit ordinal call {@code setOrdinal(null);}.
+     * @param defaultOrdinal the default ordinal, or {@code null}.
+     */
+    public void setDefaultOrdinal(Integer defaultOrdinal){
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+    public int getOrdinal() {
+        Integer ordinal = this.ordinal;
+        if(ordinal!=null){
+            Logger.getLogger(getClass().getName()).finest(
+                    "Using explicit ordinal '"+ordinal+"' for property source: " + getName());
+            return ordinal;
+        }
+        String configuredOrdinal = getValue(CONFIG_ORDINAL);
+        if(configuredOrdinal!=null){
+            try {
+                return Integer.parseInt(configuredOrdinal);
+            } catch (Exception e) {
+                Logger.getLogger(getClass().getName()).log(Level.WARNING,
+                        "Configured ordinal is not an int number: " + configuredOrdinal, e);
+            }
+        }
+        return getDefaultOrdinal();
+    }
+
+    /**
+     * Returns the  default ordinal used, when no ordinal is set, or the ordinal was not parseable to an int value.
+     * @return the  default ordinal used, by default 0.
+     */
+    public int getDefaultOrdinal(){
+        return defaultOrdinal;
+    }
+
+    @Override
+    public String getValue(String key) {
+        Map<String,String> properties = getProperties();
+        String val = properties.get(key);
+        if(val==null){
+            return null;
+        }
+        return val;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BaseConfigSource that = (BaseConfigSource) o;
+
+        return name.equals(that.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+                toStringValues() +
+                '}';
+    }
+
+    protected String toStringValues() {
+        return  "  defaultOrdinal=" + defaultOrdinal + '\n' +
+                "  ordinal=" + ordinal  + '\n' +
+                "  name='" + name + '\''  + '\n';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSource.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSource.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSource.java
new file mode 100644
index 0000000..b0e859b
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSource.java
@@ -0,0 +1,208 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import javax.config.spi.ConfigSource;
+import java.util.*;
+
+/**
+ * A Buildable property source.
+ */
+public class BuildableConfigSource implements ConfigSource{
+
+    private int ordinal;
+    private String name = "PropertySource-"+UUID.randomUUID().toString();
+    private Map<String,String> properties = new HashMap<>();
+
+    @Override
+    public int getOrdinal() {
+        return ordinal;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getValue(String key) {
+        return properties.get(key);
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return Collections.unmodifiableMap(properties);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BuildableConfigSource that = (BuildableConfigSource) o;
+
+        return name.equals(that.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "BuildablePropertySource{" +
+                "ordinal=" + ordinal +
+                ", name='" + name + '\'' +
+                ", properties=" + properties +
+                '}';
+    }
+
+    /**
+     * Builder builder.
+     *
+     * @return the builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+
+    /**
+     * The type Builder.
+     */
+    public static final class Builder {
+        private int ordinal;
+        private String source;
+        private String name = "PropertySource-"+ UUID.randomUUID().toString();
+        private Map<String,String> properties = new HashMap<>();
+
+        private Builder() {
+        }
+
+        /**
+         * With ordinal builder.
+         *
+         * @param ordinal the ordinal
+         * @return the builder
+         */
+        public Builder withOrdinal(int ordinal) {
+            this.ordinal = ordinal;
+            return this;
+        }
+
+        /**
+         * With source builder.
+         *
+         * @param source the source
+         * @return the builder
+         */
+        public Builder withSource(String source) {
+            this.source = Objects.requireNonNull(source);
+            return this;
+        }
+
+        /**
+         * With name builder.
+         *
+         * @param name the name
+         * @return the builder
+         */
+        public Builder withName(String name) {
+            this.name = Objects.requireNonNull(name);
+            return this;
+        }
+
+        /**
+         * With simple property builder.
+         *
+         * @param key   the key
+         * @param value the value
+         * @return the builder
+         */
+        public Builder withProperty(String key, String value) {
+            return withProperty(key, value, this.source);
+        }
+
+        /**
+         * With simple property builder.
+         *
+         * @param key    the key
+         * @param value  the value
+         * @param source the source
+         * @return the builder
+         */
+        public Builder withProperty(String key, String value, String source) {
+            this.properties.put(key, value);
+            if(source!=null) {
+                this.properties.put(key+"[meta]", "source="+source);
+            }
+            return this;
+        }
+
+        /**
+         * With properties builder.
+         *
+         * @param properties the properties
+         * @param source     the source
+         * @return the builder
+         */
+        public Builder withProperty(Map<String, String> properties, String source) {
+            properties.forEach((k,v) -> {
+                withProperty(k, v, source);
+            });
+            return this;
+        }
+
+        /**
+         * With simple properties builder.
+         *
+         * @param properties the properties
+         * @return the builder
+         */
+        public Builder withProperties(Map<String, String> properties) {
+            properties.forEach((k,v) -> {
+                withProperty(k, v);
+            });
+            return this;
+        }
+
+        /**
+         * But builder.
+         *
+         * @return the builder
+         */
+        public Builder but() {
+            return builder().withOrdinal(ordinal).withName(name).withProperties(properties);
+        }
+
+        /**
+         * Build buildable property source.
+         *
+         * @return the buildable property source
+         */
+        public BuildableConfigSource build() {
+            BuildableConfigSource buildableConfigSource = new BuildableConfigSource();
+            buildableConfigSource.name = this.name;
+            buildableConfigSource.properties = this.properties;
+            buildableConfigSource.ordinal = this.ordinal;
+            return buildableConfigSource;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSourceProvider.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSourceProvider.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSourceProvider.java
new file mode 100644
index 0000000..d670576
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/BuildableConfigSourceProvider.java
@@ -0,0 +1,113 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import javax.config.spi.ConfigSource;
+import javax.config.spi.ConfigSourceProvider;
+import java.util.*;
+
+/**
+ * A Buildable property source.
+ */
+public class BuildableConfigSourceProvider implements ConfigSourceProvider{
+
+    private List<ConfigSource> sources = new ArrayList<>();
+
+    @Override
+    public Collection<ConfigSource> getConfigSources(ClassLoader cl) {
+        return Collections.unmodifiableCollection(sources);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BuildableConfigSourceProvider that = (BuildableConfigSourceProvider) o;
+
+        return sources.equals(that.sources);
+    }
+
+    @Override
+    public int hashCode() {
+        return sources.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "BuildablePropertySourceProvider{" +
+                "sources=" + sources +
+                '}';
+    }
+
+    /**
+     * Builder builder.
+     *
+     * @return the builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+
+
+
+    /**
+     * The type Builder.
+     */
+    public static final class Builder {
+        private List<ConfigSource> sources = new ArrayList<>();
+
+        private Builder() {
+        }
+
+        /**
+         * With propertySources.
+         *
+         * @param propertySources the propertySources
+         * @return the builder
+         */
+        public Builder withPropertySourcs(ConfigSource... propertySources) {
+            this.sources.addAll(Arrays.asList(propertySources));
+            return this;
+        }
+
+        /**
+         * With property sources builder.
+         *
+         * @param sources the property sources
+         * @return the builder
+         */
+        public Builder withPropertySourcs(Collection<ConfigSource> sources) {
+            this.sources.addAll(sources);
+            return this;
+        }
+
+        /**
+         * Build buildable property source.
+         *
+         * @return the buildable property source
+         */
+        public BuildableConfigSourceProvider build() {
+            BuildableConfigSourceProvider buildablePropertySource = new BuildableConfigSourceProvider();
+            buildablePropertySource.sources.addAll(this.sources);
+            return buildablePropertySource;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/CLIConfigSource.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/CLIConfigSource.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/CLIConfigSource.java
new file mode 100644
index 0000000..4e57229
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/CLIConfigSource.java
@@ -0,0 +1,130 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import java.util.*;
+
+/**
+ * PropertySource that allows to add the programs main arguments as configuration entries. Unix syntax using '--' and
+ * '-' params is supported.
+ */
+public class CLIConfigSource extends BaseConfigSource {
+
+    /** The original main arguments. */
+    private static String[] args = new String[0];
+
+    /** The map of parsed main arguments. */
+    private static Map<String,String> mainArgs;
+
+    /** Initializes the initial state. */
+    static{
+        initMainArgs(args);
+    }
+
+    /**
+     * Creates a new instance.
+     */
+    public CLIConfigSource(){
+        this((String[])null);
+    }
+
+    /**
+     * Creates a new instance, allows optionally to pass the main arguments.
+     * @param args the args, or null.
+     */
+    public CLIConfigSource(String... args){
+        super("CLI");
+        if(args!=null){
+            initMainArgs(args);
+        }
+    }
+
+    /**
+     * Creates a new instance, allows optionally to pass the main arguments.
+     * @param args the args, or null.
+     * @param ordinal the ordinal to be applied.
+     */
+    public CLIConfigSource(int ordinal, String... args){
+        if(args!=null){
+            initMainArgs(args);
+        }
+        setOrdinal(ordinal);
+    }
+
+
+
+    /**
+     * Configure the main arguments, hereby parsing and mapping the main arguments into
+     * configuration propertiesi as key-value pairs.
+     * @param args the main arguments, not null.
+     */
+    public static void initMainArgs(String... args){
+        CLIConfigSource.args = Objects.requireNonNull(args);
+        // TODO is there a way to figure out the args?
+        String argsProp = System.getProperty("main.args");
+        if(argsProp!=null){
+            CLIConfigSource.args = argsProp.split("\\s");
+        }
+        Map<String,String> result;
+        if(CLIConfigSource.args==null){
+            result = Collections.emptyMap();
+        }else{
+            result = new HashMap<>();
+            String prefix = System.getProperty("main.args.prefix");
+            if(prefix==null){
+                prefix="";
+            }
+            String key = null;
+            for(String arg: CLIConfigSource.args){
+                if(arg.startsWith("--")){
+                    arg = arg.substring(2);
+                    int index = arg.indexOf("=");
+                    if(index>0){
+                        key = arg.substring(0,index).trim();
+                        result.put(prefix+key, arg.substring(index+1).trim());
+                        key = null;
+                    }else{
+                        result.put(prefix+arg, arg);
+                    }
+                }else if(arg.startsWith("-")){
+                    key = arg.substring(1);
+                }else{
+                    if(key!=null){
+                        result.put(prefix+key, arg);
+                        key = null;
+                    }else{
+                        result.put(prefix+arg, arg);
+                    }
+                }
+            }
+        }
+        CLIConfigSource.mainArgs = Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return Collections.unmodifiableMap(mainArgs);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return  super.toStringValues() +
+                "  args=" + Arrays.toString(args) + '\n';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceComparator.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceComparator.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceComparator.java
new file mode 100644
index 0000000..c1015ea
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceComparator.java
@@ -0,0 +1,117 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import javax.config.spi.ConfigSource;
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.logging.Logger;
+
+/**
+ * Comparator for ordering of PropertySources based on their ordinal method and class name.
+ */
+public class ConfigSourceComparator implements Comparator<ConfigSource>, Serializable {
+    /** serial version UID. */
+    private static final long serialVersionUID = 1L;
+
+    private static final Logger LOG = Logger.getLogger(ConfigSourceComparator.class.getName());
+
+    private static final ConfigSourceComparator INSTANCE = new ConfigSourceComparator();
+
+    private String alternativeOrdinalKey;
+
+    /** Singleton constructor. */
+    private ConfigSourceComparator(){}
+
+    /**
+     * Get the shared instance of the comparator.
+     * @return the shared instance, never null.
+     */
+    public static ConfigSourceComparator getInstance(){
+        return INSTANCE;
+    }
+
+
+    /**
+     * Order property source reversely, the most important comes first.
+     *
+     * @param source1 the first PropertySource
+     * @param source2 the second PropertySource
+     * @return the comparison result.
+     */
+    private int compareConfigSources(ConfigSource source1, ConfigSource source2) {
+        if (getOrdinal(source1) < getOrdinal(source2)) {
+            return -1;
+        } else if (getOrdinal(source1) > getOrdinal(source2)) {
+            return 1;
+        } else {
+            return source1.getClass().getName().compareTo(source2.getClass().getName());
+        }
+    }
+
+    /**
+     * Evaluates an ordinal value from a {@link ConfigSource}, Hereby the ordinal of type {@code int}
+     * is evaluated as follows:
+     * <ol>
+     *     <li>It evaluates the {@code String} value for {@link ConfigSource#CONFIG_ORDINAL} and tries
+     *     to convert it to an {@code int} value, using {@link Integer#parseInt(String)}.</li>
+     *     <li>It tries to find and evaluate a method {@code int getOrdinal()}.</li>
+     *     <li>It tries to find and evaluate a static field {@code int ORDINAL}.</li>
+     *     <li>It tries to find and evaluate a class level {@link javax.annotation.Priority} annotation.</li>
+     *     <li>It uses the default priority ({@code 0}.</li>
+     * </ol>
+     * @param propertySource the property source, not {@code null}.
+     * @return the ordinal value to compare the property source.
+     */
+    public static int getOrdinal(ConfigSource propertySource) {
+        return getOrdinal(propertySource, null);
+    }
+
+    public static int getOrdinal(ConfigSource propertySource, String alternativeOrdinalKey) {
+        if(alternativeOrdinalKey!=null) {
+            String ordinalValue = propertySource.getValue(alternativeOrdinalKey);
+            if (ordinalValue != null) {
+                try {
+                    return Integer.parseInt(ordinalValue.trim());
+                } catch (Exception e) {
+                    LOG.finest("Failed to parse ordinal from " + alternativeOrdinalKey +
+                            " in " + propertySource.getName() + ": " + ordinalValue);
+                }
+            }
+        }
+        return propertySource.getOrdinal();
+    }
+
+    /**
+     * Overrides/adds the key to evaluate/override a property sources ordinal.
+     * @param ordinalKey sets the alternative ordinal key, if null default
+     *                   behaviour will be active.
+     * @return the instance for chaining.
+     */
+    public ConfigSourceComparator setOrdinalKey(String ordinalKey) {
+        this.alternativeOrdinalKey = ordinalKey;
+        return this;
+    }
+
+    @Override
+    public int compare(ConfigSource source1, ConfigSource source2) {
+        return compareConfigSources(source1, source2);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java
new file mode 100644
index 0000000..7a09bf5
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java
@@ -0,0 +1,375 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import org.apache.tamaya.base.FormatUtils;
+import org.apache.tamaya.spi.*;
+
+import javax.config.Config;
+import javax.config.spi.ConfigSource;
+import javax.config.spi.ConfigSourceProvider;
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link Config} to evaluate the
+ * chain of {@link javax.config.spi.ConfigSource} and {@link Filter}
+ * instance to evaluate the current Configuration.
+ */
+public class ConfigSourceManager {
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = Logger.getLogger(ConfigSourceManager.class.getName());
+    /**
+     * The current list of loaded {@link ConfigSource} instances.
+     */
+    private final List<ConfigSource> configSources = new ArrayList<>();
+
+    /**
+     * The overriding policy used when combining PropertySources registered to evalute the final configuration
+     * values.
+     */
+    ConfigValueCombinationPolicy configValueCombinationPolicy;
+
+    private ClassLoader classloader = ServiceContext.defaultClassLoader();
+
+    /**
+     * Create a new filter manager.
+     */
+    public ConfigSourceManager(){
+        configValueCombinationPolicy = ServiceContextManager.getServiceContext().getService(
+                ConfigValueCombinationPolicy.class);
+        if(configValueCombinationPolicy == null){
+            configValueCombinationPolicy = ConfigValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+        }
+        LOG.info("Using PropertyValueCombinationPolicy: " + configValueCombinationPolicy);
+    }
+
+    /**
+     * Create a new filter manager.
+     * @param configSources the config sources to be used, not null.
+     */
+    public ConfigSourceManager(List<ConfigSource> configSources){
+        this.configSources.addAll(configSources);
+        LOG.info("Registered " + configSources.size() + " config sources: " + configSources);
+    }
+
+    /**
+     * Get the classloader used for instance creation.
+     * @return the classloader, never null.
+     */
+    public ClassLoader getClassloader(){
+        return classloader;
+    }
+
+    /**
+     * Sets the classloader to use for loading of instances.
+     * @param ClassLoader the classloader, not null.
+     * @return this instance for chaining.
+     */
+    public ConfigSourceManager setClassloader(ClassLoader ClassLoader){
+        this.classloader = Objects.requireNonNull(classloader);
+        return this;
+    }
+
+    /**
+     * The current unmodifiable list of loaded {@link ConfigSource} instances.
+     */
+    public List<ConfigSource> getSources(){
+        return Collections.unmodifiableList(configSources);
+    }
+
+    /**
+     * Registers a new ConfigSource instance.
+     *
+     * @param configSources  the config source, not {@code null}.
+     */
+    public ConfigSourceManager addSources(Collection<ConfigSource> configSources) {
+        Objects.requireNonNull(configSources);
+        for(ConfigSource configSource:configSources) {
+            if (!this.configSources.contains(configSource)) {
+                this.configSources.add(configSource);
+            }
+        }
+        return this;
+    }
+
+    public ConfigSourceManager addDiscoveredSources() {
+        List<ConfigSource> propertySources = new ArrayList<>();
+        addCoreSources(propertySources);
+        for(ConfigSource ps: ServiceContextManager.getServiceContext().getServices(ConfigSource.class)) {
+            if(!propertySources.contains(ps)){
+                propertySources.add(ps);
+            }
+        }
+        for(ConfigSourceProvider provider:
+                ServiceContextManager.getServiceContext().getServices(ConfigSourceProvider.class)){
+            provider.getConfigSources(classloader).forEach(propertySources::add);
+        }
+        Collections.sort(propertySources, ConfigSourceComparator.getInstance());
+        return addSources(propertySources);
+    }
+
+    protected ConfigSourceManager addCoreSources(List<ConfigSource> propertySources) {
+        for(ConfigSource ps: new ConfigSource[]{
+                new EnvironmentConfigSource(),
+                new JavaConfigurationConfigSource(),
+                new CLIConfigSource(),
+                new SystemConfigSource()
+        }){
+            if(!propertySources.contains(ps)){
+                propertySources.add(ps);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Registers a new ConfigSource instance.
+     *
+     * @param configSources  the config source, not {@code null}.
+     */
+    public ConfigSourceManager addSources(ConfigSource... configSources) {
+        return addSources(Arrays.asList(configSources));
+    }
+
+
+    /**
+     * Access a {@link ConfigSource} using its (unique) name.
+     * @param name the propoerty source's name, not {@code null}.
+     * @return the propoerty source found, or {@code null}.
+     */
+    public ConfigSource getSource(String name) {
+        for(ConfigSource ps: getSources()){
+            if(name.equals(ps.getName())){
+                return ps;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Removes the given config sources, if existing. The existing order of config
+     * sources is preserved.
+     *
+     * @param configSources the config sources to remove, not {@code null}.
+     * @return the builder for chaining.
+     */
+    public final ConfigSourceManager removeSources(ConfigSource... configSources) {
+        return removeSources(Arrays.asList(configSources));
+    }
+    /**
+     * Removes the given config sources, if existing. The existing order of config
+     * sources is preserved.
+     *
+     * @param configSources the config sources to remove, not {@code null}.
+     * @return the builder for chaining.
+     */
+    public ConfigSourceManager removeSources(Collection<ConfigSource> configSources) {
+        this.configSources.removeAll(configSources);
+        return this;
+    }
+
+    /**
+     * Increases the priority of the given property source, by moving it towards the end
+     * of the chain of property sources. If the property source given is already at the end
+     * this method has no effect. This operation does not change any ordinal values.
+     *
+     * @param configSource the config source to be incresed regarding its significance.
+     * @return the builder for chaining.
+     * @throws IllegalArgumentException If no such property source exists in the current
+     * chain.
+     */
+    public ConfigSourceManager increasePriority(ConfigSource configSource){
+        int index = configSources.indexOf(configSource);
+        if(index<0){
+            throw new IllegalArgumentException("No such ConfigSource: " + configSource);
+        }
+        if(index<(configSources.size()-1)){
+            configSources.remove(configSource);
+            configSources.add(index+1, configSource);
+        }
+        return this;
+    }
+
+    /**
+     * Decreases the priority of the given property source, by moving it towards the start
+     * of the chain of property sources. If the property source given is already the first
+     * this method has no effect. This operation does not change any ordinal values.
+     *
+     * @param configSource the config source to be decresed regarding its significance.
+     * @return the builder for chaining.
+     * @throws IllegalArgumentException If no such property source exists in the current
+     * chain.
+     */
+    public ConfigSourceManager decreasePriority(ConfigSource configSource){
+        int index = configSources.indexOf(configSource);
+        if(index<0){
+            throw new IllegalArgumentException("No such ConfigSource: " + configSource);
+        }
+        if(index>0){
+            configSources.remove(configSource);
+            configSources.add(index-1, configSource);
+        }
+        return this;
+    }
+
+    /**
+     * Increases the priority of the given property source to be maximal, by moving it to
+     * the tail of the of property source chain. If the property source given is
+     * already the last item this method has no effect. This operation does not change
+     * any ordinal values.
+     *
+     * @param configSource the config source to be maximized regarding its significance.
+     * @return the builder for chaining.
+     * @throws IllegalArgumentException If no such property source exists in the current
+     * chain.
+     */
+    public ConfigSourceManager highestPriority(ConfigSource configSource){
+        int index = configSources.indexOf(configSource);
+        if(index<0){
+            throw new IllegalArgumentException("No such ConfigSource: " + configSource);
+        }
+        if(index<(configSources.size()-1)){
+            configSources.remove(configSource);
+            configSources.add(configSource);
+        }
+        return this;
+    }
+
+    /**
+     * Decreases the priority of the given property source to be minimal, by moving it to
+     * the start of the chain of property source chain. If the property source given is
+     * already the first item this method has no effect. This operation does not change
+     * any ordinal values.
+     *
+     * @param configSource the config source to be minimized regarding its significance.
+     * @return the builder for chaining.
+     * @throws IllegalArgumentException If no such property source exists in the current
+     * chain.
+     */
+    public ConfigSourceManager lowestPriority(ConfigSource configSource){
+        int index = configSources.indexOf(configSource);
+        if(index<0){
+            throw new IllegalArgumentException("No such PropertySource: " + configSource);
+        }
+        if(index>0){
+            configSources.remove(configSource);
+            configSources.add(0, configSource);
+        }
+        return this;
+    }
+
+    public ConfigSourceManager sortSources(Comparator<ConfigSource> comparator) {
+        Collections.sort(configSources, comparator);
+        return this;
+    }
+
+    /**
+     * Access the {@link ConfigValueCombinationPolicy} used to evaluate the final
+     * property values.
+     * @return the {@link ConfigValueCombinationPolicy} used, never null.
+     */
+    public ConfigValueCombinationPolicy getConfigValueCombinationPolicy(){
+        return configValueCombinationPolicy;
+    }
+
+    /**
+     * Removes all contained items.
+     * @return this instance for chaining.
+     */
+    public ConfigSourceManager clear() {
+        this.configSources.clear();
+        this.configValueCombinationPolicy = ConfigValueCombinationPolicy.DEFAULT_OVERRIDING_POLICY;
+        return this;
+    }
+
+    /**
+     * Evaluates the raw value using the context's PropertyValueCombinationPolicy.
+     * @param key the key, not null.
+     * @return the value, before filtering is applied.
+     */
+    public ConfigValue evaluteRawValue(String key) {
+        List<ConfigSource> configSources = getSources();
+        ConfigValue unfilteredValue = null;
+        ConfigValueCombinationPolicy combinationPolicy = getConfigValueCombinationPolicy();
+        for (ConfigSource propertySource : configSources) {
+            unfilteredValue = combinationPolicy.collect(unfilteredValue, key, propertySource);
+        }
+        return unfilteredValue;
+    }
+
+    public Map<String, ConfigValue> evaluateRawValues() {
+        List<ConfigSource> configSources = getSources();
+        ConfigValueCombinationPolicy combinationPolicy = getConfigValueCombinationPolicy();
+        Map<String, ConfigValue> result = new HashMap<>();
+        for (ConfigSource propertySource : configSources) {
+            for (Map.Entry<String,String> propEntry: propertySource.getProperties().entrySet()) {
+                ConfigValue unfilteredValue = result.get(propEntry.getKey());
+                unfilteredValue = combinationPolicy.
+                        collect(unfilteredValue, propEntry.getKey(), propertySource);
+                if(unfilteredValue!=null){
+                    result.put(unfilteredValue.getKey(), unfilteredValue);
+                }
+            }
+        }
+        return result;
+    }
+
+
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder("Config Sources\n");
+             b.append("--------------\n");
+        if(configSources.isEmpty()){
+            b.append("  No config sources loaded.\n\n");
+        }else {
+            b.append("  CLASS                         NAME                                                                  ORDINAL SCANNABLE SIZE    STATE     ERROR\n\n");
+            for (ConfigSource ps : configSources) {
+                b.append("  ");
+                FormatUtils.appendFormatted(b, ps.getClass().getSimpleName(), 30);
+                FormatUtils.appendFormatted(b, ps.getName(), 70);
+                FormatUtils.appendFormatted(b, String.valueOf(ConfigSourceComparator.getOrdinal(ps)), 8);
+                String state = ps.getValue("_state");
+                if(state==null){
+                    FormatUtils.appendFormatted(b, "OK", 10);
+                }else {
+                    FormatUtils.appendFormatted(b, state, 10);
+                    if("ERROR".equals(state)){
+                        String val = ps.getValue("_exception");
+                        if(val!=null) {
+                            FormatUtils.appendFormatted(b, val, 30);
+                        }
+                    }
+                }
+                b.append('\n');
+            }
+            b.append("\n");
+        }
+        b.append("\n");
+        b.append("  ConfigValueCombinationPolicy: " + configValueCombinationPolicy.getClass().getName()).append('\n');
+        return b.toString();
+    }
+
+    public void setConfigValueCombinationPolicy(ConfigValueCombinationPolicy configValueCombinationPolicy) {
+        this.configValueCombinationPolicy = Objects.requireNonNull(configValueCombinationPolicy);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/063f8ada/code/base/src/main/java/org/apache/tamaya/base/configsource/EnvironmentConfigSource.java
----------------------------------------------------------------------
diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/EnvironmentConfigSource.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/EnvironmentConfigSource.java
new file mode 100644
index 0000000..2e45bb0
--- /dev/null
+++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/EnvironmentConfigSource.java
@@ -0,0 +1,281 @@
+/*
+ * 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.tamaya.base.configsource;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>{@link javax.config.spi.ConfigSource} to access environment variables via Tamaya
+ * which are set via {@code export VARIABLE=value} on UNIX systems or
+ * {@code set VARIABLE=value} on Windows systems.</p>
+ *
+ * <p>Using the {@linkplain EnvironmentConfigSource} without any
+ * additional configuration gives access to all existing environment
+ * variables available to the Java process Tamaya is running in.</p>
+ *
+ * <h1>Simple usage example</h1>
+ *
+ * <pre>
+ * $ export OPS_MODE=production
+ * $ export COLOR=false
+ * $ java -jar application.jar
+ * </pre>
+ *
+ * <p>To access {@code OPS_MODE} and {@code COLOR} with the following code
+ * fragment could be used:</p>
+ *
+ * <pre>
+ * PropertySource ps = new EnvironmentPropertySource();
+ * PropertyValue opsMode = ps.get("OPS_MODE");
+ * PropertyValue color = ps.get("COLOR");
+ * </pre>
+ *
+ * <h1>Application specific environmet variables with prefix</h1>
+ *
+ * <p>Given the case where to instances of the same application are running on
+ * a single machine but need different values for the environment variable
+ * {@code CUSTOMER}. The {@linkplain EnvironmentConfigSource} allows you
+ * to prefix the environment variable with an application specific prefix
+ * and to access it by the non-prefixed variable name.</p>
+ *
+ * <pre>
+ * $ export CUSTOMER=none
+ * $ export a81.CUSTOMER=moon
+ * $ export b78.CUSTOMER=luna
+ * </pre>
+ *
+ * <p>Given an environment with these tree variables the application running
+ * for the customer called Moon could be started with the following command:</p>
+ *
+ * <pre>
+ * $ java -Dtamaya.envprops.prefix=a81 -jar application.jar
+ * </pre>
+ *
+ * <p>The application specific value can now be accessed from the code of the
+ * application like this:</p>
+ *
+ * <pre>
+ * PropertySource ps = new EnvironmentPropertySource();
+ * PropertyValue pv = ps.get("CUSTOMER");
+ * System.out.println(pv.getValue());
+ * </pre>
+ *
+ * <p>The output of application would be {@code moon}.</p>
+ *
+ * <h1>Disabling the access to environment variables</h1>
+ *
+ * <p>The access to environment variables could be simply
+ * disabled by the setting the systemproperty {@code tamaya.envprops.disable}
+ * or {@code tamaya.defaults.disable} to {@code true}.</p>
+ */
+public class EnvironmentConfigSource extends BaseConfigSource {
+    private static final String TAMAYA_ENVPROPS_PREFIX = "tamaya.envprops.prefix";
+    private static final String TAMAYA_ENVPROPS_DISABLE = "tamaya.envprops.disable";
+    private static final String TAMAYA_DEFAULT_DISABLE = "tamaya.defaults.disable";
+
+    /**
+     * Default ordinal for {@link EnvironmentConfigSource}
+     */
+    public static final int DEFAULT_ORDINAL = 300;
+
+    /**
+     * Prefix that allows environment properties to virtually be mapped on specified sub section.
+     */
+    private String prefix;
+
+    /**
+     * If true, this property source does not return any properties. This is useful since this
+     * property source is applied by default, but can be switched off by setting the
+     * {@code tamaya.envprops.disable} system/environment property to {@code true}.
+     */
+    private boolean disabled = false;
+
+    private SystemPropertiesProvider propertiesProvider = new SystemPropertiesProvider();
+
+    /**
+     * Creates a new instance. Also initializes the {@code prefix} and {@code disabled} properties
+     * from the system-/ environment properties:
+     * <pre>
+     *     tamaya.envprops.prefix
+     *     tamaya.envprops.disable
+     * </pre>
+     */
+    public EnvironmentConfigSource(){
+        initFromSystemProperties();
+    }
+
+    /**
+     * Initializes the {@code prefix} and {@code disabled} properties from the system-/
+     * environment properties:
+     * <pre>
+     *     tamaya.envprops.prefix
+     *     tamaya.envprops.disable
+     * </pre>
+     */
+    private void initFromSystemProperties() {
+        String value = System.getProperty("tamaya.envprops.prefix");
+        if(value==null){
+            prefix = System.getenv("tamaya.envprops.prefix");
+        }
+        value = System.getProperty("tamaya.envprops.disable");
+        if(value==null){
+            value = System.getenv("tamaya.envprops.disable");
+        }
+        if(value==null){
+            value = System.getProperty("tamaya.defaults.disable");
+        }
+        if(value==null){
+            value = System.getenv("tamaya.defaults.disable");
+        }
+        if(value!=null && !value.isEmpty()) {
+            this.disabled = Boolean.parseBoolean(value);
+        }
+    }
+
+    /**
+     * Creates a new instance using a fixed ordinal value.
+     * @param ordinal the ordinal number.
+     */
+    public EnvironmentConfigSource(int ordinal){
+        this(null, ordinal);
+    }
+
+    /**
+     * Creates a new instance.
+     * @param prefix the prefix to be used, or null.
+     * @param ordinal the ordinal to be used.
+     */
+    public EnvironmentConfigSource(String prefix, int ordinal){
+        super("environment-properties");
+        this.prefix = prefix;
+        setOrdinal(ordinal);
+    }
+
+    /**
+     * Creates a new instance.
+     * @param prefix the prefix to be used, or null.
+     */
+    public EnvironmentConfigSource(String prefix){
+        this.prefix = prefix;
+    }
+
+    @Override
+    public int getDefaultOrdinal() {
+        return DEFAULT_ORDINAL;
+    }
+
+    @Override
+    public String getName() {
+        if (isDisabled()) {
+            return "environment-properties(disabled)";
+        }
+        return "environment-properties";
+    }
+
+    @Override
+    public String getValue(String key) {
+        if (isDisabled()) {
+            return null;
+        }
+        String effectiveKey = hasPrefix() ? getPrefix() + "." + key
+                                          : key;
+        return getPropertiesProvider().getenv(effectiveKey);
+    }
+
+    private boolean hasPrefix() {
+        return null != prefix;
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        if(disabled){
+            return Collections.emptyMap();
+        }
+        String prefix = this.prefix;
+        if(prefix==null) {
+            Map<String, String> entries = new HashMap<>(System.getenv().size());
+            for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
+                entries.put(entry.getKey(), entry.getValue());
+            }
+            return entries;
+        }else{
+            Map<String, String> entries = new HashMap<>(System.getenv().size());
+            for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
+                entries.put(prefix + entry.getKey(), entry.getValue());
+            }
+            return entries;
+        }
+    }
+
+
+    @Override
+    protected String toStringValues() {
+        return  super.toStringValues() +
+                "  prefix=" + prefix + '\n' +
+                "  disabled=" + disabled + '\n';
+    }
+
+    void setPropertiesProvider(SystemPropertiesProvider spp) {
+        propertiesProvider = spp;
+        initFromSystemProperties();
+    }
+
+    SystemPropertiesProvider getPropertiesProvider() {
+        return propertiesProvider;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public boolean isDisabled() {
+        return disabled;
+    }
+
+    /**
+     * <p>Provides access to the system properties used to configure
+     * {@linkplain EnvironmentConfigSource}.</p>
+     *
+     * <p>This implementation delegates all property lookups
+     * to {@linkplain System#getProperty(String)}.</p>
+     */
+    static class SystemPropertiesProvider {
+        String getEnvPropsPrefix() {
+            return System.getenv(TAMAYA_ENVPROPS_PREFIX);
+        }
+
+        String getEnvPropsDisable() {
+            return System.getenv(TAMAYA_ENVPROPS_DISABLE);
+        }
+
+        String getDefaultsDisable() {
+            return System.getenv(TAMAYA_DEFAULT_DISABLE);
+        }
+
+        String getenv(String name) {
+            return System.getenv(name);
+        }
+
+        Map<String, String> getenv() {
+            return System.getenv();
+        }
+    }
+}



Mime
View raw message