You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2016/11/11 08:42:49 UTC

[2/2] incubator-tamaya-extensions git commit: TAMAYA-192: Unified format API and calrified responsibilities between ConfigurationData and MappedConfigurationDataPropertySource.

TAMAYA-192: Unified format API and calrified responsibilities between ConfigurationData and MappedConfigurationDataPropertySource.


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

Branch: refs/heads/master
Commit: 773526d6c3cae825ed1198ae08d437e9b6ea4f8d
Parents: dfe2d8a
Author: anatole <an...@apache.org>
Authored: Fri Nov 11 09:42:36 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Fri Nov 11 09:42:36 2016 +0100

----------------------------------------------------------------------
 modules/formats/base/pom.xml                    |  93 ++++++++
 .../BaseFormatPropertySourceProvider.java       | 154 +++++++++++++
 .../apache/tamaya/format/ConfigurationData.java | 165 ++++++++++++++
 .../tamaya/format/ConfigurationDataBuilder.java | 198 +++++++++++++++++
 .../tamaya/format/ConfigurationFormat.java      | 100 +++++++++
 .../tamaya/format/ConfigurationFormats.java     | 181 +++++++++++++++
 .../tamaya/format/InputStreamFactory.java       |  89 ++++++++
 .../MappedConfigurationDataPropertySource.java  | 107 +++++++++
 .../format/formats/IniConfigurationFormat.java  |  95 ++++++++
 .../tamaya/format/formats/PropertiesFormat.java |  71 ++++++
 .../format/formats/PropertiesXmlFormat.java     |  69 ++++++
 .../tamaya/format/formats/package-info.java     |  23 ++
 .../org/apache/tamaya/format/package-info.java  |  28 +++
 ...org.apache.tamaya.format.ConfigurationFormat |  21 ++
 .../tamaya/format/ConfigurationFormatsTest.java |  68 ++++++
 .../tamaya/format/InputStreamFactoryTest.java   | 145 ++++++++++++
 ...ppedConfigurationDataPropertySourceTest.java |  98 +++++++++
 .../formats/base/src/test/resources/Test.ini    |  26 +++
 .../base/src/test/resources/Test.properties     |  21 ++
 modules/formats/common/pom.xml                  |  88 --------
 .../BaseFormatPropertySourceProvider.java       | 154 -------------
 .../apache/tamaya/format/ConfigurationData.java | 206 -----------------
 .../tamaya/format/ConfigurationDataBuilder.java | 219 -------------------
 .../tamaya/format/ConfigurationFormat.java      | 103 ---------
 .../tamaya/format/ConfigurationFormats.java     | 187 ----------------
 .../format/FlattenedDefaultPropertySource.java  | 118 ----------
 .../tamaya/format/InputStreamFactory.java       |  89 --------
 .../format/formats/IniConfigurationFormat.java  |  95 --------
 .../tamaya/format/formats/PropertiesFormat.java |  71 ------
 .../format/formats/PropertiesXmlFormat.java     |  69 ------
 .../tamaya/format/formats/package-info.java     |  23 --
 .../org/apache/tamaya/format/package-info.java  |  28 ---
 ...org.apache.tamaya.format.ConfigurationFormat |  21 --
 .../tamaya/format/ConfigurationFormatsTest.java |  68 ------
 .../FlattenedDefaultPropertySourceTest.java     |  98 ---------
 .../tamaya/format/InputStreamFactoryTest.java   | 145 ------------
 .../formats/common/src/test/resources/Test.ini  |  26 ---
 .../common/src/test/resources/Test.properties   |  21 --
 .../java/org/apache/tamaya/json/JSONFormat.java |   2 +-
 .../json/CommonJSONTestCaseCollection.java      |   2 +-
 .../org/apache/tamaya/json/JSONFormatTest.java  |   4 +-
 .../org/apache/tamaya/json/YAMLFormatTest.java  |   3 -
 42 files changed, 1756 insertions(+), 1836 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/pom.xml
