http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/java/org/apache/tamaya/spi/FilterContextTest.java 
b/code/compat/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
new file mode 100644
index 0000000..e272b9a
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.spi;
+
+import org.apache.tamaya.spi.FilterContext;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link org.apache.tamaya.spi.FilterContext}.
+ */
+public class FilterContextTest {
+
+    @Test(expected = NullPointerException.class)
+    public void constructorRequiresNonNullPropertyValueTwoParameterVariant() {
+        new org.apache.tamaya.spi.FilterContext(null, new TestConfigContext());
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void 
constructorRequiresNonNullConfigurationContextTwoParameterVariant() {
+        new org.apache.tamaya.spi.FilterContext(PropertyValue.of("a", "b", 
"s"), null);
+    }
+
+    @SuppressWarnings("unchecked")
+       @Test(expected = NullPointerException.class)
+    public void constructorRequiresNonNullPropertyValueThreeParameterVariant() 
{
+        new org.apache.tamaya.spi.FilterContext(null, Collections.EMPTY_MAP, 
new TestConfigContext());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(expected = NullPointerException.class)
+    public void 
constructorRequiresNonNullConfigurationContextThreeParameterVariant() {
+        new org.apache.tamaya.spi.FilterContext(PropertyValue.of("a", "b", 
"s"), Collections.EMPTY_MAP, null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void 
constructorRequiresNonNullMapForConfigEntriesThreeParameterVariant() {
+        new org.apache.tamaya.spi.FilterContext(PropertyValue.of("a", "b", 
"s"), null, new TestConfigContext());
+    }
+
+    @Test
+    public void getKey() throws Exception {
+        PropertyValue val = PropertyValue.of("getKey", "v", "");
+        org.apache.tamaya.spi.FilterContext ctx = new 
org.apache.tamaya.spi.FilterContext(val,
+                new HashMap<String,PropertyValue>(), new TestConfigContext());
+        assertEquals(val, ctx.getProperty());
+    }
+
+    @Test
+    public void isSinglePropertyScoped() throws Exception {
+        PropertyValue val = PropertyValue.of("isSinglePropertyScoped", "v", 
"");
+        org.apache.tamaya.spi.FilterContext ctx = new 
org.apache.tamaya.spi.FilterContext(val, new HashMap<String,PropertyValue>(), 
new TestConfigContext());
+        assertEquals(false, ctx.isSinglePropertyScoped());
+        ctx = new org.apache.tamaya.spi.FilterContext(val, new 
TestConfigContext());
+        assertEquals(true, ctx.isSinglePropertyScoped());
+    }
+
+    @Test
+    public void getConfigEntries() throws Exception {
+        Map<String,PropertyValue> config = new HashMap<>();
+        for(int i=0;i<10;i++) {
+            config.put("key-"+i, PropertyValue.of("key-"+i, "value-"+i, 
"test"));
+        }
+        PropertyValue val = PropertyValue.of("getConfigEntries", "v", "");
+        org.apache.tamaya.spi.FilterContext ctx = new 
org.apache.tamaya.spi.FilterContext(val, config, new TestConfigContext());
+        assertEquals(config, ctx.getConfigEntries());
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        Map<String,PropertyValue> config = new HashMap<>();
+        for(int i=0;i<2;i++) {
+            config.put("key-"+i, PropertyValue.of("key-"+i, "value-"+i, 
"test"));
+        }
+        PropertyValue val = PropertyValue.of("testToString", "val", 
"mySource");
+        org.apache.tamaya.spi.FilterContext ctx = new FilterContext(val, 
config, new TestConfigContext());
+        String toString = ctx.toString();
+
+        assertNotNull(toString);
+        
assertTrue(toString.contains("FilterContext{value='PropertyValue{key='testToString',
 value='val', " +
+                                     "source='mySource'}', configEntries=["));
+        assertTrue(toString.contains("key-0"));
+        assertTrue(toString.contains("key-1"));
+        assertTrue(toString.endsWith("}"));
+    }
+
+    private static class TestConfigContext implements ConfigurationContext {
+
+        @Override
+        public void addPropertySources(PropertySource... propertySources) {
+
+        }
+
+        @Override
+        public List<PropertySource> getPropertySources() {
+            return null;
+        }
+
+        @Override
+        public PropertySource getPropertySource(String name) {
+            return null;
+        }
+
+        @Override
+        public <T> void addPropertyConverter(TypeLiteral<T> type, 
PropertyConverter<T> propertyConverter) {
+
+        }
+
+        @Override
+        public Map<TypeLiteral<?>, List<PropertyConverter<?>>> 
getPropertyConverters() {
+            return null;
+        }
+
+        @Override
+        public <T> List<PropertyConverter<T>> 
getPropertyConverters(TypeLiteral<T> type) {
+            return null;
+        }
+
+        @Override
+        public List<PropertyFilter> getPropertyFilters() {
+            return null;
+        }
+
+        @Override
+        public PropertyValueCombinationPolicy 
getPropertyValueCombinationPolicy() {
+            return null;
+        }
+
+        @Override
+        public ConfigurationContextBuilder toBuilder() {
+            return null;
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
 
b/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
new file mode 100644
index 0000000..31fb2f8
--- /dev/null
+++ 
b/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.spi;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * Additional tests for {@link ServiceContextManager}, created by atsticks on 
20.08.16.
+ */
+public class ServiceContextManagerTest {
+
+    @Test
+    public void setGetServiceContext() throws Exception {
+        ServiceContext prev = ServiceContextManager.getServiceContext();
+        try {
+            MyServiceContext mine = new MyServiceContext();
+            ServiceContextManager.set(mine);
+            assertTrue(ServiceContextManager.getServiceContext() == mine);
+            ServiceContextManager.set(mine);
+            assertTrue(ServiceContextManager.getServiceContext() == mine);
+        } finally {
+            ServiceContextManager.set(prev);
+            assertTrue(ServiceContextManager.getServiceContext() == prev);
+        }
+
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void setRequiresNonNullParameter() {
+        ServiceContextManager.set(null);
+    }
+
+    private static final class MyServiceContext implements ServiceContext{
+
+        @Override
+        public int ordinal() {
+            return 0;
+        }
+
+        @Override
+        public <T> T getService(Class<T> serviceType) {
+            return null;
+        }
+
+        @Override
+        public <T> T getService(Class<T> serviceType, ClassLoader classLoader) 
{
+            return getService(serviceType, 
ServiceContext.defaultClassLoader());
+        }
+
+        @Override
+        public <T> T create(Class<T> serviceType) {
+            return null;
+        }
+
+        @Override
+        public <T> T create(Class<T> serviceType, ClassLoader classLoader) {
+            return create(serviceType, ServiceContext.defaultClassLoader());
+        }
+
+        @Override
+        public <T> List<T> getServices(Class<T> serviceType) {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public <T> List<T> getServices(Class<T> serviceType, ClassLoader 
classLoader) {
+            return getServices(serviceType, 
ServiceContext.defaultClassLoader());
+        }
+
+        @Override
+        public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+            return null;
+        }
+
+        @Override
+        public URL getResource(String resource, ClassLoader cl) {
+            return null;
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java 
b/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
new file mode 100644
index 0000000..fe4ee05
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.spi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
+import org.junit.Test;
+
+public class ServiceContextTest {
+
+    private final ServiceContext serviceContext = new ServiceContext(){
+
+        @Override
+        public int ordinal() {
+            return 1;
+        }
+
+        @Override
+        public <T> T getService(Class<T> serviceType) {
+            if(String.class.equals(serviceType)){
+                return serviceType.cast("ServiceContextTest");
+            }
+            return null;
+        }
+
+        @Override
+        public <T> T getService(Class<T> serviceType, ClassLoader classLoader) 
{
+            return getService(serviceType, 
ServiceContext.defaultClassLoader());
+        }
+
+        @Override
+        public <T> T create(Class<T> serviceType) {
+            return getService(serviceType);
+        }
+
+        @Override
+        public <T> T create(Class<T> serviceType, ClassLoader classLoader) {
+            return create(serviceType, ServiceContext.defaultClassLoader());
+        }
+
+        @SuppressWarnings("unchecked")
+               @Override
+        public <T> List<T> getServices(Class<T> serviceType) {
+            if(String.class.equals(serviceType)){
+                List<String> list = new ArrayList<>();
+                list.add("ServiceContextTest");
+                return List.class.cast(list);
+            }
+            return Collections.emptyList();
+        }
+
+        @Override
+        public <T> List<T> getServices(Class<T> serviceType, ClassLoader 
classLoader) {
+            return getServices(serviceType, 
ServiceContext.defaultClassLoader());
+        }
+
+        @Override
+        public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+            return cl.getResources(resource);
+        }
+
+        @Override
+        public URL getResource(String resource, ClassLoader cl) {
+            return cl.getResource(resource);
+        }
+    };
+
+    @Test
+    public void testOrdinal() throws Exception {
+        assertEquals(1, serviceContext.ordinal());
+    }
+
+    @Test
+    public void testgetService() throws Exception {
+        assertEquals("ServiceContextTest", 
serviceContext.getService(String.class));
+        assertNull(serviceContext.getService(Integer.class));
+    }
+
+    @Test
+    public void testGetService() throws Exception {
+        String service = serviceContext.getService(String.class);
+        assertNotNull(service);
+        assertEquals("ServiceContextTest", service);
+        Integer intService = serviceContext.getService(Integer.class);
+        assertNull(intService);
+    }
+
+    @Test
+    public void testGetServices() throws Exception {
+        Collection<String> services = serviceContext.getServices(String.class);
+        assertNotNull(services);
+        assertFalse(services.isEmpty());
+        assertEquals("ServiceContextTest", services.iterator().next());
+        List<Integer> intServices = serviceContext.getServices(Integer.class);
+        assertNotNull(intServices);
+        assertTrue(intServices.isEmpty());
+    }
+
+    @Test
+    public void testGetInstance() throws Exception {
+        assertNotNull(ServiceContextManager.getServiceContext());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/java/org/apache/tamaya/spi/TestServiceContext.java 
b/code/compat/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
new file mode 100644
index 0000000..4b8edc1
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
@@ -0,0 +1,120 @@
+/*
+ * 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.spi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class implements the (default) {@link 
org.apache.tamaya.spi.ServiceContext} interface and hereby uses the JDK
+ * {@link java.util.ServiceLoader} to load the services required.
+ */
+public final class TestServiceContext implements ServiceContext {
+    /** List current services loaded, per class. */
+    private final ConcurrentHashMap<Class<?>, List<Object>> servicesLoaded = 
new ConcurrentHashMap<>();
+
+    private final Map<Class<?>, Object> singletons = new ConcurrentHashMap<>();
+
+    @Override
+    public int ordinal() {
+        return 1;
+    }
+
+    @SuppressWarnings("rawtypes")
+       @Override
+    public <T> T getService(Class<T> serviceType) {
+        T cached = serviceType.cast(singletons.get(serviceType));
+        if(cached==null) {
+            cached = create(serviceType);
+            singletons.put((Class)serviceType, cached);
+        }
+        if (cached == Object.class) {
+            cached = null;
+        }
+        return cached;
+    }
+
+    @Override
+    public <T> T getService(Class<T> serviceType, ClassLoader classLoader) {
+        return getService(serviceType, ServiceContext.defaultClassLoader());
+    }
+
+    @SuppressWarnings("unchecked")
+       @Override
+    public <T> T create(Class<T> serviceType) {
+        Collection<T> services = getServices(serviceType);
+        if (services.isEmpty()) {
+            return (T) Object.class; // as marker for 'nothing here'
+        }
+        else{
+            return services.iterator().next();
+        }
+    }
+
+    @Override
+    public <T> T create(Class<T> serviceType, ClassLoader classLoader) {
+        return create(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(Class<T> serviceType) {
+        try {
+            List<T> services = new ArrayList<>();
+            for (T t : ServiceLoader.load(serviceType)) {
+                services.add(t);
+            }
+            services = Collections.unmodifiableList(services);
+            @SuppressWarnings("unchecked")
+                       final List<T> previousServices = 
List.class.cast(servicesLoaded.putIfAbsent(serviceType, 
(List<Object>)services));
+            return previousServices != null ? previousServices : services;
+        } catch (Exception e) {
+            
Logger.getLogger(TestServiceContext.class.getName()).log(Level.WARNING,
+                                      "Error loading services current type " + 
serviceType, e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public <T> List<T> getServices(Class<T> serviceType, ClassLoader 
classLoader) {
+        return getServices(serviceType, ServiceContext.defaultClassLoader());
+    }
+
+    @Override
+    public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+        return cl.getResources(resource);
+    }
+
+    @Override
+    public URL getResource(String resource, ClassLoader cl) {
+        return cl.getResource(resource);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/spisupport/RegexFilterTest.java
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/java/org/apache/tamaya/spisupport/RegexFilterTest.java 
b/code/compat/src/test/java/org/apache/tamaya/spisupport/RegexFilterTest.java
new file mode 100644
index 0000000..5614c01
--- /dev/null
+++ 
b/code/compat/src/test/java/org/apache/tamaya/spisupport/RegexFilterTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.spi.FilterContext;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link RegexPropertyFilter}. Created by anatole on 11.02.16.
+ */
+public class RegexFilterTest {
+
+    private static PropertyValue prop1 = PropertyValue.of("test1", "test1", 
"test");
+    private static PropertyValue prop2 = PropertyValue.of("test2", "test2", 
"test");
+    private static PropertyValue prop3 = PropertyValue.of("test1.test3", 
"test.test3", "test");
+    private static Configuration config = new 
DefaultConfigurationBuilder().build();
+
+    @org.junit.Test
+    public void testFilterProperty() throws Exception {
+        RegexPropertyFilter filter = new RegexPropertyFilter();
+        filter.setIncludes("test1.*");
+        Map<String,PropertyValue> map = new HashMap<>();
+        map.put(prop1.getKey(), prop1);
+        map.put(prop2.getKey(), prop2);
+        map.put(prop3.getKey(), prop3);
+        FilterContext ctx = new FilterContext(prop1, config.getContext());
+        assertEquals(filter.filterProperty(prop1, ctx), prop1);
+        ctx = new FilterContext(prop2, config.getContext());
+        assertNull(filter.filterProperty(prop2, ctx));
+        ctx = new FilterContext(prop3, map, config.getContext());
+        assertEquals(filter.filterProperty(
+                prop3, ctx), prop3);
+        ctx = new FilterContext(prop3, map, config.getContext());
+        assertEquals(filter.filterProperty(
+                prop3, ctx), prop3);
+        filter = new RegexPropertyFilter();
+        filter.setIncludes("test1.*");
+        ctx = new FilterContext(prop1, map, config.getContext());
+        assertNotNull(filter.filterProperty(prop1, ctx));
+        ctx = new FilterContext(prop2, map, config.getContext());
+        assertNull(filter.filterProperty(prop2, ctx));
+        ctx = new FilterContext(prop3, map, config.getContext());
+        assertNotNull(filter.filterProperty(prop3, ctx));
+    }
+
+    @org.junit.Test
+    public void testToString() throws Exception {
+        RegexPropertyFilter filter = new RegexPropertyFilter();
+        filter.setIncludes("test\\..*");
+        assertTrue(filter.toString().contains("test\\..*"));
+        assertTrue(filter.toString().contains("RegexPropertyFilter"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationProviderSpi
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationProviderSpi
 
b/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationProviderSpi
new file mode 100644
index 0000000..b9c5ba5
--- /dev/null
+++ 
b/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationProviderSpi
@@ -0,0 +1,19 @@
+#
+# 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.TestConfigurationProvider

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext
----------------------------------------------------------------------
diff --git 
a/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext
 
b/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext
new file mode 100644
index 0000000..199956f
--- /dev/null
+++ 
b/code/compat/src/test/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext
@@ -0,0 +1,19 @@
+#
+# 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.spi.TestServiceContext
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/BannerManager.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/BannerManager.java 
b/code/core/src/main/java/org/apache/tamaya/core/BannerManager.java
new file mode 100644
index 0000000..d387267
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/BannerManager.java
@@ -0,0 +1,163 @@
+/*
+ * 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.core;
+
+import javax.config.ConfigProvider;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * Controls the output of the banner of Tamaya.
+ *
+ * <p>This class controls if and how the banner of Tamaya is presented the 
user.
+ * The banner is provided by the Tamaya Core under the resource path
+ * {@value BANNER_RESOURCE_PATH}.</p>
+ *
+ * <p>The behavior of the banner manager can be controlled by
+ * specifying the configuration key {@code tamaya.banner} with one of
+ * the three folowing values:
+ *
+ * <dl>
+ *     <dt>OFF</dt>
+ *     <dd>Banner will not be shown</dd>
+ *     <dt>CONSOLE</dt>
+ *     <dd>The banner will be printed on STDOUT</dd>
+ *     <dt>LOGGER</dt>
+ *     <dd>The banner will be logged</dd>
+ * </dl>
+ *
+ * In case of any other value the banner will not be shown.
+ * </p>
+ *
+ *
+ *
+ * @see BannerTarget
+ */
+class BannerManager {
+    /**
+     * The resouce path to the file containing the banner of Tamaya.
+     */
+    protected final static String BANNER_RESOURCE_PATH = "/tamaya-banner.txt";
+
+    enum BannerTarget {
+        OFF, CONSOLE, LOGGER
+    }
+
+    private BannerTarget bannerTarget;
+
+    public BannerManager(String value) {
+        value = Objects.requireNonNull(value).toUpperCase(Locale.getDefault());
+
+        try {
+            bannerTarget = BannerTarget.valueOf(value);
+        } catch (NullPointerException | IllegalArgumentException e) {
+            bannerTarget = BannerTarget.OFF;
+        }
+    }
+
+    public void outputBanner() {
+        BannerPrinter bp = new SilentBannerPrinter();
+
+        switch (bannerTarget) {
+            case CONSOLE:
+                bp = new ConsoleBannerPrinter();
+                break;
+            case LOGGER:
+                bp = new LoggingBannerPrinter();
+                break;
+            case OFF:
+            default:
+                break;
+        }
+
+        bp.outputBanner();
+    }
+}
+
+abstract class AbstractBannerPrinter implements BannerPrinter {
+    private static final Logger log = 
Logger.getLogger(AbstractBannerPrinter.class.getName());
+
+    @Override
+    public void outputBanner() {
+        try (InputStream in = 
ConfigProvider.class.getResourceAsStream(BannerManager.BANNER_RESOURCE_PATH)) {
+            BufferedReader reader = new BufferedReader(new 
InputStreamReader(in));
+            String line;
+
+            while ((line = reader.readLine()) != null) {
+                outputSingleLine(line);
+            }
+        } catch (Exception e) {
+            log.log(Level.WARNING, "Failed to output the banner of tamaya.", 
e);
+        }
+    }
+
+    abstract void outputSingleLine(String line);
+}
+
+
+/**
+ * Outputs the Tamaya banner to an implementation specific output channel
+ * as STDOUT or the logging system.
+ */
+interface BannerPrinter {
+    /**
+     * Outputs the banner to the output channel
+     * used by the implementation.
+     */
+    void outputBanner();
+}
+
+/**
+ * Silent implementation of a {@link BannerPrinter}.
+ */
+class SilentBannerPrinter implements BannerPrinter {
+    @Override
+    public void outputBanner() {
+    }
+}
+
+/**
+ * Logs the banner via JUL at level {@link java.util.logging.Level#INFO}.
+ */
+class LoggingBannerPrinter extends AbstractBannerPrinter {
+    private static final Logger log = 
Logger.getLogger(LoggingBannerPrinter.class.getName());
+
+    @Override
+    void outputSingleLine(String line) {
+        log.log(Level.INFO, line);
+    }
+}
+
+/**
+ * Prints the banner to the console.
+ */
+class ConsoleBannerPrinter extends AbstractBannerPrinter {
+    @Override
+    void outputSingleLine(String line) {
+        System.out.println(line);
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceComparator.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceComparator.java 
b/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceComparator.java
new file mode 100644
index 0000000..009927d
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceComparator.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core;
+
+import org.osgi.framework.ServiceReference;
+
+import javax.annotation.Priority;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for ordering services loaded based on their 
increasing priority values.
+ */
+@SuppressWarnings("rawtypes")
+class OSGIServiceComparator implements Comparator<ServiceReference> {
+
+    @Override
+    public int compare(ServiceReference o1, ServiceReference o2) {
+        int prio = getPriority(o1) - getPriority(o2);
+        if (prio < 0) {
+            return 1;
+        } else if (prio > 0) {
+            return -1;
+        } else {
+            return 0; 
//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.
+     */
+    public static int getPriority(Class<? extends Object> type) {
+        int prio = 1;
+        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/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceContext.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceContext.java 
b/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceContext.java
new file mode 100644
index 0000000..eb01733
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceContext.java
@@ -0,0 +1,187 @@
+/*
+ * 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.core;
+
+import org.apache.tamaya.spi.ServiceContext;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import javax.config.spi.ConfigProviderResolver;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * ServiceContext implementation based on OSGI Service mechanisms.
+ */
+public class OSGIServiceContext implements ServiceContext{
+
+    private static final Logger LOG = 
Logger.getLogger(OSGIServiceContext.class.getName());
+    private static final OSGIServiceComparator REF_COMPARATOR = new 
OSGIServiceComparator();
+
+    private final OSGIServiceLoader osgiServiceLoader;
+
+    public OSGIServiceContext(OSGIServiceLoader osgiServiceLoader){
+        this.osgiServiceLoader = Objects.requireNonNull(osgiServiceLoader);
+    }
+
+    public boolean isInitialized(){
+        return osgiServiceLoader != null;
+    }
+
+
+    @Override
+    public int ordinal() {
+        return 10;
+    }
+
+    @Override
+    public <T> T getService(Class<T> serviceType) {
+        LOG.finest("TAMAYA  Loading service: " + serviceType.getName());
+        ServiceReference<T> ref = 
this.osgiServiceLoader.getBundleContext().getServiceReference(serviceType);
+        if(ref!=null){
+            return this.osgiServiceLoader.getBundleContext().getService(ref);
+        }
+        if(ConfigProviderResolver.class==serviceType){
+            @SuppressWarnings("unchecked")
+                       T service = (T)new TamayaConfigProviderResolver();
+            this.osgiServiceLoader.getBundleContext().registerService(
+                    serviceType.getName(),
+                    service,
+                    new Hashtable<String, Object>());
+            return service;
+        }
+        return null;
+    }
+
+    @Override
+    public <T> T getService(Class<T> serviceType, ClassLoader classLoader) {
+        return getService(serviceType);
+    }
+
+    @SuppressWarnings("unchecked")
+       @Override
+    public <T> T create(Class<T> serviceType) {
+        LOG.finest("TAMAYA  Creating service: " + serviceType.getName());
+        ServiceReference<T> ref = 
this.osgiServiceLoader.getBundleContext().getServiceReference(serviceType);
+        if(ref!=null){
+            try {
+                return 
(T)this.osgiServiceLoader.getBundleContext().getService(ref).getClass().newInstance();
+            } catch (Exception e) {
+                return null;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public <T> T create(Class<T> serviceType, ClassLoader classLoader) {
+        return create(serviceType);
+    }
+
+    @Override
+    public <T> List<T> getServices(Class<T> serviceType) {
+        LOG.finest("TAMAYA  Loading services: " + serviceType.getName());
+        List<ServiceReference<T>> refs = new ArrayList<>();
+        List<T> services = new ArrayList<>(refs.size());
+        try {
+            
refs.addAll(this.osgiServiceLoader.getBundleContext().getServiceReferences(serviceType,
 null));
+            Collections.sort(refs, REF_COMPARATOR);
+            for(ServiceReference<T> ref:refs){
+                T service = 
osgiServiceLoader.getBundleContext().getService(ref);
+                if(service!=null) {
+                    services.add(service);
+                }
+            }
+        } catch (InvalidSyntaxException e) {
+            e.printStackTrace();
+        }
+        try{
+            for(T service:ServiceLoader.load(serviceType)){
+                services.add(service);
+            }
+            return services;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return services;
+    }
+
+    @Override
+    public <T> List<T> getServices(Class<T> serviceType, ClassLoader 
classLoader) {
+        return getServices(serviceType);
+    }
+
+    @Override
+    public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException{
+        LOG.finest("TAMAYA  Loading resources: " + resource);
+        List<URL> result = new ArrayList<>();
+        URL url = osgiServiceLoader.getBundleContext().getBundle()
+                .getEntry(resource);
+        if(url != null) {
+            LOG.finest("TAMAYA  Resource: " + resource + " found in 
unregistered bundle " +
+                    
osgiServiceLoader.getBundleContext().getBundle().getSymbolicName());
+            result.add(url);
+        }
+        for(Bundle bundle: osgiServiceLoader.getResourceBundles()) {
+            url = bundle.getEntry(resource);
+            if (url != null && !result.contains(url)) {
+                LOG.finest("TAMAYA  Resource: " + resource + " found in 
registered bundle " + bundle.getSymbolicName());
+                result.add(url);
+            }
+        }
+        for(Bundle bundle: osgiServiceLoader.getBundleContext().getBundles()) {
+            url = bundle.getEntry(resource);
+            if (url != null && !result.contains(url)) {
+                LOG.finest("TAMAYA  Resource: " + resource + " found in 
unregistered bundle " + bundle.getSymbolicName());
+                result.add(url);
+            }
+        }
+        return Collections.enumeration(result);
+    }
+
+    @Override
+    public URL getResource(String resource, ClassLoader cl){
+        LOG.finest("TAMAYA  Loading resource: " + resource);
+        URL url = osgiServiceLoader.getBundleContext().getBundle()
+                .getEntry(resource);
+        if(url!=null){
+            LOG.finest("TAMAYA  Resource: " + resource + " found in bundle " +
+                    
osgiServiceLoader.getBundleContext().getBundle().getSymbolicName());
+            return url;
+        }
+        for(Bundle bundle: osgiServiceLoader.getResourceBundles()) {
+            url = bundle.getEntry(resource);
+            if(url != null){
+                LOG.finest("TAMAYA  Resource: " + resource + " found in 
registered bundle " + bundle.getSymbolicName());
+                return url;
+            }
+        }
+        for(Bundle bundle: osgiServiceLoader.getBundleContext().getBundles()) {
+            url = bundle.getEntry(resource);
+            if(url != null){
+                LOG.finest("TAMAYA  Resource: " + resource + " found in 
unregistered bundle " + bundle.getSymbolicName());
+                return url;
+            }
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceLoader.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceLoader.java 
b/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceLoader.java
new file mode 100644
index 0000000..90e74bc
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/OSGIServiceLoader.java
@@ -0,0 +1,254 @@
+/*
+ * 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.core;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tamaya.spisupport.PriorityServiceComparator;
+import org.osgi.framework.*;
+
+/**
+ * A bundle listener that registers services defined in META-INF/services, when
+ * a bundle is starting.
+ *
+ * @author [email protected]
+ */
+@SuppressWarnings("rawtypes")
+public class OSGIServiceLoader implements BundleListener {
+       // Provide logging
+       private static final Logger log = 
Logger.getLogger(OSGIServiceLoader.class.getName());
+       private static final String META_INF_SERVICES = "META-INF/services/";
+
+       private BundleContext context;
+
+       private Set<Bundle> resourceBundles = Collections.synchronizedSet(new 
HashSet<Bundle>());
+
+       public OSGIServiceLoader(BundleContext context) {
+               this.context = Objects.requireNonNull(context);
+               // Check for matching bundles already installed...
+               for (Bundle bundle : context.getBundles()) {
+                       switch (bundle.getState()) {
+                       case Bundle.ACTIVE:
+                               checkAndLoadBundle(bundle);
+                       }
+               }
+       }
+
+       public BundleContext getBundleContext() {
+               return context;
+       }
+
+       public Set<Bundle> getResourceBundles() {
+               synchronized (resourceBundles) {
+                       return new HashSet<>(resourceBundles);
+               }
+       }
+
+       @Override
+       public void bundleChanged(BundleEvent bundleEvent) {
+               // Parse and create metadata when installed
+               if (bundleEvent.getType() == BundleEvent.STARTED) {
+                       Bundle bundle = bundleEvent.getBundle();
+                       checkAndLoadBundle(bundle);
+               } else if (bundleEvent.getType() == BundleEvent.STOPPED) {
+                       Bundle bundle = bundleEvent.getBundle();
+                       checkAndUnloadBundle(bundle);
+               }
+       }
+
+       private void checkAndUnloadBundle(Bundle bundle) {
+               if (bundle.getEntry(META_INF_SERVICES) == null) {
+                       return;
+               }
+               synchronized (resourceBundles) {
+                       resourceBundles.remove(bundle);
+                       log.fine("Unregistered ServiceLoader bundle: " + 
bundle.getSymbolicName());
+               }
+               Enumeration<String> entryPaths = 
bundle.getEntryPaths(META_INF_SERVICES);
+               while (entryPaths.hasMoreElements()) {
+                       String entryPath = entryPaths.nextElement();
+                       if (!entryPath.endsWith("/")) {
+                               removeEntryPath(bundle, entryPath);
+                       }
+               }
+       }
+
+       private void checkAndLoadBundle(Bundle bundle) {
+               if (bundle.getEntry(META_INF_SERVICES) == null) {
+                       return;
+               }
+               synchronized (resourceBundles) {
+                       resourceBundles.add(bundle);
+                       log.info("Registered ServiceLoader bundle: " + 
bundle.getSymbolicName());
+               }
+               Enumeration<String> entryPaths = 
bundle.getEntryPaths(META_INF_SERVICES);
+               while (entryPaths.hasMoreElements()) {
+                       String entryPath = entryPaths.nextElement();
+                       if (!entryPath.endsWith("/")) {
+                               processEntryPath(bundle, entryPath);
+                       }
+               }
+       }
+
+       private void processEntryPath(Bundle bundle, String entryPath) {
+               try {
+                       String serviceName = 
entryPath.substring(META_INF_SERVICES.length());
+                       if (!serviceName.startsWith("org.apache.tamaya")) {
+                               // Ignore non Tamaya entries...
+                               return;
+                       }
+                       Class<?> serviceClass = bundle.loadClass(serviceName);
+                       URL child = bundle.getEntry(entryPath);
+                       InputStream inStream = child.openStream();
+                       log.info("Loading Services " + serviceClass.getName() + 
" from bundle...: " + bundle.getSymbolicName());
+                       try (BufferedReader br = new BufferedReader(new 
InputStreamReader(inStream, "UTF-8"))) {
+                               String implClassName = br.readLine();
+                               while (implClassName != null) {
+                                       int hashIndex = 
implClassName.indexOf("#");
+                                       if (hashIndex > 0) {
+                                               implClassName = 
implClassName.substring(0, hashIndex - 1);
+                                       } else if (hashIndex == 0) {
+                                               implClassName = "";
+                                       }
+                                       implClassName = implClassName.trim();
+                                       if (implClassName.length() > 0) {
+                                               try {
+                                                       // Load the service 
class
+                                                       log.fine("Loading Class 
" + implClassName + " from bundle...: " + bundle.getSymbolicName());
+                                                       Class<?> implClass = 
bundle.loadClass(implClassName);
+                                                       if 
(!serviceClass.isAssignableFrom(implClass)) {
+                                                               
log.warning("Configured service: " + implClassName + " is not assignable to "
+                                                                               
+ serviceClass.getName());
+                                                               continue;
+                                                       }
+                                                       log.info("Loaded 
Service Factory (" + serviceName + "): " + implClassName);
+                                                       // Provide service 
properties
+                                                       Hashtable<String, 
String> props = new Hashtable<>();
+                                                       
props.put(Constants.VERSION_ATTRIBUTE, bundle.getVersion().toString());
+                                                       String vendor = 
bundle.getHeaders().get(Constants.BUNDLE_VENDOR);
+                                                       
props.put(Constants.SERVICE_VENDOR, (vendor != null ? vendor : "anonymous"));
+                                                       // Translate annotated 
@Priority into a service ranking
+                                                       
props.put(Constants.SERVICE_RANKING,
+                                                                       
String.valueOf(PriorityServiceComparator.getPriority(implClass)));
+
+                                                       // Register the service 
factory on behalf of the intercepted bundle
+                                                       JDKUtilServiceFactory 
factory = new JDKUtilServiceFactory(implClass);
+                                                       BundleContext 
bundleContext = bundle.getBundleContext();
+                                                       
bundleContext.registerService(serviceName, factory, props);
+                                                       log.info("Registered 
Tamaya service class: " + implClassName + "(" + serviceName + ")");
+                                               } catch (Exception e) {
+                                                       log.log(Level.SEVERE, 
"Failed to load service: " + implClassName, e);
+                                               } catch (NoClassDefFoundError 
err) {
+                                                       log.log(Level.SEVERE, 
"Failed to load service: " + implClassName, err);
+                                               }
+                                       }
+                                       implClassName = br.readLine();
+                               }
+                       }
+               } catch (RuntimeException rte) {
+                       throw rte;
+               } catch (Exception e) {
+                       log.log(Level.SEVERE, "Failed to read services from: " 
+ entryPath, e);
+               }
+       }
+
+       private void removeEntryPath(Bundle bundle, String entryPath) {
+               try {
+                       String serviceName = 
entryPath.substring(META_INF_SERVICES.length());
+                       if (!serviceName.startsWith("org.apache.tamaya")) {
+                               // Ignore non Tamaya entries...
+                               return;
+                       }
+                       Class<?> serviceClass = bundle.loadClass(serviceName);
+
+                       URL child = bundle.getEntry(entryPath);
+                       InputStream inStream = child.openStream();
+
+                       BufferedReader br = new BufferedReader(new 
InputStreamReader(inStream, "UTF-8"));
+                       String implClassName = br.readLine();
+                       while (implClassName != null) {
+                               int hashIndex = implClassName.indexOf("#");
+                               if (hashIndex > 0) {
+                                       implClassName = 
implClassName.substring(0, hashIndex - 1);
+                               } else if (hashIndex == 0) {
+                                       implClassName = "";
+                               }
+                               implClassName = implClassName.trim();
+                               if (implClassName.length() > 0) {
+                                       log.fine("Unloading Service (" + 
serviceName + "): " + implClassName);
+                                       try {
+                                               // Load the service class
+                                               Class<?> implClass = 
bundle.loadClass(implClassName);
+                                               if 
(!serviceClass.isAssignableFrom(implClass)) {
+                                                       log.warning("Configured 
service: " + implClassName + " is not assignable to "
+                                                                       + 
serviceClass.getName());
+                                                       continue;
+                                               }
+                                               ServiceReference<?> ref = 
bundle.getBundleContext().getServiceReference(implClass);
+                                               if (ref != null) {
+                                                       
bundle.getBundleContext().ungetService(ref);
+                                               }
+                                       } catch (Exception e) {
+                                               log.log(Level.SEVERE, "Failed 
to unload service: " + implClassName, e);
+                                       } catch (NoClassDefFoundError err) {
+                                               log.log(Level.SEVERE, "Failed 
to unload service: " + implClassName, err);
+                                       }
+                               }
+                               implClassName = br.readLine();
+                       }
+                       br.close();
+               } catch (RuntimeException rte) {
+                       throw rte;
+               } catch (Exception e) {
+                       log.log(Level.SEVERE, "Failed to read services from: " 
+ entryPath, e);
+               }
+       }
+
+       /**
+        * Service factory simply instantiating the configured service.
+        */
+       static class JDKUtilServiceFactory implements ServiceFactory {
+               private final Class<?> serviceClass;
+
+               public JDKUtilServiceFactory(Class<?> serviceClass) {
+                       this.serviceClass = serviceClass;
+               }
+
+               @Override
+               public Object getService(Bundle bundle, ServiceRegistration 
registration) {
+                       try {
+                               log.fine("Creating Service...:" + 
serviceClass.getName());
+                               return serviceClass.newInstance();
+                       } catch (Exception ex) {
+                               ex.printStackTrace();
+                               throw new IllegalStateException("Failed to 
create service: " + serviceClass.getName(), ex);
+                       }
+               }
+
+               @Override
+               public void ungetService(Bundle bundle, ServiceRegistration 
registration, Object service) {
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/TamayaConfigProviderResolver.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/TamayaConfigProviderResolver.java
 
b/code/core/src/main/java/org/apache/tamaya/core/TamayaConfigProviderResolver.java
new file mode 100644
index 0000000..f4bc048
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/TamayaConfigProviderResolver.java
@@ -0,0 +1,92 @@
+/*
+ * 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.core;
+
+import org.apache.tamaya.base.DefaultConfigBuilder;
+import org.apache.tamaya.spi.ConfigContext;
+import org.apache.tamaya.spi.Filter;
+import org.apache.tamaya.spi.ServiceContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.Config;
+import javax.config.spi.ConfigBuilder;
+import javax.config.spi.ConfigProviderResolver;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link 
ConfigContext} to evaluate the
+ * chain of {@link javax.config.spi.ConfigSource} and {@link Filter}
+ * instance to evaluate the current Configuration.
+ */
+@Component(service = ConfigProviderResolver.class)
+public class TamayaConfigProviderResolver extends ConfigProviderResolver {
+
+    private Map<ClassLoader, Config> configs = new ConcurrentHashMap<>();
+
+    @Override
+    public Config getConfig() {
+        return getConfig(Thread.currentThread().getContextClassLoader());
+    }
+
+    @Override
+    public Config getConfig(ClassLoader loader) {
+        Config config = this.configs.get(loader);
+        if(config==null){
+            config = new DefaultConfigBuilder()
+                    .addDiscoveredFilters()
+                    .addDiscoveredConverters()
+                    .addDefaultSources()
+                    .addDiscoveredSources()
+                    .build();
+            this.configs.put(loader, config);
+        }
+        return config;
+    }
+
+    @Override
+    public ConfigBuilder getBuilder() {
+        return new DefaultConfigBuilder();
+    }
+
+    @Override
+    public void registerConfig(Config config, ClassLoader classLoader) {
+        if(classLoader==null){
+            classLoader = ServiceContext.defaultClassLoader();
+        }
+        if(configs.containsKey(classLoader)){
+            Logger.getLogger(getClass().getName())
+                    .warning("Replacing existing config for classloader: " + 
classLoader);
+//            throw new IllegalArgumentException("Already a config registered 
with classloader: " + classLoader);
+        }
+        this.configs.put(classLoader, config);
+    }
+
+    @Override
+    public void releaseConfig(Config config) {
+        for(Map.Entry<ClassLoader, Config> en: this.configs.entrySet()){
+            if(en.getValue().equals(config)){
+                this.configs.remove(en.getKey());
+                return;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/BigDecimalConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/BigDecimalConverter.java
 
b/code/core/src/main/java/org/apache/tamaya/core/converters/BigDecimalConverter.java
new file mode 100644
index 0000000..e29cf85
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/BigDecimalConverter.java
@@ -0,0 +1,78 @@
+/*
+ * 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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to BigDecimal, the supported format is 
one of the following:
+ * <ul>
+ *     <li>232573527352.76352753</li>
+ *     <li>-23257352.735276352753</li>
+ *     <li>-0xFFFFFF (integral numbers only)</li>
+ *     <li>-0XFFFFAC (integral numbers only)</li>
+ *     <li>0xFFFFFF (integral numbers only)</li>
+ *     <li>0XFFFFAC (integral numbers only)</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class BigDecimalConverter implements Converter<BigDecimal> {
+
+    /** The logger. */
+    private static final Logger LOG = 
Logger.getLogger(BigDecimalConverter.class.getName());
+    /** Converter to be used if the format is not directly supported by 
BigDecimal, e.g. for integral hex values. */
+    private final BigIntegerConverter integerConverter = new 
BigIntegerConverter();
+
+    @Override
+    public BigDecimal convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        if(context!=null) {
+            context.addSupportedFormats(getClass(), "<BigDecimal> -> new 
BigDecimal(String)");
+        }
+        String trimmed = Objects.requireNonNull(value).trim();
+        try{
+            return new BigDecimal(trimmed);
+        } catch(Exception e){
+            LOG.finest("Parsing BigDecimal failed, trying BigInteger for: " + 
value);
+            BigInteger bigInt = integerConverter.convert(value);
+            if(bigInt!=null){
+                return new BigDecimal(bigInt);
+            }
+            LOG.finest("Failed to parse BigDecimal from: " + value);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/BigIntegerConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/BigIntegerConverter.java
 
b/code/core/src/main/java/org/apache/tamaya/core/converters/BigIntegerConverter.java
new file mode 100644
index 0000000..1e73b19
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/BigIntegerConverter.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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to BigInteger, the supported format is 
one of the following:
+ * <ul>
+ *     <li>0xFFFFFF</li>
+ *     <li>0XFFFFAC</li>
+ *     <li>23257352735276352753</li>
+ *     <li>-0xFFFFFF</li>
+ *     <li>-0XFFFFAC</li>
+ *     <li>-23257352735276352753</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class BigIntegerConverter implements Converter<BigInteger> {
+
+    /** The logger. */
+    private static final Logger LOG = 
Logger.getLogger(BigIntegerConverter.class.getName());
+    /** Converter used to decode hex, octal values. */
+    private final ByteConverter byteConverter = new ByteConverter();
+
+    @Override
+    public BigInteger convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        context.addSupportedFormats(getClass(), "[-]0X.. (hex)", "[-]0x... 
(hex)", "<bigint> -> new BigInteger(bigint)");
+        String trimmed = Objects.requireNonNull(value).trim();
+        if(trimmed.startsWith("0x") || trimmed.startsWith("0X")){
+            LOG.finest("Parsing Hex value to BigInteger: " + value);
+            trimmed = trimmed.substring(2);
+            StringBuilder decimal = new StringBuilder();
+            for(int offset = 0;offset < trimmed.length();offset+=2){
+                if(offset==trimmed.length()-1){
+                    LOG.finest("Invalid Hex-Byte-String: " + value);
+                    return null;
+                }
+                byte val = byteConverter.convert("0x" + 
trimmed.substring(offset, offset + 2));
+                if(val<10){
+                    decimal.append('0').append(val);
+                } else{
+                    decimal.append(val);
+                }
+            }
+            return new BigInteger(decimal.toString());
+        } else if(trimmed.startsWith("-0x") || trimmed.startsWith("-0X")){
+            LOG.finest("Parsing Hex value to BigInteger: " + value);
+            trimmed = trimmed.substring(3);
+            StringBuilder decimal = new StringBuilder();
+            for(int offset = 0;offset < trimmed.length();offset+=2){
+                if(offset==trimmed.length()-1){
+                    LOG.finest("Invalid Hex-Byte-String: " + trimmed);
+                    return null;
+                }
+                byte val = byteConverter.convert("0x" + 
trimmed.substring(offset, offset + 2));
+                if(val<10){
+                    decimal.append('0').append(val);
+                } else{
+                    decimal.append(val);
+                }
+            }
+            return new BigInteger('-' + decimal.toString());
+        }
+        try{
+            return new BigInteger(trimmed);
+        } catch(Exception e){
+            LOG.log(Level.FINEST, "Failed to parse BigInteger from: " + value, 
e);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/BooleanConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/BooleanConverter.java
 
b/code/core/src/main/java/org/apache/tamaya/core/converters/BooleanConverter.java
new file mode 100644
index 0000000..df322b1
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/BooleanConverter.java
@@ -0,0 +1,74 @@
+/*
+ * 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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class BooleanConverter implements Converter<Boolean> {
+
+    private final Logger LOG = Logger.getLogger(getClass().getName());
+
+    @Override
+    public Boolean convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        context.addSupportedFormats(getClass(), "yes (ignore case)", "y 
(ignore case)", "true (ignore case)", "t (ignore case)", "1", "no (ignore 
case)", "n (ignore case)", "false (ignore case)", "f (ignore case)", "0");
+        String ignoreCaseValue = Objects.requireNonNull(value)
+                                        .trim()
+                                        .toLowerCase(Locale.ENGLISH);
+        switch(ignoreCaseValue) {
+            case "1":
+            case "yes":
+            case "y":
+            case "true":
+            case "t":
+            case "on":
+                return Boolean.TRUE;
+            case "no":
+            case "n":
+            case "false":
+            case "f":
+            case "0":
+            case "off":
+                return Boolean.FALSE;
+            default:
+                LOG.finest("Unknown boolean value encountered: " + value);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/ByteConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/ByteConverter.java 
b/code/core/src/main/java/org/apache/tamaya/core/converters/ByteConverter.java
new file mode 100644
index 0000000..7b72cc5
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/ByteConverter.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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Byte, the supported format is one of 
the following:
+ * <ul>
+ *     <li>123 (byte value)</li>
+ *     <li>0xFF (byte value)</li>
+ *     <li>0XDF (byte value)</li>
+ *     <li>0D1 (byte value)</li>
+ *     <li>-123 (byte value)</li>
+ *     <li>-0xFF (byte value)</li>
+ *     <li>-0XDF (byte value)</li>
+ *     <li>-0D1 (byte value)</li>
+ *     <li>MIN_VALUE (ignoring case)</li>
+ *     <li>MIN (ignoring case)</li>
+ *     <li>MAX_VALUE (ignoring case)</li>
+ *     <li>MAX (ignoring case)</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class ByteConverter implements Converter<Byte> {
+
+    private final Logger LOG = Logger.getLogger(getClass().getName());
+
+    @Override
+    public Byte convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        context.addSupportedFormats(getClass(),"<byte>", "MIN_VALUE", "MIN", 
"MAX_VALUE", "MAX");
+        String trimmed = Objects.requireNonNull(value).trim();
+        switch(trimmed.toUpperCase(Locale.ENGLISH)){
+            case "MIN_VALUE":
+            case "MIN":
+                return Byte.MIN_VALUE;
+            case "MAX_VALUE":
+            case "MAX":
+                return Byte.MAX_VALUE;
+            default:
+                try{
+                    return Byte.decode(trimmed);
+                }
+                catch(Exception e){
+                    LOG.log(Level.FINEST, "Unparseable Byte: " + value);
+                    return null;
+                }
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/CharConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/CharConverter.java 
b/code/core/src/main/java/org/apache/tamaya/core/converters/CharConverter.java
new file mode 100644
index 0000000..9fa4e69
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/CharConverter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Character, the supported format is one 
of the following:
+ * <ul>
+ *     <li>'a'</li>
+ *     <li>123 (byte value)</li>
+ *     <li>0xFF (byte value)</li>
+ *     <li>0XDF (byte value)</li>
+ *     <li>0D1 (byte value)</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class CharConverter implements Converter<Character> {
+
+    private static final Logger LOG = 
Logger.getLogger(CharConverter.class.getName());
+
+    @Override
+    public Character convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        context.addSupportedFormats(getClass(),"\\'<char>\\'", "<char>", 
"<charNum>");
+        String trimmed = Objects.requireNonNull(value).trim();
+        if(trimmed.isEmpty()){
+            return null;
+        }
+        if(trimmed.startsWith("'")) {
+            try {
+                trimmed = trimmed.substring(1, trimmed.length() - 1);
+                if (trimmed.isEmpty()) {
+                    return null;
+                }
+                return trimmed.charAt(0);
+            } catch (Exception e) {
+                LOG.finest("Invalid character format encountered: '" + value + 
"', valid formats are 'a', 101 and a.");
+                return null;
+            }
+        }
+        try {
+            Integer val = Integer.parseInt(trimmed);
+            return (char) val.shortValue();
+        } catch (Exception e) {
+            LOG.finest("Character format is not numeric: '" + value + "', 
using first character.");
+            return trimmed.charAt(0);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/ClassConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/ClassConverter.java 
b/code/core/src/main/java/org/apache/tamaya/core/converters/ClassConverter.java
new file mode 100644
index 0000000..c998065
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/ClassConverter.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Class, hereby using the following 
classloaders:
+ * <ul>
+ *     <li>The current ThreadContext ClassLoader</li>
+ *     <li>The Classloader of this class</li>
+ *     <li>The system Classloader</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class ClassConverter implements Converter<Class<?>> {
+
+    private final Logger LOG = Logger.getLogger(getClass().getName());
+
+    @Override
+    public Class<?> convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        if(value==null){
+            return null;
+        }
+        context.addSupportedFormats(getClass(),"<fullyQualifiedClassName>");
+        String trimmed = Objects.requireNonNull(value).trim();
+        try{
+            return Class.forName(trimmed, false, 
Thread.currentThread().getContextClassLoader());
+        }
+        catch(Exception e){
+            LOG.finest("Class not found in context CL: " + trimmed);
+        }
+        try{
+            return Class.forName(trimmed, false, 
ClassConverter.class.getClassLoader());
+        }
+        catch(Exception e){
+            LOG.finest("Class not found in ClassConverter's CL: " + trimmed);
+        }
+        try{
+            return Class.forName(trimmed, false, 
ClassLoader.getSystemClassLoader());
+        }
+        catch(Exception e){
+            LOG.finest("Class not found in System CL (giving up): " + trimmed);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/ConvertQuery.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/ConvertQuery.java 
b/code/core/src/main/java/org/apache/tamaya/core/converters/ConvertQuery.java
new file mode 100644
index 0000000..2b22d83
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/ConvertQuery.java
@@ -0,0 +1,81 @@
+/*
+ * 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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.apache.tamaya.spi.ConfigContext;
+import org.apache.tamaya.spi.ConfigContextSupplier;
+
+import javax.config.Config;
+import javax.config.spi.Converter;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Query to convert a String value.
+ * @param <T> the target type.
+ */
+final class ConvertQuery<T> implements Function<Config, T> {
+
+    private static final Logger LOG = 
Logger.getLogger(ConvertQuery.class.getName());
+
+    private String rawValue;
+    private Type type;
+
+    public ConvertQuery(String rawValue, Type type) {
+        this.rawValue = Objects.requireNonNull(rawValue);
+        this.type = Objects.requireNonNull(type);
+    }
+
+    @Override
+    public T apply(Config config) {
+        if(!(config instanceof ConfigContextSupplier)){
+            throw new IllegalArgumentException("Config must implement 
ConfigContextSupplier");
+        }
+        ConfigContext ctx = ((ConfigContextSupplier)config).getConfigContext();
+        List<Converter> converters = ctx.getConverters(type);
+        ConversionContext context = new ConversionContext.Builder("<nokey>", 
type)
+                .setConfiguration(config)
+                .setKey(ConvertQuery.class.getName())
+                .build();
+        ConversionContext.setContext(context);
+        try {
+            for (Converter<?> conv : converters) {
+                try {
+                    if (conv instanceof OptionalConverter) {
+                        continue;
+                    }
+                    T result = (T) conv.convert(rawValue);
+                    if (result != null) {
+                        return result;
+                    }
+                } catch (Exception e) {
+                    LOG.log(Level.FINEST, e, () -> "Converter " + conv + " 
failed to convert to " + type);
+                }
+            }
+        }finally{
+            ConversionContext.reset();
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/CurrencyConverter.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/converters/CurrencyConverter.java
 
b/code/core/src/main/java/org/apache/tamaya/core/converters/CurrencyConverter.java
new file mode 100644
index 0000000..502e05c
--- /dev/null
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/converters/CurrencyConverter.java
@@ -0,0 +1,103 @@
+/*
+ * 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.core.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Currency, the supported format is one 
of the following:
+ * <ul>
+ *     <li>CHF (currency code)</li>
+ *     <li>123 (numeric currency value &gt;
+ *     = 0)</li>
+ *     <li>DE (ISO 2-digit country)</li>
+ *     <li>de_DE, de_DE_123 (Locale)</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class CurrencyConverter implements Converter<Currency> {
+
+    private static final Logger LOG = 
Logger.getLogger(CurrencyConverter.class.getName());
+
+    @Override
+    public Currency convert(String value) {
+        ConversionContext context = ConversionContext.getContext();
+        context.addSupportedFormats(getClass(), "<currencyCode>, using 
Locale.ENGLISH", "<numericValue>", "<locale>");
+        String trimmed = Objects.requireNonNull(value).trim();
+        try {
+            return Currency.getInstance(trimmed.toUpperCase(Locale.ENGLISH));
+        } catch (Exception e) {
+            LOG.log(Level.FINEST, "Not a valid textual currency code: " + 
trimmed + ", checking for numeric...", e);
+        }
+        try {
+            // Check for numeric code
+            Integer numCode = Integer.parseInt(trimmed);
+            for (Currency currency : Currency.getAvailableCurrencies()) {
+                if (currency.getNumericCode() == numCode) {
+                    return currency;
+                }
+            }
+        } catch (Exception e) {
+            LOG.log(Level.FINEST, "Not a valid numeric currency code: " + 
trimmed + ", checking for locale...", e);
+        }
+        try {
+            // Check for numeric code
+            String[] parts = trimmed.split("\\_");
+            Locale locale;
+            switch (parts.length) {
+                case 1:
+                    locale = new Locale("", parts[0]);
+                    break;
+                case 2:
+                    locale = new Locale(parts[0], parts[1]);
+                    break;
+                case 3:
+                    locale = new Locale(parts[0], parts[1], parts[2]);
+                    break;
+                default:
+                    locale = null;
+            }
+            if (locale != null) {
+                return Currency.getInstance(locale);
+            }
+            LOG.finest("Not a valid currency: " + trimmed + ", giving up...");
+        } catch (Exception e) {
+            LOG.log(Level.FINEST, "Not a valid country locale for currency: " 
+ trimmed + ", giving up...", e);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}

Reply via email to