tamaya-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anat...@apache.org
Subject [3/7] incubator-tamaya git commit: Reimplemented (also simjplified) Tamaya core completely based on latest JSR API. Moved prior Tamaya API into compat module.
Date Sun, 10 Dec 2017 22:07:11 GMT
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 anatole@apache.org
+ */
+@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();
+    }
+}


Mime
View raw message