----------------------------------------------------------------------
diff --git a/modules/formats/base/pom.xml b/modules/formats/base/pom.xml
new file mode 100644
index 0000000..04daa47
--- /dev/null
+++ b/modules/formats/base/pom.xml
@@ -0,0 +1,93 @@
+<!-- 
+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 current 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.tamaya.ext</groupId>
+        <artifactId>tamaya-formats-all</artifactId>
+        <version>0.3-incubating-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+    <artifactId>tamaya-formats</artifactId>
+    <name>Apache Tamaya Modules Formats Common</name>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <jdkVersion>1.7</jdkVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-resources</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-spisupport</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- Test scope only, do not create a code dependency! -->
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-core</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>java-hamcrest</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.tamaya.format,
+                            org.apache.tamaya.format.formats
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java
new file mode 100644
index 0000000..84d6cfa
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java
@@ -0,0 +1,154 @@
+/*
+ * 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.format;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of a {@link PropertySourceProvider} that reads configuration from some given resource paths
+ * and using the given formats. The resource path are resolved as classpath resources. This can be changed by
+ * overriding {@link #getPropertySources()}.
+ * For each resource found the configuration formats passed get a chance to read the resource, if they succeed the
+ * result is taken as the providers PropertySources to be exposed.
+ */
+public abstract class BaseFormatPropertySourceProvider implements PropertySourceProvider {
+    /**
+     * The logger used.
+     */
+    private static final Logger LOG = Logger.getLogger(BaseFormatPropertySourceProvider.class.getName());
+    /**
+     * The config formats supported for the given location/resource paths.
+     */
+    private final List<ConfigurationFormat> configFormats = new ArrayList<>();
+    /**
+     * The paths to be evaluated.
+     */
+    private final Collection<URL> paths = new ArrayList<>();
+
+    /**
+     * Creates a new instance.
+     *
+     * @param formats the formats to be used, not null, not empty.
+     * @param paths   the paths to be resolved, not null, not empty.
+     */
+    public BaseFormatPropertySourceProvider(
+            List<ConfigurationFormat> formats,
+            URL... paths) {
+        this.configFormats.addAll(Objects.requireNonNull(formats));
+        this.paths.addAll(Arrays.asList(Objects.requireNonNull(paths)));
+    }
+
+    /**
+     * Creates a new instance, hereby using the current thread context classloader, or if not available the classloader
+     * that loaded this class.
+     * @param formats the formats to be used, not null, not empty.
+     * @param paths   the paths to be resolved, not null, not empty.
+     */
+    public BaseFormatPropertySourceProvider(
+            List<ConfigurationFormat> formats, String... paths) {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if(cl==null){
+            cl = getClass().getClassLoader();
+        }
+        this.configFormats.addAll(Objects.requireNonNull(formats));
+        for(String path:paths) {
+            Enumeration<URL> urls;
+            try {
+                urls = cl.getResources(path);
+            } catch (IOException e) {
+                LOG.log(Level.WARNING, "Failed to read resource: " + path, e);
+                continue;
+            }
+            while(urls.hasMoreElements()) {
+                this.paths.add(urls.nextElement());
+            }
+        }
+    }
+
+    /**
+     * Creates a new instance.
+     *
+     * @param classLoader the ClassLoader to be used, not null, not empty.
+     * @param formats the formats to be used, not null, not empty.
+     * @param paths   the paths to be resolved, not null, not empty.
+     */
+    public BaseFormatPropertySourceProvider(
+            List<ConfigurationFormat> formats,
+            ClassLoader classLoader, String... paths) {
+        this.configFormats.addAll(Objects.requireNonNull(formats));
+        for(String path:paths) {
+            Enumeration<URL> urls;
+            try {
+                urls = classLoader.getResources(path);
+            } catch (IOException e) {
+                LOG.log(Level.WARNING, "Failed to read resource: " + path, e);
+                continue;
+            }
+            while(urls.hasMoreElements()) {
+                this.paths.add(urls.nextElement());
+            }
+        }
+    }
+
+
+    /**
+     * Method to create a {@link org.apache.tamaya.spi.PropertySource} based on the given entries read.
+     *
+     * @param data the configuration data, not null.
+     * @return the {@link org.apache.tamaya.spi.PropertySource} instance ready to be registered.
+     */
+    protected abstract Collection<PropertySource> getPropertySources(ConfigurationData data);
+
+    /**
+     * This method does dynamically resolve the paths using the current ClassLoader set. If no ClassLoader was
+     * explcitly set during creation the current Thread context ClassLoader is used. If none of the supported
+     * formats is able to parse a resource a WARNING log is written.
+     *
+     * @return the PropertySources successfully read
+     */
+    @Override
+    public Collection<PropertySource> getPropertySources() {
+        List<PropertySource> propertySources = new ArrayList<>();
+        for (URL res : this.paths) {
+            try(InputStream is = res.openStream()) {
+                for (ConfigurationFormat format : configFormats) {
+                    ConfigurationData data = format.readConfiguration(res.toString(), is);
+                    propertySources.addAll(getPropertySources(data));
+                }
+            } catch (Exception e) {
+                LOG.log(Level.WARNING, "Failed to put resource based config: " + res, e);
+            }
+        }
+        return propertySources;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationData.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationData.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationData.java
new file mode 100644
index 0000000..c310575
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationData.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.format;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>Data that abstracts the data read from a configuration resources using a certain format. The data can be divided
+ * into different sections, similar to ini-files. Herebey different sections the best map to entries with different
+ * priorities to be applied, when integrated into PropertySource instances.</p>
+ * New instances of this class can be created using a {@link org.apache.tamaya.format.ConfigurationDataBuilder}.
+ * <h3>Implementation Specification</h3>
+ * This class is
+ * <ul>
+ *     <li>immutable</li>
+ *     <li>thread-safe</li>
+ * </ul>
+ */
+public final class ConfigurationData {
+    public static final String DEFAULT_SECTION_NAME = "default";
+    /**
+     * The sections read.
+     */
+    private Map<String, Map<String, String>> namedSections = new HashMap<>();
+    /** The format instance used to read this instance. */
+    private final ConfigurationFormat format;
+    /** The resource read. */
+    private final String resource;
+
+
+    /**
+     * COnstructor used by builder.
+     * @param builder the builder instance passing the read configuration data.
+     */
+    ConfigurationData(ConfigurationDataBuilder builder){
+        this.format = builder.format;
+        this.resource = builder.resource;
+        this.namedSections.putAll(builder.namedSections);
+    }
+
+    /**
+     * Get the {@link org.apache.tamaya.format.ConfigurationFormat} that read this data.
+     * @return the {@link org.apache.tamaya.format.ConfigurationFormat} that read this data, never null.
+     */
+    public ConfigurationFormat getFormat(){
+        return format;
+    }
+
+    /**
+     * Get the resource from which this data was read.
+     * @return the resource from which this data was read, never null.
+     */
+    public String getResource(){
+        return resource;
+    }
+
+    /**
+     * Access an immutable Set of all present section names, including the default section (if any).
+     * @return the set of present section names, never null.
+     */
+    public Set<String> getSectionNames() {
+        if (namedSections == null) {
+            return Collections.emptySet();
+        }
+        return namedSections.keySet();
+    }
+
+    /**
+     * Get a section's data.
+     * @param name the section name, not null.
+     * @return the unmodifiable data of this section, or null,
+     *         if no such section exists.
+     */
+    public Map<String, String> getSection(String name) {
+        return this.namedSections.get(name);
+    }
+
+    /**
+     * Convenience accessor for accessing the 'default' section.
+     * @return the default section's data, or null, if no such section exists.
+     */
+    public Map<String, String> getDefaultProperties() {
+        Map<String,String> props = getSection(DEFAULT_SECTION_NAME);
+        if(props!=null){
+            return Collections.unmodifiableMap(props);
+        }
+        return Collections.emptyMap();
+    }
+
+    /**
+     * Get combined properties for this config data instance, which contains all
+     * properties of all sections in the form {@code Entry<section::property,value>}.
+     *
+     * @return the normalized properties.
+     */
+    public Map<String, String> getCombinedProperties() {
+        Map<String, String> combinedProperties = new HashMap<>();
+        // populate it with sections...
+        for (String sectionName : getSectionNames()) {
+            Map<String, String> section = getSection(sectionName);
+            for (Map.Entry<String, String> en : section.entrySet()) {
+                String key = sectionName + "::" + en.getKey();
+                combinedProperties.put(key, en.getValue());
+            }
+        }
+        return combinedProperties;
+    }
+
+    /**
+     * Immutable accessor to ckeck, if there are default properties present.
+     * @param section the section, not null.
+     * @return true, if default properties are present.
+     */
+    public boolean containsSection(String section) {
+        return this.namedSections.containsKey(section);
+    }
+
+    /**
+     * Immutable accessor to ckeck, if there are default properties present.
+     *
+     * @return true, if default properties are present.
+     */
+    public boolean hasDefaultProperties() {
+        return containsSection(DEFAULT_SECTION_NAME);
+    }
+
+    /**
+     * Checks if no properties are contained in this data item.
+     *
+     * @return true, if no properties are contained in this data item.
+     */
+    public boolean isEmpty() {
+        return !namedSections.isEmpty();
+    }
+
+    @Override
+    public String toString() {
+        return "ConfigurationData{" +
+                "\n  format        = " + format +
+                "\n, resource      = " + resource +
+                "\n, sections      = " + namedSections.keySet() +
+                "\n  default count = " + getDefaultProperties().size() +
+                '}';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java
new file mode 100644
index 0000000..6ac485a
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java
@@ -0,0 +1,198 @@
+/*
+ * 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.format;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+
+/**
+ * Builder for creating {@link org.apache.tamaya.format.ConfigurationData} instances. This class is not thread-safe.
+ */
+public final class ConfigurationDataBuilder {
+
+    /** The format instance used to read this instance. */
+    final ConfigurationFormat format;
+    /** The resource read. */
+    final String resource;
+    /**
+     * The sections read.
+     */
+    Map<String, Map<String, String>> namedSections = new HashMap<>();
+
+    /**
+     * Private constructor.
+     * @param resource the configuration resource URL, not null.
+     * @param format the format that read this data, not null.
+     */
+    private ConfigurationDataBuilder(String resource, ConfigurationFormat format){
+        this.format = Objects.requireNonNull(format);
+        this.resource = Objects.requireNonNull(resource);
+    }
+
+    /**
+     * Creates a new instance.
+     * @param resource the configuration resource URL, not null.
+     * @param format the format that read this data, not null.
+     * @return new instance of this class.
+     */
+    public static ConfigurationDataBuilder of(String resource, ConfigurationFormat format){
+        return new ConfigurationDataBuilder(resource, format);
+    }
+
+    /**
+     * Creates a new instance.
+     * @param data an existing ConfigurationData instances used to initialize the builder.
+     * @return new instance of this class from the given configuration.
+     */
+    public static ConfigurationDataBuilder of(ConfigurationData data){
+        ConfigurationDataBuilder b = new ConfigurationDataBuilder(data.getResource(), data.getFormat());
+        if (!data.isEmpty()) {
+            for(String section:data.getSectionNames()) {
+                b.addSectionProperties(section, data.getSection(section));
+            }
+        }
+        return b;
+    }
+
+    /**
+     * Adds (empty) sections,if they are not yet existing. Already existing sections will not be touched.
+     * @param sections the new sections to put.
+     * @return the builder for chaining.
+     */
+    public ConfigurationDataBuilder addSections(String... sections){
+        for (String section : sections) {
+            if (!namedSections.containsKey(section)) {
+                namedSections.put(section, new HashMap<String, String>());
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Adds a single entry to a target section.
+     * @param section the target section (will be created if not existing).
+     * @param key the entry's key
+     * @param value the entry's value
+     * @return the builder for chaining.
+     */
+    public ConfigurationDataBuilder addSectionProperty(String section, String key, String value) {
+        Map<String, String> map = namedSections.get(section);
+        if (map == null) {
+            map = new HashMap<>();
+            namedSections.put(section, map);
+        }
+        map.put(key, value);
+        return this;
+    }
+
+    /**
+     * Adds a single entry to the <i>default</i> section.
+     * @param key the entry's key
+     * @param value the entry's value
+     * @return the builder for chaining.
+     */
+    public ConfigurationDataBuilder addDefaultProperty(String key, String value) {
+        return addSectionProperty("default", key, value);
+    }
+
+    /**
+     * Adds a single entry to the <i>default</i> section.
+     * @param key the entry's key
+     * @param value the entry's value
+     * @return the builder for chaining.
+     * @deprecated Use {@link #addDefaultProperty(String, String)} instead of.
+     */
+    @Deprecated
+    public ConfigurationDataBuilder addProperty(String key, String value) {
+        return addDefaultProperty(key, value);
+    }
+
+    /**
+     * Adds the given entries to the given section, all existing values will be overridden.
+     * @param section the target section (will be created if not existing).
+     * @param properties the entry's data
+     * @return the builder for chaining.
+     */
+    public ConfigurationDataBuilder addSectionProperties(String section, Map<String, String> properties) {
+        Map<String, String> map = namedSections.get(section);
+        if (map == null) {
+            map = new HashMap<>();
+            namedSections.put(section, map);
+        }
+        map.putAll(properties);
+        return this;
+    }
+
+    /**
+     * Adds the given entries to the <i>default</i> section, all existing values will be overridden.
+     * @param properties the entry's data
+     * @return the builder for chaining.
+     * @deprecated Use {@link #addDefaultProperties(Map)} instead of.
+     */
+    @Deprecated
+    public ConfigurationDataBuilder addProperties(Map<String, String> properties) {
+        return addDefaultProperties(properties);
+    }
+
+
+        /**
+         * Adds the given entries to the <i>default</i> section, all existing values will be overridden.
+         * @param properties the entry's data
+         * @return the builder for chaining.
+         */
+    public ConfigurationDataBuilder addDefaultProperties(Map<String, String> properties) {
+        Map<String,String> defaultProps = this.namedSections.get("default");
+        if(defaultProps==null){
+            defaultProps = new HashMap<>();
+            this.namedSections.put("default", defaultProps);
+        }
+        defaultProps.putAll(properties);
+        return this;
+    }
+
+
+    /**
+     * Access the current named sections, if not present a new instance is initialized.
+     *
+     * @return the current named sections, never null.
+     */
+    public Set<String> getSectionNames() {
+        return namedSections.keySet();
+    }
+
+    /**
+     * Builds a new {@link org.apache.tamaya.format.ConfigurationData} instance.
+     * @return a new {@link org.apache.tamaya.format.ConfigurationData} instance, not null.
+     */
+    public ConfigurationData build(){
+        return new ConfigurationData(this);
+    }
+
+    @Override
+    public String toString() {
+        return "ConfigurationDataBuilder{" +
+                "\n  format=" + format +
+                "\n  sections=" + namedSections.keySet() +
+                "\n  resource=" + resource +
+                "\n}";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
new file mode 100644
index 0000000..ee11207
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
@@ -0,0 +1,100 @@
+/*
+ * 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.format;
+
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * <p>Implementations current this class encapsulate the mechanism how to read a
+ * resource including interpreting the format correctly (e.g. xml vs.
+ * properties vs. ini). In most cases file only contains entries of the same priority, which would then
+ * result in only one {@link org.apache.tamaya.spi.PropertySource}. Complex file formats, however, may contain entries
+ * of different priorities. In this cases, each ordinal type found typically is returned as a separate section so the
+ * consuming {@link org.apache.tamaya.spi.PropertySourceProvider} implementation can distribute the different part to
+ * individual {@link org.apache.tamaya.spi.PropertySource}s.</p>
+ *
+ * <h3>Implementation Requirements</h3>
+ * Implementations of this type must be
+ * <ul>
+ *     <li>thread-safe</li>
+ * </ul>
+ */
+public interface ConfigurationFormat {
+
+    /**
+     * Get a unique name of the format. This name can be used to access the format.
+     * @return the (unique) format's name, never null and not empty.
+     */
+    String getName();
+
+    /**
+     * Allows the format to examine the given resource, e.g. for a matching file ending. Only, if a format accepts an
+     * URL, it will be tried for reading the configuration.
+     * @param url the url to read the configuration data from (could be a file, a server location, a classpath
+     *            resource or something else, not null.
+     * @return true, if this format accepts the given URL for reading.
+     */
+    boolean accepts(URL url);
+
+    /**
+     * Reads a configuration from an URL, hereby parsing the given {@link java.io.InputStream}. Dependening on
+     * the capabilities of the format the returned {@link org.apache.tamaya.format.ConfigurationData} may contain
+     * different levels of data:
+     * <ul>
+     *     <li>Only a <i>default</i> section is returned, since the configuration format does not support
+     *     hierarchies. This is the case for properties and xml properties.</li>
+     *     <li>Hierarchical formats such as INI, XML and JSON can map each node to a section. Each section
+     *     can have its own key/value pairs. This allows to map also complex formats in a generic way. A
+     *     format implementation should then additionally flatten the whole data and store it in a accessible as
+     *     {@link ConfigurationData#getCombinedProperties()}. This allows to use the properties as inout to a default mapping,
+     *     which is always appropriate as long as no other semnatics
+     *     are defined in the concrete target scenario.</li>
+     *     <li>More complex custom scenarios should map their configuration data read into different
+     *     sections. Typically the data will be mapped into different {@link org.apache.tamaya.spi.PropertySource}
+     *     instances with different ordinal levels. As an example imagine a custom format that contains sections
+     *     'defaults', 'global-defaults', 'application', 'server-overrides'.</li>
+     *     <li>Alternate formats</li>
+     * </ul>
+     *
+     * Summarizing implementations common formats should always provide
+     * <ul>
+     *     <li>the data organized in sections as useful for the given format. If data is organized in one section, it
+     *     should be mapped into the DEFAULT section.</li>
+     *     <li>Formats that do provide multiple sections, should always provide a FLATTENED section as well, where
+     *     all the data is organized as a flattened key/value pairs, enabling a generic mapping to a
+     *     {@link org.apache.tamaya.spi.PropertySource}.</li>
+     * </ul>
+     *
+     * If the configuration format only contains entries of one ordinal type, normally only one single
+     * instance of PropertySource is returned (the corresponding key/values should end up in the DEFAULT section).
+     * Nevertheless custom formats may contain different sections or parts,
+     * where each part maps to a different target ordinal (eg defaults, domain config and app config). In the
+     * ladder case multiple PropertySources can be returned, each one with its own ordinal and the corresponding
+     * entries.
+     * @see org.apache.tamaya.spi.PropertySource
+     * @param resource a descriptive name for the resource, since an InputStream does not have any)
+     * @param inputStream the inputStream to read the configuration data from (could be a file, a server location, a classpath
+     *            resource or something else.
+     * @return the corresponding {@link ConfigurationData} containing sections/properties read, never {@code null}.
+     * @throws org.apache.tamaya.ConfigException if parsing of the input fails.
+     */
+    ConfigurationData readConfiguration(String resource, InputStream inputStream);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java
new file mode 100644
index 0000000..c6b85bf
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java
@@ -0,0 +1,181 @@
+/*
+ * 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.format;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tamaya.spi.ServiceContextManager;
+
+/**
+ * Small accessor and management class dealing with {@link org.apache.tamaya.format.ConfigurationFormat}
+ * instances.
+ */
+public final class ConfigurationFormats {
+    /**
+     * The logger used.
+     */
+    private static final Logger LOG = Logger.getLogger(ConfigurationFormats.class.getName());
+
+    /**
+     * Singleton constructor.
+     */
+    private ConfigurationFormats() {
+    }
+
+    /**
+     * Get all currently available formats, ordered by priority.
+     *
+     * @return the currently available formats, never null.
+     */
+    public static List<ConfigurationFormat> getFormats() {
+        return ServiceContextManager.getServiceContext().getServices(ConfigurationFormat.class);
+    }
+
+    /**
+     * Get all currently available formats, ordered by priority.
+     *
+     * @param formatNames available formats to be ordered.
+     * @return the currently available formats, never null.
+     */
+    public static List<ConfigurationFormat> getFormats(String... formatNames) {
+        final List<ConfigurationFormat> result = new ArrayList<>();
+        final Set<String> names = new HashSet<>(Arrays.asList(formatNames));
+        for (final ConfigurationFormat f : getFormats()) {
+            if (names.contains(f.getName())) {
+                result.add(f);
+            }
+        }
+        return result;
+    }
+
+    // Activate for JDK 8...
+//    /**
+//     * Get all currently available formats, ordered by priority.
+//     *
+//     * @return the currently available formats, never null.
+//     */
+//    public static List<ConfigurationFormat> getFormats(Predicate<String> namePredicate) {
+//        List<ConfigurationFormat> result = new ArrayList<>();
+//        for(ConfigurationFormat f:getFormats()){
+//            if(namePredicate.test(f.getName()){
+//                result.add(f);
+//            }
+//        }
+//        return result;
+//    }
+
+    /**
+     * Get all currently available formats, ordered by priority.
+     *
+     * @param url source to read configuration from.
+     * @return the currently available formats, never null.
+     */
+    public static List<ConfigurationFormat> getFormats(final URL url) {
+        final List<ConfigurationFormat> formats = getFormats();
+        final List<ConfigurationFormat> result = new ArrayList<>();
+        for (final ConfigurationFormat f : formats) {
+            if (f.accepts(url)) {
+                result.add(f);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Tries to read configuration data from a given URL, hereby traversing all known formats in order of precedence.
+     * Hereby the formats are first filtered to check if the URL is acceptable, before the input is being parsed.
+     *
+     * @param url the url from where to read, not null.
+     * @return the ConfigurationData read, or null.
+     * @throws IOException if the resource cannot be read.
+     */
+    public static ConfigurationData readConfigurationData(final URL url) throws IOException {
+        final List<ConfigurationFormat> formats = getFormats(url);
+        return readConfigurationData(url, formats.toArray(new ConfigurationFormat[formats.size()]));
+    }
+
+    /**
+     * Tries to read configuration data from a given URL, hereby explicitly trying all given formats in order.
+     *
+     * @param url     the url from where to read, not null.
+     * @param formats the formats to try.
+     * @return the ConfigurationData read, or null.
+     * @throws IOException if the resource cannot be read.
+     */
+    public static ConfigurationData readConfigurationData(URL url, ConfigurationFormat... formats) throws IOException {
+        return readConfigurationData(url.toString(), url.openStream(), formats);
+    }
+
+    /**
+     * @param urls    the urls from where to read, not null.
+     * @param formats the formats to try.
+     * @return the {@link org.apache.tamaya.format.ConfigurationData} of the files successfully decoded by the
+     * given formats.
+     */
+    public static Collection<ConfigurationData> getPropertySources(Collection<URL> urls, ConfigurationFormat... formats) {
+        final List<ConfigurationData> dataRead = new ArrayList<>();
+        for (final URL url : urls) {
+            try {
+                final ConfigurationData data = readConfigurationData(url, formats);
+                if (data != null) {
+                    dataRead.add(data);
+                }
+            } catch (final Exception e) {
+                LOG.log(Level.SEVERE, "Error reading file: " + url.toExternalForm(), e);
+            }
+        }
+        return dataRead;
+    }
+
+    /**
+     * Tries to read configuration data from a given URL, hereby explicitly trying all given formats in order.
+     *
+     * @param resource    a descriptive name for the resource, since an InputStream does not have any
+     * @param inputStream the inputStream from where to read, not null.
+     * @param formats     the formats to try.
+     * @return the ConfigurationData read, or null.
+     * @throws IOException if the resource cannot be read.
+     */
+    public static ConfigurationData readConfigurationData(String resource, InputStream inputStream,
+                                                          ConfigurationFormat... formats) throws IOException {
+        Objects.requireNonNull(inputStream);
+        Objects.requireNonNull(resource);
+        try(InputStreamFactory isFactory = new InputStreamFactory(inputStream)) {
+            for (final ConfigurationFormat format : formats) {
+                try (InputStream is = isFactory.createInputStream()) {
+                    final ConfigurationData data = format.readConfiguration(resource, is);
+                    if (data != null) {
+                        return data;
+                    }
+                } catch (final Exception e) {
+                    LOG.log(Level.INFO,
+                            "Format " + format.getClass().getName() + " failed to read resource " + resource, e);
+                }
+            }
+        }
+        return null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/InputStreamFactory.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/InputStreamFactory.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/InputStreamFactory.java
new file mode 100644
index 0000000..912dd08
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/InputStreamFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.format;
+
+import java.io.*;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Wrapper for a given {@link InputStream} to be able to close
+ * it via the try-with-resources construct of Java 7.
+ *
+ * <h1>Usage example</h1>
+ *
+ * <pre>
+ * public void readIt(InputStream inputStream) {
+ *    try (InputStream is = new ParallelInputStream(inputStream) {
+ *        // Consume the stream
+ *    }
+ * }
+ * </pre>
+ */
+public class InputStreamFactory implements Closeable {
+    private static final Logger LOG = Logger.getLogger(InputStreamFactory.class.getName());
+
+    private byte[] data;
+
+    /**
+     * Creates a new InputStreamFactory.
+     *
+     * @param original the InputStream to be read for extract its data into memory.
+     * @throws IOException if thrown by the original during read.
+     */
+    public InputStreamFactory(InputStream original) throws IOException {
+        Objects.requireNonNull(original);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        byte[] bytes = new byte[256];
+        try {
+            int read = original.read(bytes);
+            while (read > 0) {
+                bos.write(bytes, 0, read);
+                read = original.read(bytes);
+            }
+            this.data = bos.toByteArray();
+        } finally {
+            try {
+                original.close();
+            } catch (IOException e) {
+                LOG.log(Level.FINEST, "Error closing stream: " + original, e);
+            }
+        }
+    }
+
+    /**
+     * Creates a new InputStream with the same data as provided by the InputStream passed on factory creation.
+     *
+     * @return a new InputStream , never null.
+     * @throws IOException if no data is available.
+     */
+    public InputStream createInputStream() throws IOException {
+        byte[] bytes = this.data;
+        if (bytes == null) {
+            throw new IOException("InputStreamFactory is closed.");
+        }
+        return new ByteArrayInputStream(bytes);
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.data = null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/MappedConfigurationDataPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/MappedConfigurationDataPropertySource.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/MappedConfigurationDataPropertySource.java
new file mode 100644
index 0000000..e47652c
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/MappedConfigurationDataPropertySource.java
@@ -0,0 +1,107 @@
+/*
+ * 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.format;
+
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spisupport.BasePropertySource;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Mapped PropertySource that uses the flattened config data read from an URL by a
+ * {@link org.apache.tamaya.format.ConfigurationFormat}.
+ */
+public class MappedConfigurationDataPropertySource extends BasePropertySource {
+    private static final Logger LOG = Logger.getLogger(MappedConfigurationDataPropertySource.class.getName());
+    private final Map<String, String> properties;
+    private final ConfigurationData data;
+
+
+    /*
+     * Constructor, uses hereby the flattened config data read from an URL by a
+     * ${@link org.apache.tamaya.format.ConfigurationFormat}.
+     * Hereby it reads the <i>default</i> properties as is and adds properties
+     * contained in a section as {@code Entry<section.propertyName,value>}.
+     * @see ConfigurationData#getCombinedProperties()
+     */
+    public MappedConfigurationDataPropertySource(ConfigurationData data) {
+        this.properties = Collections.unmodifiableMap(populateData(data));
+        this.data = data;
+    }
+
+    /*
+     * Constructor, uses hereby the flattened config data read from an URL by a
+     * ${@link org.apache.tamaya.format.ConfigurationFormat}.
+     * Hereby it reads the <i>default</i> properties as is and adds properties
+     * contained in a section as {@code Entry<section.propertyName,value>}.
+     * @see ConfigurationData#getCombinedProperties()
+     */
+    public MappedConfigurationDataPropertySource(int defaultOrdinal, ConfigurationData data) {
+        super(defaultOrdinal);
+        this.properties = Collections.unmodifiableMap(populateData(data));
+        this.data = data;
+    }
+
+    /**
+     * Method that copies and converts the properties read from the data instance
+     * provided.
+     * @param data the data returned from the format, not null.
+     * @return the final properties to be included.
+     */
+    protected Map<String, String> populateData(ConfigurationData data) {
+        Map<String, String> result = new HashMap<>();
+        for(String section:data.getSectionNames()){
+            for(Map.Entry<String,String> en:data.getSection(section).entrySet()){
+                if("default".equals(section)){
+                    result.put(en.getKey(), en.getValue());
+                }else {
+                    result.put(section + '.' + en.getKey(), en.getValue());
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String getName() {
+        String name = this.properties.get("_name");
+        if (name == null) {
+            name = this.data.getResource();
+        }
+        if (name == null) {
+            name = getClass().getSimpleName();
+        }
+        return name;
+    }
+
+    @Override
+    public PropertyValue get(String key) {
+        String val = properties.get(key);
+        return PropertyValue.of(key, val, getName());
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java
new file mode 100644
index 0000000..ea52367
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java
@@ -0,0 +1,95 @@
+/*
+ * 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.format.formats;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.format.ConfigurationData;
+import org.apache.tamaya.format.ConfigurationDataBuilder;
+import org.apache.tamaya.format.ConfigurationFormat;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implements a ini file format.
+ */
+public class IniConfigurationFormat implements ConfigurationFormat {
+
+    /**
+     * The logger.
+     */
+    private final static Logger LOG = Logger.getLogger(IniConfigurationFormat.class.getName());
+
+    @Override
+    public String getName() {
+        return "ini";
+    }
+
+    @Override
+    public boolean accepts(URL url) {
+        String fileName = url.getFile();
+        return fileName.endsWith(".ini") || fileName.endsWith(".INI");
+    }
+
+    @Override
+    public ConfigurationData readConfiguration(String resource, InputStream inputStream) {
+        ConfigurationDataBuilder builder = ConfigurationDataBuilder.of(resource, this);
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
+            String line = reader.readLine();
+            int lineNum = 0;
+            String section = null;
+            while (line != null) {
+                lineNum++;
+                line = line.trim();
+                if (line.isEmpty()) {
+                    line = reader.readLine();
+                    continue;
+                }
+                if (line.startsWith("[")) {
+                    int end = line.indexOf(']');
+                    if (end < 0) {
+                        throw new ConfigException(
+                                "Invalid INI-Format, ']' expected, at " + lineNum + " in " + resource);
+                    }
+                    section = line.substring(1, end);
+                } else if (line.trim().startsWith("#")) {
+                    // comment
+                } else {
+                    int sep = line.indexOf('=');
+                    String key = line.substring(0, sep);
+                    String value = line.substring(sep + 1);
+                    if (section != null) {
+                        builder.addSectionProperty(section, key, value);
+                    } else {
+                        builder.addDefaultProperty(key, value);
+                    }
+                }
+                line = reader.readLine();
+            }
+            return builder.build();
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Could not read configuration: " + resource, e);
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java
new file mode 100644
index 0000000..c45185b
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java
@@ -0,0 +1,71 @@
+/*
+ * 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.format.formats;
+
+import org.apache.tamaya.format.ConfigurationData;
+import org.apache.tamaya.format.ConfigurationDataBuilder;
+import org.apache.tamaya.format.ConfigurationFormat;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of a {@link org.apache.tamaya.format.ConfigurationFormat} for -properties files.
+ *
+ * @see java.util.Properties#load(java.io.InputStream)
+ */
+public class PropertiesFormat implements ConfigurationFormat {
+    /**
+     * The logger.
+     */
+    private final static Logger LOG = Logger.getLogger(PropertiesFormat.class.getName());
+
+
+    @Override
+    public String getName() {
+        return "properties";
+    }
+
+    @Override
+    public boolean accepts(URL url) {
+        String fileName = url.getFile();
+        return fileName.endsWith(".properties") || fileName.endsWith(".PROPERTIES") ||
+                fileName.endsWith(".conf") || fileName.endsWith(".CONF");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ConfigurationData readConfiguration(String resource, InputStream inputStream) {
+        Objects.requireNonNull(inputStream);
+        Objects.requireNonNull(resource);
+        try {
+            final Properties p = new Properties();
+            p.load(inputStream);
+            return ConfigurationDataBuilder.of(resource, this).addDefaultProperties(Map.class.cast(p)).build();
+        } catch (Exception e) {
+            LOG.log(Level.FINEST, "Failed to read config from resource: " + resource, e);
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java
new file mode 100644
index 0000000..df150ea
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java
@@ -0,0 +1,69 @@
+/*
+ * 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.format.formats;
+
+import org.apache.tamaya.format.ConfigurationData;
+import org.apache.tamaya.format.ConfigurationDataBuilder;
+import org.apache.tamaya.format.ConfigurationFormat;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of a {@link org.apache.tamaya.format.ConfigurationFormat} for xml property
+ * files.
+ *
+ * @see java.util.Properties#loadFromXML(java.io.InputStream)
+ */
+public class PropertiesXmlFormat implements ConfigurationFormat {
+    /**
+     * The logger.
+     */
+    private final static Logger LOG = Logger.getLogger(PropertiesXmlFormat.class.getName());
+
+    @Override
+    public String getName() {
+        return "xml-properties";
+    }
+
+    @Override
+    public boolean accepts(URL url) {
+        String fileName = url.getFile();
+        return fileName.endsWith(".xml") || fileName.endsWith(".XML");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ConfigurationData readConfiguration(String resource, InputStream inputStream) {
+        Objects.requireNonNull(inputStream);
+        Objects.requireNonNull(resource);
+
+        try {
+            final Properties p = new Properties();
+            p.loadFromXML(inputStream);
+            return ConfigurationDataBuilder.of(resource, this).addDefaultProperties(Map.class.cast(p)).build();
+        } catch (Exception e) {
+            LOG.log(Level.FINEST, "Failed to read config from resource: " + resource, e);
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/package-info.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/package-info.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/package-info.java
new file mode 100644
index 0000000..db8987d
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/formats/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * This package provides implementtion of {@link org.apache.tamaya.format.ConfigurationFormat}
+ * for properties, xml-properties and ini files.
+ */
+package org.apache.tamaya.format.formats;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/java/org/apache/tamaya/format/package-info.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/java/org/apache/tamaya/format/package-info.java b/modules/formats/base/src/main/java/org/apache/tamaya/format/package-info.java
new file mode 100644
index 0000000..39b5f0b
--- /dev/null
+++ b/modules/formats/base/src/main/java/org/apache/tamaya/format/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+/**
+ * This package provides an abstraction for parsing a configuration
+ * from an input strem, called {@link org.apache.tamaya.format.ConfigurationFormat}
+ * and corresponding helper artifacts.
+ *
+ * @see org.apache.tamaya.format.ConfigurationFormat
+ * @see org.apache.tamaya.format.ConfigurationData
+ * @see org.apache.tamaya.format.ConfigurationFormats
+ */
+package org.apache.tamaya.format;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat b/modules/formats/base/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat
new file mode 100644
index 0000000..96e898f
--- /dev/null
+++ b/modules/formats/base/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat
@@ -0,0 +1,21 @@
+#
+# 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 current 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.
+#
+org.apache.tamaya.format.formats.IniConfigurationFormat
+org.apache.tamaya.format.formats.PropertiesFormat
+org.apache.tamaya.format.formats.PropertiesXmlFormat
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java b/modules/formats/base/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java
new file mode 100644
index 0000000..0839714
--- /dev/null
+++ b/modules/formats/base/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.format;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests for {@link org.apache.tamaya.format.ConfigurationFormats}.
+ */
+public class ConfigurationFormatsTest {
+
+    @org.junit.Test
+    public void testGetFormats() throws Exception {
+        List<ConfigurationFormat> formats = ConfigurationFormats.getFormats();
+        assertNotNull(formats);
+        assertEquals(formats.size(), 3);
+    }
+
+    @org.junit.Test
+    public void testReadConfigurationData() throws Exception {
+        List<ConfigurationFormat> formats = ConfigurationFormats.getFormats(getClass().getResource("/Test.ini"));
+        assertNotNull(formats);
+        assertEquals(formats.size(), 1);
+        formats = ConfigurationFormats.getFormats(getClass().getResource("/Test.properties"));
+        assertNotNull(formats);
+        assertEquals(formats.size(), 1);
+//        formats = ConfigurationFormats.getFormats(getClass().getResource("/Test.xml"));
+//        assertNotNull(formats);
+//        assertEquals(formats.size(), 1);
+
+    }
+
+    @org.junit.Test
+    public void testReadConfigurationData_URL() throws Exception {
+        ConfigurationData data = ConfigurationFormats.readConfigurationData(getClass().getResource("/Test.ini"));
+        assertNotNull(data);
+        data = ConfigurationFormats.readConfigurationData(getClass().getResource("/Test.properties"));
+        assertNotNull(data);
+    }
+
+    @org.junit.Test
+    public void testReadConfigurationData2() throws Exception {
+        List<ConfigurationFormat> formats = ConfigurationFormats.getFormats();
+        ConfigurationData data = ConfigurationFormats.readConfigurationData(getClass().getResource("/Test.ini"),
+                formats.toArray(new ConfigurationFormat[formats.size()]));
+        assertNotNull(data);
+        System.out.println(data);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java b/modules/formats/base/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java
new file mode 100644
index 0000000..c05da09
--- /dev/null
+++ b/modules/formats/base/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.format;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class InputStreamFactoryTest {
+
+    @Test(expected = NullPointerException.class)
+    public void ctorEnforcesNonNullOriginal() throws IOException {
+        new InputStreamFactory(null);
+    }
+
+    @Test
+    public void givenStreamIsClosedInTryWithResourcesConstruct() throws Exception {
+        InputStream stream = mock(InputStream.class);
+        doReturn(34).when(stream).read();
+
+        InputStreamFactory factory = new InputStreamFactory(stream);
+        verify(stream).close();
+        for (int i = 0; i < 100; i++) {
+            try (InputStream in = factory.createInputStream()) {
+                in.read();
+            }
+        }
+        verify(stream).close();
+    }
+
+    @Test
+    public void callToReadIsNotForwardedCallToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        byte[] byteArray = new byte[4];
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            assertThat(is.read(byteArray), equalTo(4));
+        }
+    }
+
+
+    @Test
+    public void callToSkipIsForwardedToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            assertThat(is.skip(2L), equalTo(2L));
+        }
+    }
+
+
+    @Test
+    public void callToAvailableIsNotForwardedToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            assertThat(is.available(), equalTo(4));
+        }
+    }
+
+    @Test
+    public void callToCloseIsNotForwardedToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            is.close();
+        }
+    }
+
+    @Test
+    public void callToMarkIsNotForwardedToWrapped() throws IOException {
+//        ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            is.mark(2);
+        }
+    }
+
+
+    @Test
+    public void callToResetIsNotForwardedToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            is.reset();
+        }
+    }
+
+    @Test
+    public void callToMarkSupportedIsNotForwardedToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            assertThat(is.markSupported(), is(true));
+        }
+    }
+
+    @Test
+    public void callToReadIsForwardedToWrapped() throws IOException {
+        InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4});
+        InputStreamFactory closer = new InputStreamFactory(stream);
+        for (int i = 0; i < 100; i++) {
+            InputStream is = closer.createInputStream();
+            assertThat(is.read(), equalTo(1));
+            assertThat(is.read(), equalTo(2));
+            assertThat(is.read(), equalTo(3));
+            assertThat(is.read(), equalTo(4));
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/test/java/org/apache/tamaya/format/MappedConfigurationDataPropertySourceTest.java
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/test/java/org/apache/tamaya/format/MappedConfigurationDataPropertySourceTest.java b/modules/formats/base/src/test/java/org/apache/tamaya/format/MappedConfigurationDataPropertySourceTest.java
new file mode 100644
index 0000000..1e18187
--- /dev/null
+++ b/modules/formats/base/src/test/java/org/apache/tamaya/format/MappedConfigurationDataPropertySourceTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.format;
+
+import org.apache.tamaya.format.formats.PropertiesFormat;
+import org.apache.tamaya.spi.PropertySource;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Tests for {@link MappedConfigurationDataPropertySource}.
+ */
+public class MappedConfigurationDataPropertySourceTest {
+
+    @Test
+    public void testGetName() throws Exception {
+        MappedConfigurationDataPropertySource ps = new MappedConfigurationDataPropertySource(createConfigurationData("test1"));
+        assertEquals("test1", ps.getName());
+    }
+
+    private ConfigurationData createConfigurationData(String sourceName) {
+        return ConfigurationDataBuilder.of(sourceName, new PropertiesFormat())
+                .addDefaultProperty("a", "aValue").addSectionProperty("section1", "sectionKey1", "sectionValue11")
+                .addSections("section1", "section12")
+                .addSectionProperty("section2", "sectionKey1", "sectionValue21").build();
+    }
+
+    private ConfigurationData createConfigurationData(String sourceName, int ordinal) {
+        return ConfigurationDataBuilder.of(sourceName, new PropertiesFormat())
+                .addDefaultProperty("a", "aValue").addSectionProperty("section1", "sectionKey1", "sectionValue11")
+                .addSections("section1", "section12").addDefaultProperty(PropertySource.TAMAYA_ORDINAL, String.valueOf(ordinal))
+                .addSectionProperty("section2", "sectionKey1", "sectionValue21").build();
+    }
+
+    private ConfigurationData createConfigurationDataNoDefault(String sourceName) {
+        return ConfigurationDataBuilder.of(sourceName, new PropertiesFormat())
+                .addSectionProperty("section1", "sectionKey1", "sectionValue11")
+                .addSections("section1", "section12")
+                .addSectionProperty("section2", "sectionKey1", "sectionValue21").build();
+    }
+
+    @Test
+    public void testGetOrdinal() throws Exception {
+        MappedConfigurationDataPropertySource ps = new MappedConfigurationDataPropertySource(createConfigurationData("test1", 11));
+        assertEquals(11, ps.getOrdinal());
+    }
+
+    @Test
+    public void testGet() throws Exception {
+        MappedConfigurationDataPropertySource ps = new MappedConfigurationDataPropertySource(createConfigurationData("test2"));
+        assertEquals("aValue", ps.get("a").get("a"));
+        assertNotNull(ps.get("section1.sectionKey1").get("section1.sectionKey1"));
+        assertNotNull(ps.get("section2.sectionKey1").get("section2.sectionKey1"));
+        assertNull(ps.get("sectionKey1"));
+        ps = new MappedConfigurationDataPropertySource(createConfigurationDataNoDefault("test2"));
+        assertEquals("sectionValue11", ps.get("section1.sectionKey1").get("section1.sectionKey1"));
+        assertEquals("sectionValue21", ps.get("section2.sectionKey1").get("section2.sectionKey1"));
+        assertNull(ps.get("a"));
+        assertNull(ps.get("section1"));
+    }
+
+    @Test
+    public void testGetProperties() throws Exception {
+        MappedConfigurationDataPropertySource ps = new MappedConfigurationDataPropertySource(createConfigurationData("test3"));
+        assertNotNull(ps.getProperties());
+        assertEquals("aValue", ps.getProperties().get("a"));
+        assertNotNull(ps.getProperties().get("section1.sectionKey1"));
+        assertNotNull(ps.getProperties().get("section2.sectionKey1"));
+        assertNull(ps.getProperties().get("section1.sectionKey2"));
+        assertNull(ps.getProperties().get("section2.sectionKey2"));
+        assertNull(ps.getProperties().get("sectionKey1"));
+        assertNull(ps.getProperties().get("sectionKey2"));
+        ps = new MappedConfigurationDataPropertySource(createConfigurationDataNoDefault("test3"));
+        assertNotNull(ps.getProperties());
+        assertEquals("sectionValue11", ps.getProperties().get("section1.sectionKey1"));
+        assertEquals("sectionValue21", ps.getProperties().get("section2.sectionKey1"));
+        assertNull(ps.get("section1"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/test/resources/Test.ini
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/test/resources/Test.ini b/modules/formats/base/src/test/resources/Test.ini
new file mode 100644
index 0000000..906a1e6
--- /dev/null
+++ b/modules/formats/base/src/test/resources/Test.ini
@@ -0,0 +1,26 @@
+#
+# 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 current 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.
+#
+
+aGeneralEntry=blabla
+
+[MySection1]
+sectionEntry1=value1
+
+[MySection2]
+sectionEntry2=value2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/base/src/test/resources/Test.properties
----------------------------------------------------------------------
diff --git a/modules/formats/base/src/test/resources/Test.properties b/modules/formats/base/src/test/resources/Test.properties
new file mode 100644
index 0000000..ced544b
--- /dev/null
+++ b/modules/formats/base/src/test/resources/Test.properties
@@ -0,0 +1,21 @@
+#
+# 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 current 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.
+#
+aGeneralEntry=blabla
+MySection1.sectionEntry1=value1
+MySection2.sectionEntry2=value2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/773526d6/modules/formats/common/pom.xml
----------------------------------------------------------------------
diff --git a/modules/formats/common/pom.xml b/modules/formats/common/pom.xml
deleted file mode 100644
index 93f4bd2..0000000
--- a/modules/formats/common/pom.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<!-- 
-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 current 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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.tamaya.ext</groupId>
-        <artifactId>tamaya-formats-all</artifactId>
-        <version>0.3-incubating-SNAPSHOT</version>
-        <relativePath>..</relativePath>
-    </parent>
-    <artifactId>tamaya-formats</artifactId>
-    <name>Apache Tamaya Modules Formats</name>
-    <packaging>bundle</packaging>
-
-    <properties>
-        <jdkVersion>1.7</jdkVersion>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.tamaya</groupId>
-            <artifactId>tamaya-api</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tamaya.ext</groupId>
-            <artifactId>tamaya-resources</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <!-- Test scope only, do not create a code dependency! -->
-        <dependency>
-            <groupId>org.apache.tamaya</groupId>
-            <artifactId>tamaya-core</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>java-hamcrest</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.tamaya.format,
-                            org.apache.tamaya.format.formats
-                        </Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>