You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2017/12/10 22:07:09 UTC
[1/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Repository: incubator-tamaya
Updated Branches:
refs/heads/configjsr 9bc56a38b -> d0e14ed70
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/ConfigContextBuilderTest.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/ConfigContextBuilderTest.java b/code/core/src/test/java/org/apache/tamaya/core/ConfigContextBuilderTest.java
new file mode 100644
index 0000000..11ee957
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/ConfigContextBuilderTest.java
@@ -0,0 +1,424 @@
+///*
+// * 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.TypeLiteral;
+//import org.apache.tamaya.spi.*;
+//import org.apache.tamaya.spi.Filter;
+//import org.junit.Test;
+//
+//import javax.config.ConfigProvider;
+//import javax.config.spi.ConfigSource;
+//import javax.config.spi.Converter;
+//import java.util.Arrays;
+//import java.util.Comparator;
+//
+//import static org.junit.Assert.*;
+//
+///**
+// * Tests for {@link ConfigContextBuilder} by atsticks on 06.09.16.
+// */
+//public class ConfigContextBuilderTest {
+//
+// private TestConfigSource TestConfigSource = new TestConfigSource(){};
+//
+// @Test
+// public void setContext() throws Exception {
+// ConfigContext context = ConfigContext.of(ConfigProvider.getConfig());
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withContext(context);
+// assertEquals(context, b.build());
+// }
+//
+// @Test
+// public void withSources_Array() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("withSources_Array", 1);
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withSources(TestConfigSource, testPS2);
+// ConfigContext ctx = b.build();
+// assertEquals(2, ctx.getSources().size());
+// assertTrue(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// // Ensure no sorting happens during add, so switch ordinals!
+// testPS2 = new TestConfigSource("withSources_Array", 1);
+// b = new ConfigContextBuilder()
+// .withSources(testPS2, TestConfigSource);
+// ctx = b.build();
+// assertEquals(2, ctx.getSources().size());
+// assertTrue(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// assertEquals(ctx.getSources().get(1).getName(), "TestConfigSource");
+// assertEquals(ctx.getSources().get(0).getName(), "withSources_Array");
+// }
+//
+// @Test
+// public void withSources_Collection() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("withSources_Collection", 1);
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withSources(Arrays.asList(new ConfigSource[]{TestConfigSource, testPS2}));
+// ConfigContext ctx = b.build();
+// assertEquals(2, ctx.getSources().size());
+// assertTrue(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// assertEquals(ctx.getSources().get(0).getName(), "TestConfigSource");
+// assertEquals(ctx.getSources().get(1).getName(), "withSources_Collection");
+// // Ensure no sorting happens during add, so switch ordinals!
+// testPS2 = new TestConfigSource("withSources_Collection", 1);
+// b = new ConfigContextBuilder()
+// .withSources(Arrays.asList(new ConfigSource[]{testPS2, TestConfigSource}));
+// ctx = b.build();
+// assertEquals(2, ctx.getSources().size());
+// assertTrue(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// assertEquals(ctx.getSources().get(1).getName(), "TestConfigSource");
+// assertEquals(ctx.getSources().get(0).getName(), "withSources_Collection");
+// }
+//
+// @Test
+// public void removeConfigSources_Array() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("removeConfigSources_Array", 1);
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withSources(TestConfigSource, testPS2);
+// ConfigContext ctx = b.build();
+// assertEquals(2, ctx.getSources().size());
+// assertTrue(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// b = new ConfigContextBuilder()
+// .withSources(TestConfigSource, testPS2);
+// b.removeSources(TestConfigSource);
+// ctx = b.build();
+// assertFalse(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// assertEquals(1, ctx.getSources().size());
+// }
+//
+// @Test
+// public void removeConfigSources_Collection() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("removeConfigSources_Array", 1);
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withSources(TestConfigSource, testPS2);
+// ConfigContext ctx = b.build();
+// assertEquals(2, ctx.getSources().size());
+// assertTrue(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// b = new ConfigContextBuilder()
+// .withSources(TestConfigSource, testPS2);
+// b.removeSources(TestConfigSource);
+// ctx = b.build();
+// assertEquals(1, ctx.getSources().size());
+// assertFalse(ctx.getSources().contains(TestConfigSource));
+// assertTrue(ctx.getSources().contains(testPS2));
+// }
+//
+// @Test
+// public void addPropertyFilters_Array() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// b.withFilters(filter1, filter2);
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = new ConfigContextBuilder();
+// b.withFilters(filter1, filter2);
+// b.withFilters(filter1, filter2);
+// assertEquals(2, ctx.getPropertyFilters().size());
+// }
+//
+// @Test
+// public void addPropertyFilters_Collection() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// b.withFilters(Arrays.asList(new Filter[]{filter1, filter2}));
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = new ConfigContextBuilder();
+// b.withFilters(filter1, filter2);
+// b.withFilters(filter1, filter2);
+// assertEquals(2, ctx.getPropertyFilters().size());
+// }
+//
+// @Test
+// public void removePropertyFilters_Array() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withFilters(filter1, filter2);
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = new ConfigContextBuilder()
+// .withFilters(filter1, filter2);
+// b.removeFilters(filter1);
+// ctx = b.build();
+// assertEquals(1, ctx.getPropertyFilters().size());
+// assertFalse(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// }
+//
+// @Test
+// public void removePropertyFilters_Collection() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withFilters(Arrays.asList(new Filter[]{filter1, filter2}));
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = new ConfigContextBuilder()
+// .withFilters(Arrays.asList(new Filter[]{filter1, filter2}));
+// b.removeFilters(filter1);
+// ctx = b.build();
+// assertEquals(1, ctx.getPropertyFilters().size());
+// assertFalse(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void addConverters_Array() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters().size());
+// b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// b.withConverters(TypeLiteral.of(String.class), converter);
+// assertEquals(1, ctx.getConverters().size());
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void addConverters_Collection() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class),
+// Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(ctx.getConverters().size(), 1);
+// b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class),
+// Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// b.withConverters(TypeLiteral.of(String.class), converter);
+// assertEquals(ctx.getConverters().size(), 1);
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void removeConverters_Array() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters(TypeLiteral.of(String.class)).size());
+// b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// b.removeConverters(TypeLiteral.of(String.class), converter);
+// ctx = b.build();
+// assertFalse(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).isEmpty());
+// }
+//
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// @Test
+// public void removeConverters_Collection() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class), Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// ConfigContext ctx = b.build();
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters(TypeLiteral.of(String.class)).size());
+// b = new ConfigContextBuilder()
+// .withConverters(TypeLiteral.of(String.class), Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// b.removeConverters(TypeLiteral.of(String.class), Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// ctx = b.build();
+// assertFalse(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).isEmpty());
+// }
+//
+// @Test
+// public void setPropertyValueCombinationPolicy() throws Exception {
+// ConfigValueCombinationPolicy combPol = (currentValue, key, ConfigSource) -> currentValue;
+// ConfigContextBuilder b = new ConfigContextBuilder()
+// .withPropertyValueCombinationPolicy(combPol);
+// ConfigContext ctx = b.build();
+// assertEquals(ctx.getConfigValueCombinationPolicy(), combPol);
+// }
+//
+// @Test
+// public void increasePriority(){
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// b.increasePriority(ConfigSources[ConfigSources.length-1]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.increasePriority(ConfigSources[ConfigSources.length-2]);
+// for(int i=0;i<ConfigSources.length-2;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[ConfigSources.length-1], b.getSources().get(ConfigSources.length-2));
+// assertEquals(ConfigSources[ConfigSources.length-2], b.getSources().get(ConfigSources.length-1));
+// }
+//
+// @Test
+// public void decreasePriority(){
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// b.decreasePriority(ConfigSources[0]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.decreasePriority(ConfigSources[1]);
+// for(int i=2;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[0], b.getSources().get(1));
+// assertEquals(ConfigSources[1], b.getSources().get(0));
+// }
+//
+// @Test
+// public void lowestPriority(){
+// // setup
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// // test
+// b.lowestPriority(ConfigSources[0]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.lowestPriority(ConfigSources[1]);
+// for(int i=2;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[0], b.getSources().get(1));
+// assertEquals(ConfigSources[1], b.getSources().get(0));
+// b.lowestPriority(ConfigSources[5]);
+// assertEquals(ConfigSources[5], b.getSources().get(0));
+// }
+//
+// @Test
+// public void highestPriority(){
+// // setup
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// // test
+// b.highestPriority(ConfigSources[ConfigSources.length-1]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.highestPriority(ConfigSources[ConfigSources.length-2]);
+// for(int i=0;i<ConfigSources.length-2;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[ConfigSources.length-2], b.getSources().get(ConfigSources.length-1));
+// assertEquals(ConfigSources[ConfigSources.length-1], b.getSources().get(ConfigSources.length-2));
+// b.highestPriority(ConfigSources[5]);
+// assertEquals(ConfigSources[5], b.getSources().get(ConfigSources.length-1));
+// }
+//
+// @Test
+// public void sortConfigSources(){
+// // setup
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// Comparator<ConfigSource> psComp = (o1, o2) -> o1.toString().compareTo(o2.toString());
+// // test
+// b.sortSources(psComp);
+// Arrays.sort(ConfigSources, psComp);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// }
+//
+// @Test
+// public void sortPropertyFilter(){
+// // setup
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// Filter[] filters = new Filter[10];
+// for(int i = 0; i< filters.length; i++){
+// filters[i] = (value) -> value.toBuilder().setValue(toString() + " - ").build();
+// }
+// b.withFilters(filters);
+// Comparator<Filter> pfComp = (o1, o2) -> o1.toString().compareTo(o2.toString());
+// // test
+// b.sortFilter(pfComp);
+// Arrays.sort(filters, pfComp);
+// for(int i = 0; i< filters.length; i++){
+// assertEquals(filters[i], b.getFilters().get(i));
+// }
+// }
+//
+// @Test
+// public void build() throws Exception {
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// ConfigContext ctx = b.build();
+// assertNotNull(ctx);
+// assertTrue(ctx.getSources().isEmpty());
+// assertTrue(ctx.getPropertyFilters().isEmpty());
+// }
+//
+// @Test
+// public void testRemoveAllFilters() throws Exception {
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// b.withFilters((value) -> value.toBuilder().setValue(toString() + " - ").build());
+// assertFalse(b.getFilters().isEmpty());
+// b.removeFilters(b.getFilters());
+// assertTrue(b.getFilters().isEmpty());
+// }
+//
+// @Test
+// public void testRemoveAllSources() throws Exception {
+// ConfigContextBuilder b = new ConfigContextBuilder();
+// b.withSources(new TestConfigSource());
+// assertFalse(b.getSources().isEmpty());
+// b.removeSources(b.getSources());
+// assertTrue(b.getFilters().isEmpty());
+// }
+//}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/ExtConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/ExtConfigBuilderTest.java b/code/core/src/test/java/org/apache/tamaya/core/ExtConfigBuilderTest.java
new file mode 100644
index 0000000..178d6a6
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/ExtConfigBuilderTest.java
@@ -0,0 +1,447 @@
+///*
+// * 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.TypeLiteral;
+//import org.apache.tamaya.spi.*;
+//import org.apache.tamaya.spi.Filter;
+//import org.junit.Test;
+//
+//import javax.config.Config;
+//import javax.config.ConfigProvider;
+//import javax.config.spi.ConfigBuilder;
+//import javax.config.spi.ConfigProviderResolver;
+//import javax.config.spi.ConfigSource;
+//import javax.config.spi.Converter;
+//import java.util.Arrays;
+//import java.util.Comparator;
+//
+//import static org.junit.Assert.*;
+//
+///**
+// * Tests for {@link ConfigBuilder} by atsticks on 06.09.16.
+// */
+//public class ExtConfigBuilderTest {
+//
+// private TestConfigSource testConfigSource = new TestConfigSource(){};
+//
+// @Test
+// public void fromConfig() throws Exception {
+// Config cfg = ConfigProvider.getConfig();
+// ConfigBuilder b = ExtConfigBuilder.create(cfg);
+// assertEquals(cfg, b.build());
+// }
+//
+// @Test
+// public void fromConfigBuilder() throws Exception {
+// ConfigBuilder b = ExtConfigBuilder.from(ConfigProviderResolver.instance().getBuilder());
+// assertNotNull(b);
+// }
+//
+// @Test
+// public void addConfigSources_Array() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("addConfigSources_Array", 1);
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withSources(testConfigSource, testPS2);
+// Config cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// // Ensure no sorting happens during add, so switch ordinals!
+// testPS2 = new TestConfigSource("addConfigSources_Array", 1);
+// b = ExtConfigBuilder.create()
+// .withSources(testPS2, testConfigSource);
+// cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// assertEquals(ConfigContext.of(cfg).getSources().get(1).getName(), "TestConfigSource");
+// assertEquals(ConfigContext.of(cfg).getSources().get(0).getName(), "addConfigSources_Array");
+// }
+//
+// @Test
+// public void addConfigSources_Collection() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("addConfigSources_Collection", 1);
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withSources(Arrays.asList(new ConfigSource[]{testConfigSource, testPS2}));
+// Config cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// assertEquals(ConfigContext.of(cfg).getSources().get(0).getName(), "TestConfigSource");
+// assertEquals(ConfigContext.of(cfg).getSources().get(1).getName(), "addConfigSources_Collection");
+// // Ensure no sorting happens during add, so switch ordinals!
+// testPS2 = new TestConfigSource("addConfigSources_Collection", 1);
+// b = ExtConfigBuilder.create()
+// .withSources(testPS2, testConfigSource);
+// cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// assertEquals(ConfigContext.of(cfg).getSources().get(1).getName(), "TestConfigSource");
+// assertEquals(ConfigContext.of(cfg).getSources().get(0).getName(), "addConfigSources_Collection");
+// }
+//
+// @Test
+// public void removeConfigSources_Array() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("removeConfigSources_Array", 1);
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withSources(testConfigSource, testPS2);
+// Config cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// b = ExtConfigBuilder.from(ConfigProviderResolver.instance().getBuilder()
+// .withSources(testConfigSource, testPS2));
+// b.removeSources(testConfigSource);
+// cfg = b.build();
+// assertFalse(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// assertEquals(1, ConfigContext.of(cfg).getSources().size());
+// }
+//
+// @Test
+// public void removeConfigSources_Collection() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("removeConfigSources_Array", 1);
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withSources(testConfigSource, testPS2);
+// Config cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// b = ExtConfigBuilder.from(ConfigProviderResolver.instance().getBuilder())
+// .withSources(testConfigSource, testPS2);
+// b.removeSources(testConfigSource);
+// cfg = b.build();
+// assertEquals(1, ConfigContext.of(cfg).getSources().size());
+// assertFalse(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// }
+//
+// @Test
+// public void addPropertyFilters_Array() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// b.withFilters(filter1, filter2);
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = ExtConfigBuilder.create();
+// b.withFilters(filter1, filter2);
+// b.withFilters(filter1, filter2);
+// assertEquals(2, ctx.getPropertyFilters().size());
+// }
+//
+// @Test
+// public void addPropertyFilters_Collection() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// b.withFilters(Arrays.asList(new Filter[]{filter1, filter2}));
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = ExtConfigBuilder.create();
+// b.withFilters(filter1, filter2);
+// b.withFilters(filter1, filter2);
+// assertEquals(2, ctx.getPropertyFilters().size());
+// }
+//
+// @Test
+// public void removePropertyFilters_Array() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withFilters(filter1, filter2);
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = ExtConfigBuilder.create()
+// .withFilters(filter1, filter2);
+// b.removeFilters(filter1);
+// cfg = b.build();
+// ctx = ConfigContext.of(cfg);
+// assertEquals(1, ctx.getPropertyFilters().size());
+// assertFalse(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// }
+//
+// @Test
+// public void removePropertyFilters_Collection() throws Exception {
+// Filter filter1 = (value) -> value;
+// Filter filter2 = (value) -> value;
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withFilters(Arrays.asList(new Filter[]{filter1, filter2}));
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// assertEquals(2, ctx.getPropertyFilters().size());
+// b = ExtConfigBuilder.create()
+// .withFilters(Arrays.asList(new Filter[]{filter1, filter2}));
+// b.removeFilters(filter1);
+// cfg = b.build();
+// ctx = ConfigContext.of(cfg);
+// assertEquals(1, ctx.getPropertyFilters().size());
+// assertFalse(ctx.getPropertyFilters().contains(filter1));
+// assertTrue(ctx.getPropertyFilters().contains(filter2));
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void addPropertyConverters_Array() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters().size());
+// b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// b.withConverters(TypeLiteral.of(String.class), converter);
+// assertEquals(1, ctx.getConverters().size());
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void addPropertyConverters_Collection() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class),
+// Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(ctx.getConverters().size(), 1);
+// b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class),
+// Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// b.withConverters(TypeLiteral.of(String.class), converter);
+// assertEquals(ctx.getConverters().size(), 1);
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void removePropertyConverters_Array() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ExtConfigBuilder b = b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters(TypeLiteral.of(String.class)).size());
+// b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class), converter);
+// b.removeConverters(TypeLiteral.of(String.class), converter);
+// cfg = b.build();
+// ctx = ConfigContext.of(cfg);
+// assertFalse(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).isEmpty());
+// }
+//
+//
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// @Test
+// public void removePropertyConverters_Collection() throws Exception {
+// Converter converter = (value) -> value.toLowerCase();
+// ExtConfigBuilder b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class), Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters(TypeLiteral.of(String.class)).size());
+// b = b = ExtConfigBuilder.create()
+// .withConverters(TypeLiteral.of(String.class), Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// b.removeConverters(TypeLiteral.of(String.class), Arrays.<Converter<Object>>asList(new Converter[]{converter}));
+// cfg = b.build();
+// ctx = ConfigContext.of(cfg);
+// assertFalse(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).isEmpty());
+// }
+//
+// @Test
+// public void setPropertyValueCombinationPolicy() throws Exception {
+// ConfigValueCombinationPolicy combPol = (currentValue, key, ConfigSource) -> currentValue;
+// ExtConfigBuilder b = b = ExtConfigBuilder.create()
+// .withPropertyValueCombinationPolicy(combPol);
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertEquals(ctx.getConfigValueCombinationPolicy(), combPol);
+// }
+//
+// @Test
+// public void increasePriority(){
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// b.increasePriority(ConfigSources[ConfigSources.length-1]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.increasePriority(ConfigSources[ConfigSources.length-2]);
+// for(int i=0;i<ConfigSources.length-2;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[ConfigSources.length-1], b.getSources().get(ConfigSources.length-2));
+// assertEquals(ConfigSources[ConfigSources.length-2], b.getSources().get(ConfigSources.length-1));
+// }
+//
+// @Test
+// public void decreasePriority(){
+// ExtConfigBuilder b = b = ExtConfigBuilder.create();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// b.decreasePriority(ConfigSources[0]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.decreasePriority(ConfigSources[1]);
+// for(int i=2;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[0], b.getSources().get(1));
+// assertEquals(ConfigSources[1], b.getSources().get(0));
+// }
+//
+// @Test
+// public void lowestPriority(){
+// // setup
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// // test
+// b.lowestPriority(ConfigSources[0]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.lowestPriority(ConfigSources[1]);
+// for(int i=2;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[0], b.getSources().get(1));
+// assertEquals(ConfigSources[1], b.getSources().get(0));
+// b.lowestPriority(ConfigSources[5]);
+// assertEquals(ConfigSources[5], b.getSources().get(0));
+// }
+//
+// @Test
+// public void highestPriority(){
+// // setup
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// // test
+// b.highestPriority(ConfigSources[ConfigSources.length-1]);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// b.highestPriority(ConfigSources[ConfigSources.length-2]);
+// for(int i=0;i<ConfigSources.length-2;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// assertEquals(ConfigSources[ConfigSources.length-2], b.getSources().get(ConfigSources.length-1));
+// assertEquals(ConfigSources[ConfigSources.length-1], b.getSources().get(ConfigSources.length-2));
+// b.highestPriority(ConfigSources[5]);
+// assertEquals(ConfigSources[5], b.getSources().get(ConfigSources.length-1));
+// }
+//
+// @Test
+// public void sortConfigSources(){
+// // setup
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// TestConfigSource[] ConfigSources = new TestConfigSource[10];
+// for(int i=0;i<ConfigSources.length;i++){
+// ConfigSources[i] = new TestConfigSource("ps"+i,i);
+// }
+// b.withSources(ConfigSources);
+// Comparator<ConfigSource> psComp = (o1, o2) -> o1.toString().compareTo(o2.toString());
+// // test
+// b.sortSources(psComp);
+// Arrays.sort(ConfigSources, psComp);
+// for(int i=0;i<ConfigSources.length;i++){
+// assertEquals(ConfigSources[i], b.getSources().get(i));
+// }
+// }
+//
+// @Test
+// public void sortPropertyFilter(){
+// // setup
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// Filter[] filters = new Filter[10];
+// for(int i = 0; i< filters.length; i++){
+// filters[i] = (value) -> value.toBuilder().setValue(toString() + " - ").build();
+// }
+// b.withFilters(filters);
+// Comparator<Filter> pfComp = (o1, o2) -> o1.toString().compareTo(o2.toString());
+// // test
+// b.sortFilter(pfComp);
+// Arrays.sort(filters, pfComp);
+// for(int i = 0; i< filters.length; i++){
+// assertEquals(filters[i], b.getFilters().get(i));
+// }
+// }
+//
+// @Test
+// public void build() throws Exception {
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertNotNull(ctx);
+// assertTrue(ctx.getSources().isEmpty());
+// assertTrue(ctx.getPropertyFilters().isEmpty());
+// }
+//
+// @Test
+// public void testRemoveAllFilters() throws Exception {
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// b.withFilters((value) -> value.toBuilder().setValue(toString() + " - ").build());
+// assertFalse(b.getFilters().isEmpty());
+// b.removeFilters(b.getFilters());
+// assertTrue(b.getFilters().isEmpty());
+// }
+//
+// @Test
+// public void testRemoveAllSources() throws Exception {
+// ExtConfigBuilder b = ExtConfigBuilder.create();
+// b.withSources(new TestConfigSource());
+// assertFalse(b.getSources().isEmpty());
+// b.removeSources(b.getSources());
+// assertTrue(b.getSources().isEmpty());
+// }
+//}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/TamayaConfigProviderResolverTest.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/TamayaConfigProviderResolverTest.java b/code/core/src/test/java/org/apache/tamaya/core/TamayaConfigProviderResolverTest.java
new file mode 100644
index 0000000..dafe7a3
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/TamayaConfigProviderResolverTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core;
+
+import org.apache.tamaya.core.TamayaConfigProviderResolver;
+import org.apache.tamaya.spi.ConfigContext;
+import org.apache.tamaya.spi.ConfigContextSupplier;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by atsticks on 11.09.16.
+ */
+public class TamayaConfigProviderResolverTest {
+
+ @Test
+ public void testInstantiation() throws Exception {
+ new TamayaConfigProviderResolver();
+ }
+
+ @Test
+ public void getConfiguration() throws Exception {
+ assertNotNull(new TamayaConfigProviderResolver().getConfig());
+ }
+
+ @Test
+ public void configIsConfigContextSupplier() throws Exception {
+ assertTrue(new TamayaConfigProviderResolver().getConfig() instanceof ConfigContextSupplier);
+ }
+
+ @Test
+ public void getBuilder() throws Exception {
+ assertNotNull(new TamayaConfigProviderResolver().getBuilder());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void registerConfig_CL() throws Exception {
+ new TamayaConfigProviderResolver()
+ .registerConfig(new TamayaConfigProviderResolver().getConfig(),
+ ClassLoader.getSystemClassLoader());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void registerConfig_Null() throws Exception {
+ new TamayaConfigProviderResolver()
+ .registerConfig(new TamayaConfigProviderResolver().getConfig(), null);
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/TestConfigSource.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/TestConfigSource.java b/code/core/src/test/java/org/apache/tamaya/core/TestConfigSource.java
new file mode 100644
index 0000000..35f380b
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/TestConfigSource.java
@@ -0,0 +1,67 @@
+/*
+ * 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.spi.ConfigSource;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Created by atsticks on 18.10.16.
+ */
+public class TestConfigSource implements ConfigSource {
+
+ private String id;
+ private int ordinal;
+
+ public TestConfigSource() {
+ this("TestConfigSource", 0);
+ }
+
+ public TestConfigSource(String id, int ordinal) {
+ this.id = id;
+ this.ordinal = ordinal;
+ }
+
+ public int getOrdinal() {
+ return ordinal;
+ }
+
+ @Override
+ public String getName() {
+ return id != null ? id : "TestConfigSource";
+ }
+
+ @Override
+ public String getValue(String key) {
+ if(key.endsWith("[meta]")){
+ return "ordinal=" + String.valueOf(getOrdinal()) + '\n'+
+ "createdAt=" + String.valueOf(new Date());
+ }
+ return key + "Value";
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ return Collections.emptyMap();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/testdata/TestConfigNamesSource.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/testdata/TestConfigNamesSource.java b/code/core/src/test/java/org/apache/tamaya/core/testdata/TestConfigNamesSource.java
new file mode 100644
index 0000000..eba5bb9
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/testdata/TestConfigNamesSource.java
@@ -0,0 +1,51 @@
+/*
+ * 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.testdata;
+
+import org.apache.tamaya.base.configsource.BaseConfigSource;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Test provider reading properties from classpath:cfg/defaults/**.properties.
+ */
+public class TestConfigNamesSource extends BaseConfigSource {
+
+ private Map<String,String> properties = new HashMap<>();
+
+ public TestConfigNamesSource() {
+ super(100);
+ properties.put("name","Anatole");
+ properties.put("name2", "Sabine");
+ properties = Collections.unmodifiableMap(properties);
+ }
+
+ @Override
+ public String getName() {
+ return "default-testdata-properties";
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/testdata/TestFilter.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/testdata/TestFilter.java b/code/core/src/test/java/org/apache/tamaya/core/testdata/TestFilter.java
new file mode 100644
index 0000000..9ffe868
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/testdata/TestFilter.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.testdata;
+
+import org.apache.tamaya.base.filter.FilterContext;
+import org.apache.tamaya.spi.Filter;
+import org.apache.tamaya.spi.ConfigValue;
+
+import javax.annotation.Priority;
+
+/**
+ * Simple PropertyFilter that filters exact one value, registered using ServiceLoader.
+ */
+@Priority(100)
+public class TestFilter implements Filter {
+ @Override
+ public ConfigValue filterProperty(ConfigValue valueToBeFiltered) {
+ FilterContext context = FilterContext.getContext();
+ if("name4".equals(valueToBeFiltered.getKey())){
+ return valueToBeFiltered.toBuilder()
+ .setValue(valueToBeFiltered.getValue() + "(filtered)")
+ .build();
+ }
+ return valueToBeFiltered;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/testdata/TestRemovingFilter.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/testdata/TestRemovingFilter.java b/code/core/src/test/java/org/apache/tamaya/core/testdata/TestRemovingFilter.java
new file mode 100644
index 0000000..4bead15
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/testdata/TestRemovingFilter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.testdata;
+
+import org.apache.tamaya.base.filter.FilterContext;
+import org.apache.tamaya.spi.Filter;
+import org.apache.tamaya.spi.ConfigValue;
+
+import javax.annotation.Priority;
+import javax.config.ConfigProvider;
+
+/**
+ * Simple PropertyFilter that filters exact one value, registered using ServiceLoader.
+ */
+@Priority(200)
+public class TestRemovingFilter implements Filter {
+ @Override
+ public ConfigValue filterProperty(ConfigValue valueToBeFiltered) {
+ FilterContext context = FilterContext.getContext();
+
+ if("name5".equals(valueToBeFiltered.getKey())){
+ return null;
+ }
+ else if("name3".equals(valueToBeFiltered.getKey())){
+ return valueToBeFiltered.toBuilder().setValue(
+ "Mapped to name: " + ConfigProvider.getConfig().getValue("name", String.class))
+ .build();
+ }
+ return valueToBeFiltered;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/resources/META-INF/javaconfig.properties
----------------------------------------------------------------------
diff --git a/code/core/src/test/resources/META-INF/javaconfig.properties b/code/core/src/test/resources/META-INF/javaconfig.properties
new file mode 100644
index 0000000..33beabb
--- /dev/null
+++ b/code/core/src/test/resources/META-INF/javaconfig.properties
@@ -0,0 +1,22 @@
+# 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.
+
+confkey1=javaconf-value1
+confkey2=javaconf-value2
+confkey3=javaconf-value3
+confkey4=javaconf-value4
+confkey5=javaconf-value5
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/resources/META-INF/javaconfig.xml
----------------------------------------------------------------------
diff --git a/code/core/src/test/resources/META-INF/javaconfig.xml b/code/core/src/test/resources/META-INF/javaconfig.xml
new file mode 100644
index 0000000..f6cdc97
--- /dev/null
+++ b/code/core/src/test/resources/META-INF/javaconfig.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <entry key="aaeehh">ä</entry>
+ <entry key="ö">o</entry>
+</properties>
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSource
----------------------------------------------------------------------
diff --git a/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSource b/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSource
new file mode 100644
index 0000000..74d685e
--- /dev/null
+++ b/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSource
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy current the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.tamaya.core.testdata.TestConfigNamesSource
+org.apache.tamaya.core.internal.converters.ConverterTestsPropertySource
+
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSourceProvider
----------------------------------------------------------------------
diff --git a/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSourceProvider b/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSourceProvider
new file mode 100644
index 0000000..c9f255a
--- /dev/null
+++ b/code/core/src/test/resources/META-INF/services/javax.config.spi.ConfigSourceProvider
@@ -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.core.testdata.TestPropertySourceProvider
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/resources/META-INF/services/javax.config.spi.Converter
----------------------------------------------------------------------
diff --git a/code/core/src/test/resources/META-INF/services/javax.config.spi.Converter b/code/core/src/test/resources/META-INF/services/javax.config.spi.Converter
new file mode 100644
index 0000000..d039696
--- /dev/null
+++ b/code/core/src/test/resources/META-INF/services/javax.config.spi.Converter
@@ -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.core.internal.CTestConverter
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/resources/META-INF/services/org.apache.tamaya.spi.Filter
----------------------------------------------------------------------
diff --git a/code/core/src/test/resources/META-INF/services/org.apache.tamaya.spi.Filter b/code/core/src/test/resources/META-INF/services/org.apache.tamaya.spi.Filter
new file mode 100644
index 0000000..d727173
--- /dev/null
+++ b/code/core/src/test/resources/META-INF/services/org.apache.tamaya.spi.Filter
@@ -0,0 +1,20 @@
+#
+# 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.core.testdata.TestFilter
+org.apache.tamaya.core.testdata.TestRemovingFilter
[5/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
new file mode 100644
index 0000000..2c300ad
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
@@ -0,0 +1,277 @@
+/*
+ * 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.spi.TypeLiteral;
+import org.apache.tamaya.spi.*;
+
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Logger;
+
+/**
+ * Default implementation of a simple ConfigurationContext.
+ */
+public class DefaultConfigurationContext implements ConfigurationContext {
+
+ /** The logger used. */
+ private final static Logger LOG = Logger.getLogger(DefaultConfigurationContext.class.getName());
+
+ /**
+ * Subcomponent handling {@link PropertyConverter} instances.
+ */
+ private final PropertyConverterManager propertyConverterManager = new PropertyConverterManager();
+
+ /**
+ * The current unmodifiable list of loaded {@link PropertySource} instances.
+ */
+ private List<PropertySource> immutablePropertySources;
+
+ /**
+ * The current unmodifiable list of loaded {@link PropertyFilter} instances.
+ */
+ private List<PropertyFilter> immutablePropertyFilters;
+
+ /**
+ * The overriding policy used when combining PropertySources registered to evalute the final configuration
+ * values.
+ */
+ private PropertyValueCombinationPolicy propertyValueCombinationPolicy;
+
+ /**
+ * Lock for internal synchronization.
+ */
+ private final ReentrantReadWriteLock propertySourceLock = new ReentrantReadWriteLock();
+
+ @SuppressWarnings("unchecked")
+ protected DefaultConfigurationContext(DefaultConfigurationContextBuilder builder) {
+ List<PropertySource> propertySources = new ArrayList<>();
+ // first we load all PropertySources which got registered via java.util.ServiceLoader
+ propertySources.addAll(builder.propertySources);
+ // now sort them according to their ordinal values
+ immutablePropertySources = Collections.unmodifiableList(propertySources);
+
+ // as next step we pick up the PropertyFilters pretty much the same way
+ List<PropertyFilter> propertyFilters = new ArrayList<>(builder.getPropertyFilters());
+ immutablePropertyFilters = Collections.unmodifiableList(propertyFilters);
+
+ // Finally add the converters
+ for(Map.Entry<TypeLiteral<?>, Collection<PropertyConverter<?>>> en:builder.getPropertyConverter().entrySet()) {
+ for (@SuppressWarnings("rawtypes") PropertyConverter converter : en.getValue()) {
+ this.propertyConverterManager.register(en.getKey(), converter);
+ }
+ }
+ LOG.info("Registered " + propertyConverterManager.getPropertyConverters().size() + " property converters: " +
+ propertyConverterManager.getPropertyConverters());
+
+ propertyValueCombinationPolicy = builder.combinationPolicy;
+ if(propertyValueCombinationPolicy==null){
+ propertyValueCombinationPolicy = ServiceContextManager.getServiceContext().getService(PropertyValueCombinationPolicy.class);
+ }
+ if(propertyValueCombinationPolicy==null){
+ propertyValueCombinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+ }
+ LOG.info("Using PropertyValueCombinationPolicy: " + propertyValueCombinationPolicy);
+ }
+
+
+ @Deprecated
+ @Override
+ public void addPropertySources(PropertySource... propertySourcesToAdd) {
+ Lock writeLock = propertySourceLock.writeLock();
+ try {
+ writeLock.lock();
+ List<PropertySource> newPropertySources = new ArrayList<>(this.immutablePropertySources);
+ newPropertySources.addAll(Arrays.asList(propertySourcesToAdd));
+ Collections.sort(newPropertySources, PropertySourceComparator.getInstance());
+
+ this.immutablePropertySources = Collections.unmodifiableList(newPropertySources);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultConfigurationContext)){
+ return false;
+ }
+
+ DefaultConfigurationContext that = (DefaultConfigurationContext) o;
+
+ if (!propertyConverterManager.equals(that.propertyConverterManager)) {
+ return false;
+ }
+ if (!immutablePropertySources.equals(that.immutablePropertySources)) {
+ return false;
+ }
+ if (!immutablePropertyFilters.equals(that.immutablePropertyFilters)) {
+ return false;
+ }
+ return getPropertyValueCombinationPolicy().equals(that.getPropertyValueCombinationPolicy());
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = propertyConverterManager.hashCode();
+ result = 31 * result + immutablePropertySources.hashCode();
+ result = 31 * result + immutablePropertyFilters.hashCode();
+ result = 31 * result + getPropertyValueCombinationPolicy().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder("ConfigurationContext{\n");
+ b.append(" Property Sources\n");
+ b.append(" ----------------\n");
+ if(immutablePropertySources.isEmpty()){
+ b.append(" No property sources loaded.\n\n");
+ }else {
+ b.append(" CLASS NAME ORDINAL SCANNABLE SIZE STATE ERROR\n\n");
+ for (PropertySource ps : immutablePropertySources) {
+ b.append(" ");
+ appendFormatted(b, ps.getClass().getSimpleName(), 30);
+ appendFormatted(b, ps.getName(), 70);
+ appendFormatted(b, String.valueOf(PropertySourceComparator.getOrdinal(ps)), 8);
+ appendFormatted(b, String.valueOf(ps.isScannable()), 10);
+ if (ps.isScannable()) {
+ appendFormatted(b, String.valueOf(ps.getProperties().size()), 8);
+ } else {
+ appendFormatted(b, "-", 8);
+ }
+ PropertyValue state = ps.get("_state");
+ if(state==null){
+ appendFormatted(b, "OK", 10);
+ }else {
+ appendFormatted(b, state.getValue(), 10);
+ if("ERROR".equals(state.getValue())){
+ PropertyValue val = ps.get("_exception");
+ if(val!=null) {
+ appendFormatted(b, val.getValue(), 30);
+ }
+ }
+ }
+ b.append('\n');
+ }
+ b.append("\n");
+ }
+ b.append(" Property Filters\n");
+ b.append(" ----------------\n");
+ if(immutablePropertyFilters.isEmpty()){
+ b.append(" No property filters loaded.\n\n");
+ }else {
+ b.append(" CLASS INFO\n\n");
+ for (PropertyFilter filter : getPropertyFilters()) {
+ b.append(" ");
+ appendFormatted(b, filter.getClass().getSimpleName(), 30);
+ b.append(removeNewLines(filter.toString()));
+ b.append('\n');
+ }
+ b.append("\n\n");
+ }
+ b.append(" Property Converters\n");
+ b.append(" -------------------\n");
+ b.append(" CLASS TYPE INFO\n\n");
+ for(Map.Entry<TypeLiteral<?>, List<PropertyConverter<?>>> converterEntry:getPropertyConverters().entrySet()){
+ for(PropertyConverter converter: converterEntry.getValue()){
+ b.append(" ");
+ appendFormatted(b, converter.getClass().getSimpleName(), 30);
+ appendFormatted(b, converterEntry.getKey().getRawType().getSimpleName(), 30);
+ b.append(removeNewLines(converter.toString()));
+ b.append('\n');
+ }
+ }
+ b.append("\n\n");
+ b.append(" PropertyValueCombinationPolicy: " + getPropertyValueCombinationPolicy().getClass().getName()).append('\n');
+ b.append('}');
+ return b.toString();
+ }
+
+ private void appendFormatted(StringBuilder b, String text, int length) {
+ int padding;
+ if(text.length() <= (length)){
+ b.append(text);
+ padding = length - text.length();
+ }else{
+ b.append(text.substring(0, length-1));
+ padding = 1;
+ }
+ for(int i=0;i<padding;i++){
+ b.append(' ');
+ }
+ }
+
+ private String removeNewLines(String s) {
+ return s.replace('\n', ' ').replace('\r', ' ');
+ }
+
+
+ @Override
+ public List<PropertySource> getPropertySources() {
+ return immutablePropertySources;
+ }
+
+ @Override
+ public PropertySource getPropertySource(String name) {
+ for(PropertySource ps:getPropertySources()){
+ if(name.equals(ps.getName())){
+ return ps;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public <T> void addPropertyConverter(TypeLiteral<T> typeToConvert, PropertyConverter<T> propertyConverter) {
+ propertyConverterManager.register(typeToConvert, propertyConverter);
+ LOG.info("Added PropertyConverter: " + propertyConverter.getClass().getName());
+ }
+
+ @Override
+ public Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters() {
+ return propertyConverterManager.getPropertyConverters();
+ }
+
+ @Override
+ public <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> targetType) {
+ return propertyConverterManager.getPropertyConverters(targetType);
+ }
+
+ @Override
+ public List<PropertyFilter> getPropertyFilters() {
+ return immutablePropertyFilters;
+ }
+
+ @Override
+ public PropertyValueCombinationPolicy getPropertyValueCombinationPolicy(){
+ return propertyValueCombinationPolicy;
+ }
+
+ @Override
+ public ConfigurationContextBuilder toBuilder() {
+ return new DefaultConfigurationContextBuilder(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java
new file mode 100644
index 0000000..0ee54da
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java
@@ -0,0 +1,431 @@
+/*
+ * 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.spi.TypeLiteral;
+import org.apache.tamaya.spi.*;
+import org.apache.tamaya.spisupport.propertysource.CLIPropertySource;
+import org.apache.tamaya.spisupport.propertysource.EnvironmentPropertySource;
+import org.apache.tamaya.spisupport.propertysource.JavaConfigurationPropertySource;
+import org.apache.tamaya.spisupport.propertysource.SystemPropertySource;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Default implementation of {@link ConfigurationContextBuilder}.
+ */
+public class DefaultConfigurationContextBuilder implements ConfigurationContextBuilder {
+
+ private static final Logger LOG = Logger.getLogger(DefaultConfigurationContextBuilder.class.getName());
+
+ protected List<PropertyFilter> propertyFilters = new ArrayList<>();
+ protected List<PropertySource> propertySources = new ArrayList<>();
+ protected PropertyValueCombinationPolicy combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_POLICY;
+ protected Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> propertyConverters = new HashMap<>();
+
+ /**
+ * Flag if the config has already been built.
+ * Configuration can be built only once
+ */
+ private boolean built;
+
+
+
+ /**
+ * Creates a new builder instance.
+ */
+ public DefaultConfigurationContextBuilder() {
+ }
+
+ /**
+ * Creates a new builder instance initializing it with the given context.
+ * @param context the context to be used, not null.
+ */
+ public DefaultConfigurationContextBuilder(ConfigurationContext context) {
+ this.propertyConverters.putAll(context.getPropertyConverters());
+ this.propertyFilters.addAll(context.getPropertyFilters());
+ for(PropertySource ps:context.getPropertySources()) {
+ addPropertySources(ps);
+ }
+ this.combinationPolicy = context.getPropertyValueCombinationPolicy();
+ }
+
+ /**
+ * Allows to reset configuration context during unit tests.
+ */
+ public final ConfigurationContextBuilder resetWithConfigurationContext(ConfigurationContext configurationContext) {
+ checkBuilderState();
+ //noinspection deprecation
+ this.propertyFilters.clear();
+ this.propertyFilters.addAll(configurationContext.getPropertyFilters());
+ this.propertySources.clear();
+ for(PropertySource ps:configurationContext.getPropertySources()) {
+ addPropertySources(ps);
+ }
+ this.propertyConverters.clear();
+ this.propertyConverters.putAll(configurationContext.getPropertyConverters());
+ this.combinationPolicy = configurationContext.getPropertyValueCombinationPolicy();
+ return this;
+ }
+
+
+ @Override
+ public ConfigurationContextBuilder setContext(ConfigurationContext context) {
+ checkBuilderState();
+ this.propertyConverters.putAll(context.getPropertyConverters());
+ for(PropertySource ps:context.getPropertySources()){
+ this.propertySources.add(ps);
+ }
+ this.propertyFilters.addAll(context.getPropertyFilters());
+ this.combinationPolicy = context.getPropertyValueCombinationPolicy();
+ return this;
+ }
+
+ @Override
+ public final ConfigurationContextBuilder addPropertySources(PropertySource... sources){
+ return addPropertySources(Arrays.asList(sources));
+ }
+
+ @Override
+ public ConfigurationContextBuilder addPropertySources(Collection<PropertySource> sources){
+ checkBuilderState();
+ for(PropertySource source:sources) {
+ if (!this.propertySources.contains(source)) {
+ this.propertySources.add(source);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder addDefaultPropertySources() {
+ checkBuilderState();
+ List<PropertySource> propertySources = new ArrayList<>();
+ addCorePropertyResources(propertySources);
+ for(PropertySource ps: ServiceContextManager.getServiceContext().getServices(PropertySource.class)) {
+ if(!propertySources.contains(ps)){
+ propertySources.add(ps);
+ }
+ }
+ for(PropertySourceProvider provider:
+ ServiceContextManager.getServiceContext().getServices(PropertySourceProvider.class)){
+ propertySources.addAll(provider.getPropertySources());
+ }
+ Collections.sort(propertySources, PropertySourceComparator.getInstance());
+ return addPropertySources(propertySources);
+ }
+
+ protected void addCorePropertyResources(List<PropertySource> propertySources) {
+ for(PropertySource ps: new PropertySource[]{
+ new EnvironmentPropertySource(),
+ new JavaConfigurationPropertySource(),
+ new CLIPropertySource(),
+ new SystemPropertySource()
+ }){
+ if(!propertySources.contains(ps)){
+ propertySources.add(ps);
+ }
+ }
+ }
+
+ @Override
+ public ConfigurationContextBuilder addDefaultPropertyFilters() {
+ checkBuilderState();
+ for(PropertyFilter pf:ServiceContextManager.getServiceContext().getServices(PropertyFilter.class)){
+ addPropertyFilters(pf);
+ }
+ return this;
+ }
+
+ @Override
+ public DefaultConfigurationContextBuilder addDefaultPropertyConverters() {
+ checkBuilderState();
+ addCorePropertyConverters();
+ for(Map.Entry<TypeLiteral, Collection<PropertyConverter>> en:getDefaultPropertyConverters().entrySet()){
+ for(PropertyConverter pc: en.getValue()) {
+ addPropertyConverters(en.getKey(), pc);
+ }
+ }
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void addCorePropertyConverters() {
+ // should be overridden by subclasses.
+ }
+
+ @Override
+ public final ConfigurationContextBuilder removePropertySources(PropertySource... propertySources) {
+ return removePropertySources(Arrays.asList(propertySources));
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertySources(Collection<PropertySource> propertySources) {
+ checkBuilderState();
+ this.propertySources.removeAll(propertySources);
+ return this;
+ }
+
+ protected PropertySource getPropertySource(String name) {
+ for(PropertySource ps:propertySources){
+ if(ps.getName().equals(name)){
+ return ps;
+ }
+ }
+ throw new IllegalArgumentException("No such PropertySource: "+name);
+ }
+
+ @Override
+ public List<PropertySource> getPropertySources() {
+ return Collections.unmodifiableList(this.propertySources);
+ }
+
+ @Override
+ public ConfigurationContextBuilder increasePriority(PropertySource propertySource) {
+ checkBuilderState();
+ int index = propertySources.indexOf(propertySource);
+ if(index<0){
+ throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+ }
+ if(index<(propertySources.size()-1)){
+ propertySources.remove(propertySource);
+ propertySources.add(index+1, propertySource);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder decreasePriority(PropertySource propertySource) {
+ checkBuilderState();
+ int index = propertySources.indexOf(propertySource);
+ if(index<0){
+ throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+ }
+ if(index>0){
+ propertySources.remove(propertySource);
+ propertySources.add(index-1, propertySource);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder highestPriority(PropertySource propertySource) {
+ checkBuilderState();
+ int index = propertySources.indexOf(propertySource);
+ if(index<0){
+ throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+ }
+ if(index<(propertySources.size()-1)){
+ propertySources.remove(propertySource);
+ propertySources.add(propertySource);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder lowestPriority(PropertySource propertySource) {
+ checkBuilderState();
+ int index = propertySources.indexOf(propertySource);
+ if(index<0){
+ throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+ }
+ if(index>0){
+ propertySources.remove(propertySource);
+ propertySources.add(0, propertySource);
+ }
+ return this;
+ }
+
+ @Override
+ public final ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters){
+ return addPropertyFilters(Arrays.asList(filters));
+ }
+
+ @Override
+ public final ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters){
+ checkBuilderState();
+ for(PropertyFilter f:filters) {
+ if (!this.propertyFilters.contains(f)) {
+ this.propertyFilters.add(f);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public final ConfigurationContextBuilder removePropertyFilters(PropertyFilter... filters) {
+ return removePropertyFilters(Arrays.asList(filters));
+ }
+
+ @Override
+ public final ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters) {
+ checkBuilderState();
+ this.propertyFilters.removeAll(filters);
+ return this;
+ }
+
+
+ @Override
+ public final <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... converters) {
+ return removePropertyConverters(typeToConvert, Arrays.asList(converters));
+ }
+
+ @Override
+ public final <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> converters) {
+ Collection<PropertyConverter<?>> subConverters = this.propertyConverters.get(typeToConvert);
+ if(subConverters!=null) {
+ subConverters.removeAll(converters);
+ }
+ return this;
+ }
+
+ @Override
+ public final ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert) {
+ this.propertyConverters.remove(typeToConvert);
+ return this;
+ }
+
+
+ @Override
+ public final ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy combinationPolicy){
+ checkBuilderState();
+ this.combinationPolicy = Objects.requireNonNull(combinationPolicy);
+ return this;
+ }
+
+
+ @Override
+ public <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> type, PropertyConverter<T>... propertyConverters){
+ checkBuilderState();
+ Objects.requireNonNull(type);
+ Objects.requireNonNull(propertyConverters);
+ Collection<PropertyConverter<?>> converters = this.propertyConverters.get(type);
+ if(converters==null){
+ converters = new ArrayList<>();
+ this.propertyConverters.put(type, converters);
+ }
+ for(PropertyConverter<T> propertyConverter:propertyConverters) {
+ if (!converters.contains(propertyConverter)) {
+ converters.add(propertyConverter);
+ } else {
+ LOG.warning("Converter ignored, already registered: " + propertyConverter);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> type, Collection<PropertyConverter<T>> propertyConverters){
+ checkBuilderState();
+ Objects.requireNonNull(type);
+ Objects.requireNonNull(propertyConverters);
+ Collection<PropertyConverter<?>> converters = this.propertyConverters.get(type);
+ if(converters==null){
+ converters = new ArrayList<>();
+ this.propertyConverters.put(type, converters);
+ }
+ for(PropertyConverter<T> propertyConverter:propertyConverters) {
+ if (!converters.contains(propertyConverter)) {
+ converters.add(propertyConverter);
+ } else {
+ LOG.warning("Converter ignored, already registered: " + propertyConverter);
+ }
+ }
+ return this;
+ }
+
+ protected ConfigurationContextBuilder loadDefaults() {
+ checkBuilderState();
+ this.combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+ addDefaultPropertySources();
+ addDefaultPropertyFilters();
+ addDefaultPropertyConverters();
+ return this;
+ }
+
+
+ protected Map<TypeLiteral, Collection<PropertyConverter>> getDefaultPropertyConverters() {
+ Map<TypeLiteral, Collection<PropertyConverter>> result = new HashMap<>();
+ for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(
+ PropertyConverter.class)) {
+ for(Type type:conv.getClass().getGenericInterfaces()){
+ if(type instanceof ParameterizedType){
+ ParameterizedType pt = (ParameterizedType)type;
+ if(PropertyConverter.class.equals(((ParameterizedType) type).getRawType())){
+ TypeLiteral target = TypeLiteral.of(pt.getActualTypeArguments()[0]);
+ Collection<PropertyConverter> convList = result.get(target);
+ if (convList == null) {
+ convList = new ArrayList<>();
+ result.put(target, convList);
+ }
+ convList.add(conv);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Builds a new configuration based on the configuration of this builder instance.
+ *
+ * @return a new {@link org.apache.tamaya.Configuration configuration instance},
+ * never {@code null}.
+ */
+ @Override
+ public ConfigurationContext build() {
+ checkBuilderState();
+ built = true;
+ return new DefaultConfigurationContext(this);
+ }
+
+ @Override
+ public ConfigurationContextBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator) {
+ Collections.sort(propertyFilters, comparator);
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder sortPropertySources(Comparator<PropertySource> comparator) {
+ Collections.sort(propertySources, comparator);
+ return this;
+ }
+
+ private void checkBuilderState() {
+ if (built) {
+ throw new IllegalStateException("Configuration has already been build.");
+ }
+ }
+
+ @Override
+ public List<PropertyFilter> getPropertyFilters() {
+ return propertyFilters;
+ }
+
+ @Override
+ public Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter() {
+ return Collections.unmodifiableMap(this.propertyConverters);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java
new file mode 100644
index 0000000..1dd00c0
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+/**
+ * Converter, converting from String to tge given enum type.
+ */
+public class EnumConverter<T extends Enum> implements PropertyConverter<T>{
+
+ private org.apache.tamaya.base.convert.EnumConverter<T> converter;
+
+ public EnumConverter(Class<T> enumType){
+ converter = new org.apache.tamaya.base.convert.EnumConverter<>(enumType);
+ }
+
+ @Override
+ public T convert(String value, ConversionContext context) {
+ return converter.convert(value);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
new file mode 100644
index 0000000..dbef51f
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spisupport;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for odering services loaded based on their increasing priority values.
+ */
+public class PriorityServiceComparator implements Comparator<Object>, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final PriorityServiceComparator INSTANCE = new PriorityServiceComparator();
+
+ /** Singleton constructor. */
+ private PriorityServiceComparator(){}
+
+ /**
+ * Get the shared instance of the comparator.
+ * @return the shared instance, never null.
+ */
+ public static PriorityServiceComparator getInstance(){
+ return INSTANCE;
+ }
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ int prio = getPriority(o1) - getPriority(o2);
+ if (prio < 0) {
+ return 1;
+ } else if (prio > 0) {
+ return -1;
+ } else {
+ return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+ }
+ }
+
+ /**
+ * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
+ * annotation is present, a default priority {@code 1} is returned.
+ *
+ * @param o the instance, not {@code null}.
+ * @return a priority, by default 1.
+ */
+ public static int getPriority(Object o) {
+ return getPriority(o.getClass());
+ }
+
+ /**
+ * Checks the given type optionally annotated with a @Priority. If present the annotation's value is evaluated.
+ * If no such annotation is present, a default priority {@code 1} is returned.
+ *
+ * @param type the type, not {@code null}.
+ * @return a priority, by default 1.
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static int getPriority(Class type) {
+ int prio = 1;
+ Priority priority = (Priority)type.getAnnotation(Priority.class);
+ if (priority != null) {
+ prio = priority.value();
+ }
+ return prio;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
new file mode 100644
index 0000000..7bc8d26
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
@@ -0,0 +1,472 @@
+/*
+ * 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.ConfigException;
+import org.apache.tamaya.spi.TypeLiteral;
+import org.apache.tamaya.base.PriorityServiceComparator;
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Manager that deals with {@link PropertyConverter} instances.
+ * This class is thread-safe.
+ */
+public class PropertyConverterManager {
+ /**
+ * The logger used.
+ */
+ private static final Logger LOG = Logger.getLogger(PropertyConverterManager.class.getName());
+ /**
+ * The registered converters.
+ */
+ private final Map<TypeLiteral<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>();
+ /**
+ * The transitive converters.
+ */
+ private final Map<TypeLiteral<?>, List<PropertyConverter<?>>> transitiveConverters = new ConcurrentHashMap<>();
+ /**
+ * The lock used.
+ */
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ private static final Comparator<Object> PRIORITY_COMPARATOR = new Comparator<Object>() {
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ int prio = org.apache.tamaya.base.PriorityServiceComparator.getPriority(o1) - PriorityServiceComparator.getPriority(o2);
+ if (prio < 0) {
+ return 1;
+ } else if (prio > 0) {
+ return -1;
+ } else {
+ return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+ }
+ }
+ };
+
+ /**
+ * Constructor.
+ */
+ public PropertyConverterManager() {
+ this(false);
+ }
+
+ public PropertyConverterManager(boolean init) {
+ if (init) {
+ initConverters();
+ }
+ }
+
+ /**
+ * Registers the default converters provided out of the box.
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected void initConverters() {
+ for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)) {
+ Type type = TypeLiteral.getGenericInterfaceTypeParameters(conv.getClass(), PropertyConverter.class)[0];
+ register(TypeLiteral.of(type), conv);
+ }
+ }
+
+ /**
+ * Registers a new converters instance.
+ *
+ * @param targetType the target type, not {@code null}.
+ * @param converter the converters, not {@code null}.
+ * @param <T> the type.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> void register(TypeLiteral<T> targetType, PropertyConverter<T> converter) {
+ Objects.requireNonNull(converter);
+ Lock writeLock = lock.writeLock();
+ try {
+ writeLock.lock();
+ List<PropertyConverter<?>> converters = List.class.cast(this.converters.get(targetType));
+ if(converters!=null && converters.contains(converter)){
+ return;
+ }
+ List<PropertyConverter<?>> newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ if(!newConverters.contains(converter)) {
+ newConverters.add(converter);
+ }
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.converters.put(targetType, Collections.unmodifiableList(newConverters));
+ // evaluate transitive closure for all inherited supertypes and implemented interfaces
+ // direct implemented interfaces
+ for (Class<?> ifaceType : targetType.getRawType().getInterfaces()) {
+ converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
+ newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ newConverters.add(converter);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
+ }
+ Class<?> superClass = targetType.getRawType().getSuperclass();
+ while (superClass != null && !superClass.equals(Object.class)) {
+ converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(superClass)));
+ newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ newConverters.add(converter);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.transitiveConverters.put(TypeLiteral.of(superClass), Collections.unmodifiableList(newConverters));
+ for (Class<?> ifaceType : superClass.getInterfaces()) {
+ converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
+ newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ newConverters.add(converter);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
+ }
+ superClass = superClass.getSuperclass();
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Allows to evaluate if a given target type is supported.
+ *
+ * @param targetType the target type, not {@code null}.
+ * @return true, if a converters for the given type is registered, or a default one can be created.
+ */
+ public boolean isTargetTypeSupported(TypeLiteral<?> targetType) {
+ return converters.containsKey(targetType) || transitiveConverters.containsKey(targetType) || createDefaultPropertyConverter(targetType) != null;
+ }
+
+ /**
+ * Get a map of all property converters currently registered. This will not contain the converters that
+ * may be created, when an instance is adapted, which provides a String constructor or compatible
+ * factory methods taking a single String instance.
+ *
+ * @return the current map of instantiated and registered converters.
+ * @see #createDefaultPropertyConverter(TypeLiteral)
+ */
+ public Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters() {
+ Lock readLock = lock.readLock();
+ try {
+ readLock.lock();
+ return new HashMap<>(this.converters);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ /**
+ * Get the list of all current registered converters for the given target type.
+ * If not converters are registered, they component tries to create and addSources a dynamic
+ * converters based on String constructor or static factory methods available.
+ * The converters provided are of the following type and returned in the following order:
+ * <ul>
+ * <li>Converters mapped explicitly to the required target type are returned first, ordered
+ * by decreasing priority. This means, if explicit converters are registered these are used
+ * primarily for converting a value.</li>
+ * <li>The target type of each explicitly registered converters also can be transitively mapped to
+ * 1) all directly implemented interfaces, 2) all its superclasses (except Object), 3) all the interfaces
+ * implemented by its superclasses. These groups of transitive converters is returned similarly in the
+ * order as mentioned, whereas also here a priority based decreasing ordering is applied.</li>
+ * <li>java.lang wrapper classes and native types are automatically mapped.</li>
+ * <li>If no explicit converters are registered, for Enum types a default implementation is provided that
+ * compares the configuration values with the different enum members defined (cases sensitive mapping).</li>
+ * </ul>
+ * <p>
+ * So given that list above directly registered mappings always are tried first, before any transitive mapping
+ * should be used. Also in all cases @Priority annotations are honored for ordering of the converters in place.
+ * Transitive conversion is supported for all directly implemented interfaces (including inherited ones) and
+ * the inheritance hierarchy (exception Object). Superinterfaces of implemented interfaces are ignored.
+ *
+ * @param targetType the target type, not {@code null}.
+ * @param <T> the type class
+ * @return the ordered list of converters (may be empty for not convertible types).
+ * @see #createDefaultPropertyConverter(TypeLiteral)
+ */
+ public <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> targetType) {
+ Lock readLock = lock.readLock();
+ List<PropertyConverter<T>> converterList = new ArrayList<>();
+ // direct mapped converters
+ try {
+ readLock.lock();
+ addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList);
+ addConvertersToList(List.class.cast(this.transitiveConverters.get(targetType)), converterList);
+ } finally {
+ readLock.unlock();
+ }
+ // handling of java.lang wrapper classes
+ TypeLiteral<T> boxedType = mapBoxedType(targetType);
+ if (boxedType != null) {
+ try {
+ readLock.lock();
+ addConvertersToList(List.class.cast(this.converters.get(boxedType)), converterList);
+ } finally {
+ readLock.unlock();
+ }
+ }
+ if (converterList.isEmpty() && !TypeLiteral.of(String.class).equals(targetType)) {
+ // adding any converters created on the fly, e.g. for enum types.
+ PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType);
+ if (defaultConverter != null) {
+ register(targetType, defaultConverter);
+ try {
+ readLock.lock();
+ addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList);
+ } finally {
+ readLock.unlock();
+ }
+ }
+ }
+ // check for parametrized types, ignoring param type
+ // direct mapped converters
+ if(targetType.getType()!=null) {
+ try {
+ readLock.lock();
+ addConvertersToList(List.class.cast(this.converters.get(
+ TypeLiteral.of(targetType.getRawType()))), converterList);
+ } finally {
+ readLock.unlock();
+ }
+ }
+ return converterList;
+ }
+
+ private <T> void addConvertersToList(Collection<PropertyConverter<T>> converters, List<PropertyConverter<T>> converterList) {
+ if (converters != null) {
+ for(PropertyConverter<T> conv:converters) {
+ if(!converterList.contains(conv)) {
+ converterList.add(conv);
+ }
+ }
+ }
+ }
+
+ /**
+ * Maps native types to the corresponding boxed types.
+ *
+ * @param targetType the native type.
+ * @param <T> the type
+ * @return the boxed type, or null.
+ */
+ @SuppressWarnings("unchecked")
+ private <T> TypeLiteral<T> mapBoxedType(TypeLiteral<T> targetType) {
+ Type parameterType = targetType.getType();
+ if (parameterType == int.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Integer.class));
+ }
+ if (parameterType == short.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Short.class));
+ }
+ if (parameterType == byte.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Byte.class));
+ }
+ if (parameterType == long.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Long.class));
+ }
+ if (parameterType == boolean.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
+ }
+ if (parameterType == char.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Character.class));
+ }
+ if (parameterType == float.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Float.class));
+ }
+ if (parameterType == double.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Double.class));
+ }
+ if (parameterType == int[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Integer[].class));
+ }
+ if (parameterType == short[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Short[].class));
+ }
+ if (parameterType == byte[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Byte[].class));
+ }
+ if (parameterType == long[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Long[].class));
+ }
+ if (parameterType == boolean.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
+ }
+ if (parameterType == char[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Character[].class));
+ }
+ if (parameterType == float[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Float[].class));
+ }
+ if (parameterType == double[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Double[].class));
+ }
+ return null;
+ }
+
+ /**
+ * Creates a dynamic PropertyConverter for the given target type.
+ *
+ * @param targetType the target type
+ * @param <T> the type class
+ * @return a new converters, or null.
+ */
+ protected <T> PropertyConverter<T> createDefaultPropertyConverter(final TypeLiteral<T> targetType) {
+ if (Enum.class.isAssignableFrom(targetType.getRawType())) {
+ return new EnumConverter(targetType.getRawType());
+ }
+ PropertyConverter<T> converter = null;
+ final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "valueOf", "instanceOf", "getInstance", "from", "fromString", "parse");
+ if (factoryMethod != null) {
+ converter = new DefaultPropertyConverter<>(factoryMethod, targetType.getRawType());
+ }
+ if (converter == null) {
+ final Constructor<T> constr;
+ try {
+ constr = targetType.getRawType().getDeclaredConstructor(String.class);
+ } catch (NoSuchMethodException e) {
+ LOG.log(Level.FINEST, "No matching constrctor for " + targetType, e);
+ return null;
+ }
+ converter = new PropertyConverter<T>() {
+ @Override
+ public T convert(String value, ConversionContext context) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ constr.setAccessible(true);
+ return null;
+ }
+ });
+ return null;
+ }
+ });
+ try {
+ return constr.newInstance(value);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Error creating new PropertyConverter instance " + targetType, e);
+ }
+ return null;
+ }
+ };
+ }
+ return converter;
+ }
+
+ /**
+ * Tries to evaluate a factory method that can be used to create an instance based on a String.
+ *
+ * @param type the target type
+ * @param methodNames the possible static method names
+ * @return the first method found, or null.
+ */
+ private Method getFactoryMethod(Class<?> type, String... methodNames) {
+ Method m;
+ for (String name : methodNames) {
+ try {
+ m = type.getDeclaredMethod(name, String.class);
+ return m;
+ } catch (NoSuchMethodException | RuntimeException e) {
+ LOG.finest("No such factory method found on type: " + type.getName() + ", methodName: " + name);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PropertyConverterManager)) {
+ return false;
+ }
+ PropertyConverterManager that = (PropertyConverterManager) o;
+ return converters.equals(that.converters);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return converters.hashCode();
+ }
+
+ /**
+ * Default converters imüöementation perfoming several lookups for String converion
+ * option.
+ * @param <T>
+ */
+ private static class DefaultPropertyConverter<T> implements PropertyConverter<T> {
+
+ private final Method factoryMethod;
+ private final Class<T> targetType;
+
+ DefaultPropertyConverter(Method factoryMethod, Class<T> targetType){
+ this.factoryMethod = Objects.requireNonNull(factoryMethod);
+ this.targetType = Objects.requireNonNull(targetType);
+ }
+
+ @Override
+ public T convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<String -> "+factoryMethod.toGenericString());
+
+ if (!Modifier.isStatic(factoryMethod.getModifiers())) {
+ throw new ConfigException(factoryMethod.toGenericString() +
+ " is not a static method. Only static " +
+ "methods can be used as factory methods.");
+ }
+ try {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ factoryMethod.setAccessible(true);
+ return null;
+ }
+ });
+ Object invoke = factoryMethod.invoke(null, value);
+ return targetType.cast(invoke);
+ } catch (Exception e) {
+ throw new ConfigException("Failed to decode '" + value + "'", e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
new file mode 100644
index 0000000..20eef63
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
@@ -0,0 +1,72 @@
+/*
+ * 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.spi.PropertyFilter;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator for PropertyFilters based on their priority annotations.
+ */
+public final class PropertyFilterComparator implements Comparator<PropertyFilter>, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final PropertyFilterComparator INSTANCE = new PropertyFilterComparator();
+
+ /**
+ * Get the shared instance of the comparator.
+ * @return the shared instance, never null.
+ */
+ public static PropertyFilterComparator getInstance(){
+ return INSTANCE;
+ }
+
+ private PropertyFilterComparator(){}
+
+ /**
+ * Compare 2 filters for ordering the filter chain.
+ *
+ * @param filter1 the first filter
+ * @param filter2 the second filter
+ * @return the comparison result
+ */
+ private int comparePropertyFilters(PropertyFilter filter1, PropertyFilter filter2) {
+ Priority prio1 = filter1.getClass().getAnnotation(Priority.class);
+ Priority prio2 = filter2.getClass().getAnnotation(Priority.class);
+ int ord1 = prio1 != null ? prio1.value() : 0;
+ int ord2 = prio2 != null ? prio2.value() : 0;
+
+ if (ord1 < ord2) {
+ return -1;
+ } else if (ord1 > ord2) {
+ return 1;
+ } else {
+ return filter1.getClass().getName().compareTo(filter2.getClass().getName());
+ }
+ }
+
+ @Override
+ public int compare(PropertyFilter filter1, PropertyFilter filter2) {
+ return comparePropertyFilters(filter1, filter2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
new file mode 100644
index 0000000..af69899
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
@@ -0,0 +1,123 @@
+/*
+ * 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.spi.ConfigurationContext;
+import org.apache.tamaya.spi.FilterContext;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the
+ * chain of {@link org.apache.tamaya.spi.PropertySource} and {@link PropertyFilter}
+ * instance to evaluate the current Configuration.
+ */
+public final class PropertyFiltering{
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(PropertyFiltering.class.getName());
+ /**
+ * The maximal number of filter cycles performed before aborting.
+ */
+ private static final int MAX_FILTER_LOOPS = 10;
+
+ /**
+ * Private singleton constructor.
+ */
+ private PropertyFiltering(){}
+
+ /**
+ * Filters a single value.
+ * @param value the raw value, not {@code null}.
+ * @param context the context
+ * @return the filtered value, including {@code null}.
+ */
+ public static PropertyValue applyFilter(PropertyValue value, ConfigurationContext context) {
+ FilterContext filterContext = new FilterContext(value, context);
+ return filterValue(filterContext);
+ }
+
+ /**
+ * Filters all properties.
+ * @param rawProperties the unfiltered properties, not {@code null}.
+ * @param context the context
+ * @return the filtered value, inclusing null.
+ */
+ public static Map<String, PropertyValue> applyFilters(Map<String, PropertyValue> rawProperties, ConfigurationContext context) {
+ Map<String, PropertyValue> result = new HashMap<>();
+ // Apply filters to values, prevent values filtered to null!
+ for (Map.Entry<String, PropertyValue> entry : rawProperties.entrySet()) {
+ FilterContext filterContext = new FilterContext(entry.getValue(), rawProperties, context);
+ PropertyValue filtered = filterValue(filterContext);
+ if(filtered!=null){
+ result.put(filtered.getKey(), filtered);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Basic filter logic.
+ * @param context the filter context, not {@code null}.
+ * @return the filtered value.
+ */
+ private static PropertyValue filterValue(FilterContext context) {
+ PropertyValue inputValue = context.getProperty();
+ PropertyValue filteredValue = inputValue;
+
+ for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
+ int changes = 0;
+ for (PropertyFilter filter : context.getContext().getPropertyFilters()) {
+ filteredValue = filter.filterProperty(inputValue, context);
+ if (filteredValue != null && !filteredValue.equals(inputValue)) {
+ changes++;
+ LOG.finest("Filter - " + inputValue + " -> " + filteredValue + " by " + filter);
+ }
+ if(filteredValue==null){
+ LOG.finest("Filter removed entry - " + inputValue + ": " + filter);
+ break;
+ }else{
+ inputValue = filteredValue;
+ }
+ }
+ if (changes == 0) {
+ LOG.finest("Finishing filter loop, no changes detected.");
+ break;
+ } else if (filteredValue == null) {
+ break;
+ } else {
+ if (i == (MAX_FILTER_LOOPS - 1)) {
+ if (LOG.isLoggable(Level.WARNING)) {
+ LOG.warning("Maximal filter loop count reached, aborting filter evaluation after cycles: " + i);
+ }
+ } else {
+ LOG.finest("Repeating filter loop, changes detected: " + changes);
+ }
+ }
+ }
+ return filteredValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
new file mode 100644
index 0000000..e9511b5
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.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.spisupport;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.logging.Logger;
+
+/**
+ * Comparator for ordering of PropertySources based on their ordinal method and class name.
+ */
+public class PropertySourceComparator implements Comparator<PropertySource>, Serializable {
+ /** serial version UID. */
+ private static final long serialVersionUID = 1L;
+
+ private static final Logger LOG = Logger.getLogger(PropertySourceComparator.class.getName());
+
+ private static final PropertySourceComparator INSTANCE = new PropertySourceComparator();
+
+ private String alternativeOrdinalKey;
+
+ /** Singleton constructor. */
+ private PropertySourceComparator(){}
+
+ /**
+ * Get the shared instance of the comparator.
+ * @return the shared instance, never null.
+ */
+ public static PropertySourceComparator getInstance(){
+ return INSTANCE;
+ }
+
+
+ /**
+ * Order property source reversely, the most important comes first.
+ *
+ * @param source1 the first PropertySource
+ * @param source2 the second PropertySource
+ * @return the comparison result.
+ */
+ private int comparePropertySources(PropertySource source1, PropertySource source2) {
+ if (getOrdinal(source1) < getOrdinal(source2)) {
+ return -1;
+ } else if (getOrdinal(source1) > getOrdinal(source2)) {
+ return 1;
+ } else {
+ return source1.getClass().getName().compareTo(source2.getClass().getName());
+ }
+ }
+
+ /**
+ * Evaluates an ordinal value from a {@link PropertySource}, Hereby the ordinal of type {@code int}
+ * is evaluated as follows:
+ * <ol>
+ * <li>It evaluates the {@code String} value for {@link PropertySource#TAMAYA_ORDINAL} and tries
+ * to convert it to an {@code int} value, using {@link Integer#parseInt(String)}.</li>
+ * <li>It tries to find and evaluate a method {@code int getOrdinal()}.</li>
+ * <li>It tries to find and evaluate a static field {@code int ORDINAL}.</li>
+ * <li>It tries to find and evaluate a class level {@link Priority} annotation.</li>
+ * <li>It uses the default priority ({@code 0}.</li>
+ * </ol>
+ * @param propertySource the property source, not {@code null}.
+ * @return the ordinal value to compare the property source.
+ */
+ public static int getOrdinal(PropertySource propertySource) {
+ return getOrdinal(propertySource, null);
+ }
+
+ public static int getOrdinal(PropertySource propertySource, String alternativeOrdinalKey) {
+ if(alternativeOrdinalKey!=null) {
+ PropertyValue ordinalValue = propertySource.get(alternativeOrdinalKey);
+ if (ordinalValue != null) {
+ try {
+ return Integer.parseInt(ordinalValue.getValue().trim());
+ } catch (Exception e) {
+ LOG.finest("Failed to parse ordinal from " + alternativeOrdinalKey +
+ " in " + propertySource.getName() + ": " + ordinalValue.getValue());
+ }
+ }
+ }
+ return propertySource.getOrdinal();
+ }
+
+ /**
+ * Overrides/adds the key to evaluate/override a property sources ordinal.
+ * @param ordinalKey sets the alternative ordinal key, if null default
+ * behaviour will be active.
+ * @return the instance for chaining.
+ */
+ public PropertySourceComparator setOrdinalKey(String ordinalKey) {
+ this.alternativeOrdinalKey = ordinalKey;
+ return this;
+ }
+
+ @Override
+ public int compare(PropertySource source1, PropertySource source2) {
+ return comparePropertySources(source1, source2);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java
new file mode 100644
index 0000000..9be444f
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.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.spisupport;
+
+import org.apache.tamaya.spi.FilterContext;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Predicate filtering using a regex expression operating on the key. It allows either
+ * to define the target keys to be selected (includes), or to be excluded (excludes).
+ */
+public final class RegexPropertyFilter implements PropertyFilter {
+ /** The expression used to include entries that match. */
+ private List<String> includes;
+ /** The expression used to exclude entries that match. */
+ private List<String> excludes;
+
+ /**
+ * Sets the regex expression to be applied on the key to filter the corresponding entry
+ * if matching.
+ * @param expressions the regular expression for inclusion, not null.
+ */
+ public void setIncludes(String... expressions){
+ this.includes = Arrays.asList(expressions);
+ }
+
+ /**
+ * Sets the regex expression to be applied on the key to remove the corresponding entries
+ * if matching.
+ * @param expressions the regular expressions for exclusion, not null.
+ */
+ public void setExcludes(String... expressions){
+ this.excludes= Arrays.asList(expressions);
+ }
+
+ @Override
+ public PropertyValue filterProperty(PropertyValue valueToBeFiltered, FilterContext context) {
+ if(includes!=null){
+ for(String expression:includes){
+ if(context.getProperty().getKey().matches(expression)){
+ return valueToBeFiltered;
+ }
+ }
+ return null;
+ }
+ if(excludes!=null){
+ for(String expression:excludes){
+ if(context.getProperty().getKey().matches(expression)){
+ return null;
+ }
+ }
+ }
+ return valueToBeFiltered;
+ }
+
+ @Override
+ public String toString() {
+ return "RegexPropertyFilter{" +
+ "includes='" + includes + '\'' +
+ "excludes='" + excludes + '\'' +
+ '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
new file mode 100644
index 0000000..6126b68
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
@@ -0,0 +1,172 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Abstract {@link org.apache.tamaya.spi.PropertySource} that allows to set a default ordinal that will be used, if no
+ * ordinal is provided with the config.
+ */
+public abstract class BasePropertySource implements PropertySource{
+ /** default ordinal that will be used, if no ordinal is provided with the config. */
+ private int defaultOrdinal;
+ /** Used if the ordinal has been set explicitly. */
+ private volatile Integer ordinal;
+ /** The name of the property source. */
+ private String name;
+
+ /**
+ * Constructor.
+ * @param name the (unique) property source name, not {@code null}.
+ */
+ protected BasePropertySource(String name){
+ this.name = Objects.requireNonNull(name);
+ this.defaultOrdinal = 0;
+ }
+
+ /**
+ * Constructor.
+ * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided with the config.
+ */
+ protected BasePropertySource(int defaultOrdinal){
+ this.name = getClass().getSimpleName();
+ this.defaultOrdinal = defaultOrdinal;
+ }
+
+ /**
+ * Constructor.
+ * @param name the (unique) property source name, not {@code null}.
+ * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided with the config.
+ */
+ protected BasePropertySource(String name, int defaultOrdinal){
+ this.name = Objects.requireNonNull(name);
+ this.defaultOrdinal = defaultOrdinal;
+ }
+
+
+ /**
+ * Constructor, using a default ordinal of 0.
+ */
+ protected BasePropertySource(){
+ this(0);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the property source's (unique) name.
+ * @param name the name, not {@code null}.
+ */
+ public void setName(String name){
+ this.name = Objects.requireNonNull(name);
+ }
+
+ /**
+ * Allows to set the ordinal of this property source explcitly. This will override any evaluated
+ * ordinal, or default ordinal. To reset an explcit ordinal call {@code setOrdinal(null);}.
+ * @param ordinal the explicit ordinal, or {@code null}.
+ */
+ public void setOrdinal(Integer ordinal){
+ this.ordinal = ordinal;
+ }
+
+ /**
+ * Allows to set the ordinal of this property source explcitly. This will override any evaluated
+ * ordinal, or default ordinal. To reset an explcit ordinal call {@code setOrdinal(null);}.
+ * @param defaultOrdinal the default ordinal, or {@code null}.
+ */
+ public void setDefaultOrdinal(Integer defaultOrdinal){
+ this.defaultOrdinal = defaultOrdinal;
+ }
+
+ public int getOrdinal() {
+ Integer ordinal = this.ordinal;
+ if(ordinal!=null){
+ Logger.getLogger(getClass().getName()).finest(
+ "Using explicit ordinal '"+ordinal+"' for property source: " + getName());
+ return ordinal;
+ }
+ PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
+ if(configuredOrdinal!=null){
+ try {
+ return Integer.parseInt(configuredOrdinal.getValue());
+ } catch (Exception e) {
+ Logger.getLogger(getClass().getName()).log(Level.WARNING,
+ "Configured ordinal is not an int number: " + configuredOrdinal, e);
+ }
+ }
+ return getDefaultOrdinal();
+ }
+
+ /**
+ * Returns the default ordinal used, when no ordinal is set, or the ordinal was not parseable to an int value.
+ * @return the default ordinal used, by default 0.
+ */
+ public int getDefaultOrdinal(){
+ return defaultOrdinal;
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ Map<String,PropertyValue> properties = getProperties();
+ PropertyValue val = properties.get(key);
+ if(val==null){
+ return null;
+ }
+ return val;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BasePropertySource that = (BasePropertySource) o;
+
+ return name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" +
+ toStringValues() +
+ '}';
+ }
+
+ protected String toStringValues() {
+ return " defaultOrdinal=" + defaultOrdinal + '\n' +
+ " ordinal=" + ordinal + '\n' +
+ " name='" + name + '\'' + '\n';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
new file mode 100644
index 0000000..fbea188
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
@@ -0,0 +1,231 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.*;
+
+/**
+ * A Buildable property source.
+ */
+public class BuildablePropertySource implements PropertySource{
+
+ private int ordinal;
+ private String name = "PropertySource-"+UUID.randomUUID().toString();
+ private Map<String,PropertyValue> properties = new HashMap<>();
+
+ @Override
+ public int getOrdinal() {
+ return ordinal;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ return properties.get(key);
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return Collections.unmodifiableMap(properties);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BuildablePropertySource that = (BuildablePropertySource) o;
+
+ return name.equals(that.name);
+ }
+
+ @Override
+ public boolean isScannable() {
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "BuildablePropertySource{" +
+ "ordinal=" + ordinal +
+ ", name='" + name + '\'' +
+ ", properties=" + properties +
+ '}';
+ }
+
+ /**
+ * Builder builder.
+ *
+ * @return the builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+ /**
+ * The type Builder.
+ */
+ public static final class Builder {
+ private int ordinal;
+ private String source = "<on-the-fly-build>";
+ private String name = "PropertySource-"+ UUID.randomUUID().toString();
+ private Map<String,PropertyValue> properties = new HashMap<>();
+
+ private Builder() {
+ }
+
+ /**
+ * With ordinal builder.
+ *
+ * @param ordinal the ordinal
+ * @return the builder
+ */
+ public Builder withOrdinal(int ordinal) {
+ this.ordinal = ordinal;
+ return this;
+ }
+
+ /**
+ * With source builder.
+ *
+ * @param source the source
+ * @return the builder
+ */
+ public Builder withSource(String source) {
+ this.source = Objects.requireNonNull(source);
+ return this;
+ }
+
+ /**
+ * With name builder.
+ *
+ * @param name the name
+ * @return the builder
+ */
+ public Builder withName(String name) {
+ this.name = Objects.requireNonNull(name);
+ return this;
+ }
+
+ /**
+ * With simple property builder.
+ *
+ * @param key the key
+ * @param value the value
+ * @return the builder
+ */
+ public Builder withSimpleProperty(String key, String value) {
+ return withProperties(PropertyValue.of(key, value, this.source));
+ }
+
+ /**
+ * With simple property builder.
+ *
+ * @param key the key
+ * @param value the value
+ * @param source the source
+ * @return the builder
+ */
+ public Builder withSimpleProperty(String key, String value, String source) {
+ return withProperties(PropertyValue.of(key, value, source));
+ }
+
+ /**
+ * With properties builder.
+ *
+ * @param values the values
+ * @return the builder
+ */
+ public Builder withProperties(PropertyValue... values) {
+ for(PropertyValue val:values){
+ this.properties.put(val.getKey(), val);
+ }
+ return this;
+ }
+
+ /**
+ * With properties builder.
+ *
+ * @param properties the properties
+ * @return the builder
+ */
+ public Builder withProperties(Map<String, PropertyValue> properties) {
+ this.properties = Objects.requireNonNull(properties);
+ return this;
+ }
+
+ /**
+ * With properties builder.
+ *
+ * @param properties the properties
+ * @param source the source
+ * @return the builder
+ */
+ public Builder withProperties(Map<String, String> properties, String source) {
+ this.properties.putAll(PropertyValue.map(properties, source));
+ return this;
+ }
+
+ /**
+ * With simple properties builder.
+ *
+ * @param properties the properties
+ * @return the builder
+ */
+ public Builder withSimpleProperties(Map<String, String> properties) {
+ this.properties.putAll(PropertyValue.map(properties, this.source));
+ return this;
+ }
+
+ /**
+ * But builder.
+ *
+ * @return the builder
+ */
+ public Builder but() {
+ return builder().withOrdinal(ordinal).withName(name).withProperties(properties);
+ }
+
+ /**
+ * Build buildable property source.
+ *
+ * @return the buildable property source
+ */
+ public BuildablePropertySource build() {
+ BuildablePropertySource buildablePropertySource = new BuildablePropertySource();
+ buildablePropertySource.name = this.name;
+ buildablePropertySource.properties = this.properties;
+ buildablePropertySource.ordinal = this.ordinal;
+ return buildablePropertySource;
+ }
+ }
+}
[2/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/java/org/apache/tamaya/core/converters/DoubleConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/DoubleConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/DoubleConverter.java
new file mode 100644
index 0000000..eb5b717
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/DoubleConverter.java
@@ -0,0 +1,94 @@
+/*
+ * 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 Double, using the Java number syntax:
+ * (-)?[0-9]*\.[0-9]*. In case of error the value given also is tried being parsed as integral number using
+ * {@link LongConverter}. Additionally the following values are supported:
+ * <ul>
+ * <li>NaN (ignoring case)</li>
+ * <li>POSITIVE_INFINITY (ignoring case)</li>
+ * <li>NEGATIVE_INFINITY (ignoring case)</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class DoubleConverter implements Converter<Double> {
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(DoubleConverter.class.getName());
+ /**
+ * The converter used, when floating point parse failed.
+ */
+ private final LongConverter integerConverter = new LongConverter();
+
+ @Override
+ public Double convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), "<double>", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE", "POSITIVE_INFINITY", "NEGATIVE_INFINITY", "NAN");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch (trimmed.toUpperCase(Locale.ENGLISH)) {
+ case "POSITIVE_INFINITY":
+ return Double.POSITIVE_INFINITY;
+ case "NEGATIVE_INFINITY":
+ return Double.NEGATIVE_INFINITY;
+ case "NAN":
+ return Double.NaN;
+ case "MIN_VALUE":
+ case "MIN":
+ return Double.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Double.MAX_VALUE;
+ default:
+ try {
+ return Double.valueOf(trimmed);
+ } catch (Exception e) {
+ // OK perhaps we have an integral number that must be converted to the double type...
+ LOG.finest("Parsing of double as floating number failed, trying parsing integral" +
+ " number/hex instead...");
+ }
+ Long val = integerConverter.convert(trimmed);
+ if(val!=null){
+ return val.doubleValue();
+ }
+ 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/DurationConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/DurationConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/DurationConverter.java
new file mode 100644
index 0000000..eb05097
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/DurationConverter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class DurationConverter implements Converter<Duration> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public Duration convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(),
+ Duration.of(1234, ChronoUnit.SECONDS).toString());
+ try {
+ return Duration.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse Duration: " + 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/FileConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/FileConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/FileConverter.java
new file mode 100644
index 0000000..38badd4
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/FileConverter.java
@@ -0,0 +1,63 @@
+/*
+ * 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.io.File;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to URI, using new URL(value).
+ */
+@Component(service = Converter.class)
+public class FileConverter implements Converter<File> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public File convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ if(value==null || value.isEmpty()){
+ return null;
+ }
+ context.addSupportedFormats(getClass(),"<File>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return new File(trimmed);
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unparseable File Name: " + trimmed, 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/FloatConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/FloatConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/FloatConverter.java
new file mode 100644
index 0000000..b66a8e1
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/FloatConverter.java
@@ -0,0 +1,94 @@
+/*
+ * 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 Float, using the Java number syntax:
+ * (-)?[0-9]*\.[0-9]*. In case of error the value given also is tried being parsed as integral number using
+ * {@link LongConverter}. Additionally the following values are supported:
+ * <ul>
+ * <li>NaN (ignoring case)</li>
+ * <li>POSITIVE_INFINITY (ignoring case)</li>
+ * <li>NEGATIVE_INFINITY (ignoring case)</li>
+ * </ul>
+ */
+@Component(service = Converter.class)
+public class FloatConverter implements Converter<Float> {
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(FloatConverter.class.getName());
+ /**
+ * The converter used, when floating point parse failed.
+ */
+ private final IntegerConverter integerConverter = new IntegerConverter();
+
+ @Override
+ public Float convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), "<float>", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE", "POSITIVE_INFINITY", "NEGATIVE_INFINITY", "NAN");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "POSITIVE_INFINITY":
+ return Float.POSITIVE_INFINITY;
+ case "NEGATIVE_INFINITY":
+ return Float.NEGATIVE_INFINITY;
+ case "NAN":
+ return Float.NaN;
+ case "MIN_VALUE":
+ case "MIN":
+ return Float.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Float.MAX_VALUE;
+ default:
+ try {
+ return Float.valueOf(trimmed);
+ } catch(Exception e){
+ // OK perhaps we have an integral number that must be converted to the double type...
+ LOG.finest("Parsing of float as floating number failed, trying parsing integral" +
+ " number/hex instead...");
+ }
+ Integer val = integerConverter.convert(trimmed);
+ if(val!=null) {
+ return val.floatValue();
+ }
+ LOG.finest("Unparseable float value: " + 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/InstantConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/InstantConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/InstantConverter.java
new file mode 100644
index 0000000..b6d485f
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/InstantConverter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.time.Instant;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class InstantConverter implements Converter<Instant> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public Instant convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), Instant.now().toString());
+ try{
+ return Instant.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse Instant: " + 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/IntegerConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/IntegerConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/IntegerConverter.java
new file mode 100644
index 0000000..5a62a23
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/IntegerConverter.java
@@ -0,0 +1,87 @@
+/*
+ * 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 Integer, 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 IntegerConverter implements Converter<Integer> {
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(IntegerConverter.class.getName());
+
+ @Override
+ public Integer convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), "<int>", "MIN_VALUE", "MIN", "MAX_VALUE", "MAX");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "MIN_VALUE":
+ case "MIN":
+ return Integer.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Integer.MAX_VALUE;
+ default:
+ try{
+ return Integer.decode(trimmed);
+ }
+ catch(Exception e){
+ LOG.finest("Unparseable Integer value: " + 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/LocalDateConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/LocalDateConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/LocalDateConverter.java
new file mode 100644
index 0000000..edfaa3a
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/LocalDateConverter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.time.LocalDate;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class LocalDateConverter implements Converter<LocalDate> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public LocalDate convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), LocalDate.now().toString());
+ try{
+ return LocalDate.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse LocalDate: " + 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/LocalDateTimeConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/LocalDateTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/LocalDateTimeConverter.java
new file mode 100644
index 0000000..9450e30
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/LocalDateTimeConverter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.time.LocalDateTime;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class LocalDateTimeConverter implements Converter<LocalDateTime> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public LocalDateTime convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), LocalDateTime.now().toString());
+ try{
+ return LocalDateTime.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse LocalDateTime: " + 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/LocalTimeConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/LocalTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/LocalTimeConverter.java
new file mode 100644
index 0000000..dde2214
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/LocalTimeConverter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.time.LocalTime;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class LocalTimeConverter implements Converter<LocalTime> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public LocalTime convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), LocalTime.now().toString());
+ try{
+ return LocalTime.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse LocalTime: " + 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/LongConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/LongConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/LongConverter.java
new file mode 100644
index 0000000..8861c09
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/LongConverter.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.Logger;
+
+/**
+ * Converter, converting from String to Long, 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 LongConverter implements Converter<Long> {
+
+ private static final Logger LOGGER = Logger.getLogger(LongConverter.class.getName());
+
+ @Override
+ public Long convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), "<long>", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE");
+
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch (trimmed.toUpperCase(Locale.ENGLISH)) {
+ case "MIN_VALUE":
+ case "MIN":
+ return Long.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Long.MAX_VALUE;
+ default:
+ try {
+ return Long.decode(trimmed);
+ }
+ catch(Exception e){
+ LOGGER.finest("Unable to parse Long value: " + 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/NumberConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/NumberConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/NumberConverter.java
new file mode 100644
index 0000000..2f2893d
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/NumberConverter.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Number. Valid inputs are:
+ * <pre>
+ * POSITIVE_INFINITY -> Double.POSITIVE_INFINITY
+ * NEGATIVE_INFINITY -> Double.NEGATIVE_INFINITY
+ * NaN > Double.NaN
+ * 0xFFDCD3D2 -> Long
+ * 1234566789.23642327352735273752 -> new BigDecimal(input)
+ * </pre>
+ */
+@Component(service = Converter.class)
+public class NumberConverter implements Converter<Number> {
+ /** the logger. */
+ private static final Logger LOGGER = Logger.getLogger(NumberConverter.class.getName());
+ /** Converter used for trying to parse as an integral value. */
+ private final LongConverter longConverter = new LongConverter();
+
+ @Override
+ public Number convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), "<double>, <long>", "0x (hex)", "0X... (hex)", "POSITIVE_INFINITY",
+ "NEGATIVE_INFINITY", "NAN");
+
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)) {
+ case "POSITIVE_INFINITY":
+ return Double.POSITIVE_INFINITY;
+ case "NEGATIVE_INFINITY":
+ return Double.NEGATIVE_INFINITY;
+ case "NAN":
+ return Double.NaN;
+ default:
+ Long lVal = longConverter.convert(trimmed);
+ if (lVal != null) {
+ return lVal;
+ }
+ try{
+ return new BigDecimal(trimmed);
+ }
+ catch(Exception e){
+ LOGGER.finest("Unparseable Number: " + 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/OffsetDateTimeConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/OffsetDateTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/OffsetDateTimeConverter.java
new file mode 100644
index 0000000..8b78814
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/OffsetDateTimeConverter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.time.OffsetDateTime;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class OffsetDateTimeConverter implements Converter<OffsetDateTime> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public OffsetDateTime convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), OffsetDateTime.now().toString());
+ try{
+ return OffsetDateTime.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse OffsetDateTime: " + 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/OffsetTimeConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/OffsetTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/OffsetTimeConverter.java
new file mode 100644
index 0000000..8186ac0
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/OffsetTimeConverter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.time.OffsetTime;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class OffsetTimeConverter implements Converter<OffsetTime> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public OffsetTime convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), OffsetTime.now().toString());
+ try{
+ return OffsetTime.parse(value);
+ }catch(Exception e){
+ LOG.log(Level.FINEST, e, () -> "Cannot parse OffsetTime: " + 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/OptionalConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/OptionalConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/OptionalConverter.java
new file mode 100644
index 0000000..ef307cc
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/OptionalConverter.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.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Optional;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class OptionalConverter implements Converter<Optional> {
+
+ @Override
+ public Optional convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ if(value==null){
+ return Optional.empty();
+ }
+ try{
+ if(context==null){
+ throw new IllegalStateException("Failed to evaluate target type, context == null.");
+ }
+ Type targetType = context.getTargetType();
+ if(Optional.class.equals(targetType)){
+ ParameterizedType pt = (ParameterizedType) targetType;
+ if(String.class.equals(pt.getActualTypeArguments()[0])){
+ return Optional.of(value);
+ }
+ else{
+ targetType = pt.getActualTypeArguments()[0];
+ }
+ }
+ if(context.getConfiguration()==null){
+ throw new IllegalStateException("Parametrized converters require a configuration for accessing the converters of their" +
+ "child elements.");
+ }
+ ConvertQuery converter = new ConvertQuery(value, targetType);
+ return Optional.ofNullable(converter.apply(context.getConfiguration()));
+ }catch (IllegalStateException ise){
+ throw ise;
+ }catch(Exception e){
+ throw new IllegalArgumentException("Error evaluating config value.", e);
+ }
+ }
+
+ @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/PathConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/PathConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/PathConverter.java
new file mode 100644
index 0000000..6bc9fc3
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/PathConverter.java
@@ -0,0 +1,64 @@
+/*
+ * 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.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to URI, using new URL(value).
+ */
+@Component(service = Converter.class)
+public class PathConverter implements Converter<Path> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public Path convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ if(value==null || value.isEmpty()){
+ return null;
+ }
+ context.addSupportedFormats(getClass(),"<File>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return FileSystems.getDefault().getPath(value);
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unparseable Path: " + trimmed, 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/ShortConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/ShortConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/ShortConverter.java
new file mode 100644
index 0000000..19c5f77
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/ShortConverter.java
@@ -0,0 +1,85 @@
+/*
+ * 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 Short, 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 ShortConverter implements Converter<Short> {
+
+ /** the logger. */
+ private static final Logger LOG = Logger.getLogger(ShortConverter.class.getName());
+
+ @Override
+ public Short convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ context.addSupportedFormats(getClass(), "short", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "MIN_VALUE":
+ case "MIN":
+ return Short.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Short.MAX_VALUE;
+ default:
+ try{
+ return Short.decode(trimmed);
+ }
+ catch(Exception e){
+ LOG.finest("Unparseable Short: " + 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/SupplierConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/SupplierConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/SupplierConverter.java
new file mode 100644
index 0000000..e39f93a
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/SupplierConverter.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.converters;
+
+import org.apache.tamaya.base.convert.ConversionContext;
+import org.osgi.service.component.annotations.Component;
+
+import javax.config.spi.Converter;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.function.Supplier;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Boolean.
+ */
+@Component(service = Converter.class)
+public class SupplierConverter implements Converter<Supplier> {
+
+ private static final Logger LOG = Logger.getLogger(SupplierConverter.class.getName());
+
+ @Override
+ public Supplier convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ return () -> {
+ try{
+ Type targetType = context.getTargetType();
+ ParameterizedType pt = (ParameterizedType) targetType;
+ if(String.class.equals(pt.getActualTypeArguments()[0])){
+ return value;
+ }
+ ConvertQuery converter = new ConvertQuery(value, pt.getActualTypeArguments()[0]);
+ Object o = converter.apply(context.getConfiguration());
+ if(o==null){
+ throw new IllegalArgumentException("No such value: " + context.getKey());
+ }
+ return o;
+ }catch(Exception e){
+ throw new IllegalArgumentException("Error evaluating config value.", e);
+ }
+ };
+ }
+
+ @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/URIConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/URIConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/URIConverter.java
new file mode 100644
index 0000000..d63103a
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/URIConverter.java
@@ -0,0 +1,63 @@
+/*
+ * 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.net.URI;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to URI, using new URI(value).
+ */
+@Component(service = Converter.class)
+public class URIConverter implements Converter<URI> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public URI convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ if(value==null || value.isEmpty()){
+ return null;
+ }
+ context.addSupportedFormats(getClass(), "<uri> -> new URI(uri)");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return new URI(trimmed);
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unparseable URI: " + trimmed, 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/URLConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/URLConverter.java b/code/core/src/main/java/org/apache/tamaya/core/converters/URLConverter.java
new file mode 100644
index 0000000..27c69b1
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/URLConverter.java
@@ -0,0 +1,63 @@
+/*
+ * 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.net.URL;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to URI, using new URL(value).
+ */
+@Component(service = Converter.class)
+public class URLConverter implements Converter<URL> {
+
+ private final Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public URL convert(String value) {
+ ConversionContext context = ConversionContext.getContext();
+ if(value==null || value.isEmpty()){
+ return null;
+ }
+ context.addSupportedFormats(getClass(),"<URL>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return new URL(trimmed);
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unparseable URL: " + trimmed, 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/package-info.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/converters/package-info.java b/code/core/src/main/java/org/apache/tamaya/core/converters/package-info.java
new file mode 100644
index 0000000..2eb5858
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/converters/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Contains implementations of the converters provided by default.
+ */
+package org.apache.tamaya.core.converters;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigProviderResolver
----------------------------------------------------------------------
diff --git a/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigProviderResolver b/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigProviderResolver
new file mode 100644
index 0000000..7177d12
--- /dev/null
+++ b/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigProviderResolver
@@ -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.core.TamayaConfigProviderResolver
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigSource
----------------------------------------------------------------------
diff --git a/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigSource b/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigSource
new file mode 100644
index 0000000..ffa770a
--- /dev/null
+++ b/code/core/src/main/resources/META-INF/services/javax.config.spi.ConfigSource
@@ -0,0 +1,22 @@
+#
+# 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.base.configsource.CLIConfigSource
+org.apache.tamaya.base.configsource.EnvironmentConfigSource
+org.apache.tamaya.base.configsource.JavaConfigurationConfigSource
+org.apache.tamaya.base.configsource.SystemConfigSource
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/resources/META-INF/services/javax.config.spi.Converter
----------------------------------------------------------------------
diff --git a/code/core/src/main/resources/META-INF/services/javax.config.spi.Converter b/code/core/src/main/resources/META-INF/services/javax.config.spi.Converter
new file mode 100644
index 0000000..f7b9134
--- /dev/null
+++ b/code/core/src/main/resources/META-INF/services/javax.config.spi.Converter
@@ -0,0 +1,44 @@
+#
+# 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.core.converters.BooleanConverter
+org.apache.tamaya.core.converters.ByteConverter
+org.apache.tamaya.core.converters.CharConverter
+org.apache.tamaya.core.converters.ClassConverter
+org.apache.tamaya.core.converters.DoubleConverter
+org.apache.tamaya.core.converters.FloatConverter
+org.apache.tamaya.core.converters.IntegerConverter
+org.apache.tamaya.core.converters.LongConverter
+org.apache.tamaya.core.converters.ShortConverter
+org.apache.tamaya.core.converters.BigDecimalConverter
+org.apache.tamaya.core.converters.BigIntegerConverter
+org.apache.tamaya.core.converters.CurrencyConverter
+org.apache.tamaya.core.converters.NumberConverter
+org.apache.tamaya.core.converters.URIConverter
+org.apache.tamaya.core.converters.URLConverter
+org.apache.tamaya.core.converters.FileConverter
+org.apache.tamaya.core.converters.PathConverter
+org.apache.tamaya.core.converters.DurationConverter
+org.apache.tamaya.core.converters.LocalDateConverter
+org.apache.tamaya.core.converters.LocalDateTimeConverter
+org.apache.tamaya.core.converters.LocalTimeConverter
+org.apache.tamaya.core.converters.OffsetDateTimeConverter
+org.apache.tamaya.core.converters.OffsetTimeConverter
+org.apache.tamaya.core.converters.InstantConverter
+org.apache.tamaya.core.converters.OptionalConverter
+org.apache.tamaya.core.converters.SupplierConverter
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.ConfigValueEvaluator
----------------------------------------------------------------------
diff --git a/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.ConfigValueEvaluator b/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.ConfigValueEvaluator
new file mode 100644
index 0000000..26d41ab
--- /dev/null
+++ b/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.ConfigValueEvaluator
@@ -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.base.DefaultConfigValueEvaluator
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/main/resources/tamaya-banner.txt
----------------------------------------------------------------------
diff --git a/code/core/src/main/resources/tamaya-banner.txt b/code/core/src/main/resources/tamaya-banner.txt
new file mode 100644
index 0000000..b4ceca4
--- /dev/null
+++ b/code/core/src/main/resources/tamaya-banner.txt
@@ -0,0 +1,11 @@
+
+ █████╗ ██████╗ █████╗ ██████╗██╗ ██╗███████╗ ████████╗ █████╗ ███╗ ███╗ █████╗ ██╗ ██╗ █████╗
+██╔══██╗██╔══██╗██╔══██╗██╔════╝██║ ██║██╔════╝ ╚══██╔══╝██╔══██╗████╗ ████║██╔══██╗╚██╗ ██╔╝██╔══██╗
+███████║██████╔╝███████║██║ ███████║█████╗ ██║ ███████║██╔████╔██║███████║ ╚████╔╝ ███████║
+██╔══██║██╔═══╝ ██╔══██║██║ ██╔══██║██╔══╝ ██║ ██╔══██║██║╚██╔╝██║██╔══██║ ╚██╔╝ ██╔══██║
+██║ ██║██║ ██║ ██║╚██████╗██║ ██║███████╗ ██║ ██║ ██║██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║
+╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
+
+Apache Tamaya Configuration API: http://tamaya.incubator.apache.org
+
+
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/BannerManagerTest.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/BannerManagerTest.java b/code/core/src/test/java/org/apache/tamaya/core/BannerManagerTest.java
new file mode 100644
index 0000000..bb750b1
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/BannerManagerTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.PrintStream;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+
+/*
+ * Note:
+ * The tests of this class will fail PIT, our coverage tool.
+ * Therefore we excluded this class in the parent POM
+ * from the test execution.
+ * Oliver B. Fischer, 2017-09-16
+ */
+public class BannerManagerTest {
+
+ @Test
+ public void valueConsoleSendsBannerToSystemOut() {
+
+ SecurityManager sm = new SecurityManager();
+ AccessControlContext con = AccessController.getContext();
+
+ Permission p = new RuntimePermission("setIO");
+
+ /*
+ * Here we check the precondition for this unit test
+ * and the correct setup of the test environment
+ * The JVM must have been started with
+ * -Djava.security.policy=<path_to_core_module</src/test/resources/java-security.policy
+ */
+ sm.checkPermission(p, con);
+
+ PrintStream standard = System.out;
+ PrintStream printStream = Mockito.mock(PrintStream.class);
+
+ System.setOut(printStream);
+ standard.println("Changed stream for STDOUT successfully");
+
+ try {
+ BannerManager bm = new BannerManager("console");
+ bm.outputBanner();
+
+ } finally {
+ System.setOut(standard);
+ }
+ Mockito.verify(printStream, Mockito.atLeastOnce()).println(Mockito.anyString());
+ }
+
+ @Test
+ public void invalidValueAvoidsLoggingToConsonle() {
+
+ PrintStream standard = System.out;
+ PrintStream printStream = Mockito.mock(PrintStream.class);
+
+ System.setOut(printStream);
+
+ try {
+ BannerManager bm = new BannerManager("snafu");
+ bm.outputBanner();
+
+ } finally {
+ System.setOut(standard);
+ }
+
+ Mockito.verify(printStream, Mockito.never()).println(Mockito.anyString());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/core/src/test/java/org/apache/tamaya/core/ConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/code/core/src/test/java/org/apache/tamaya/core/ConfigBuilderTest.java b/code/core/src/test/java/org/apache/tamaya/core/ConfigBuilderTest.java
new file mode 100644
index 0000000..8767621
--- /dev/null
+++ b/code/core/src/test/java/org/apache/tamaya/core/ConfigBuilderTest.java
@@ -0,0 +1,94 @@
+///*
+// * 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.TypeLiteral;
+//import org.apache.tamaya.spi.ConfigContext;
+//import org.apache.tamaya.spisupport.DefaultConfigBuilder;
+//import org.junit.Test;
+//
+//import javax.config.Config;
+//import javax.config.spi.ConfigBuilder;
+//import javax.config.spi.ConfigProviderResolver;
+//import javax.config.spi.ConfigSource;
+//import javax.config.spi.Converter;
+//
+//import static org.junit.Assert.*;
+//
+///**
+// * Tests for {@link ConfigBuilder} by atsticks on 06.09.16.
+// */
+//public class ConfigBuilderTest {
+//
+// private TestConfigSource testConfigSource = new TestConfigSource(){};
+//
+//
+// @Test
+// public void addConfigSources_Array() throws Exception {
+// ConfigSource testPS2 = new TestConfigSource("addConfigSources_Array", 1);
+// ConfigBuilder b = new DefaultConfigBuilder()
+// .withSources(testConfigSource, testPS2);
+// Config cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// // Ensure no sorting happens during add, so switch ordinals!
+// testPS2 = new TestConfigSource("addConfigSources_Array", 1);
+// b = ConfigProviderResolver.instance().getBuilder()
+// .withSources(testPS2, testConfigSource);
+// cfg = b.build();
+// assertEquals(2, ConfigContext.of(cfg).getSources().size());
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testConfigSource));
+// assertTrue(ConfigContext.of(cfg).getSources().contains(testPS2));
+// assertEquals(ConfigContext.of(cfg).getSources().get(1).getName(), "TestConfigSource");
+// assertEquals(ConfigContext.of(cfg).getSources().get(0).getName(), "addConfigSources_Array");
+// }
+//
+// @Test
+// @SuppressWarnings({ "rawtypes", "unchecked" })
+// public void addPropertyConverters_Array() throws Exception {
+// Converter<String> converter = new Converter<String>(){
+// @Override
+// public String convert(String value) {
+// return value;
+// }
+// }; //(value) -> value.toLowerCase();
+// ConfigBuilder b = ConfigProviderResolver.instance().getBuilder()
+// .withConverters(converter);
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertTrue(ctx.getConverters(TypeLiteral.of(String.class)).contains(converter));
+// assertEquals(1, ctx.getConverters().size());
+// b = ConfigProviderResolver.instance().getBuilder()
+// .withConverters(converter);
+// b.withConverters(converter);
+// assertEquals(1, ctx.getConverters().size());
+// }
+//
+// @Test
+// public void build() throws Exception {
+// ConfigBuilder b = ConfigProviderResolver.instance().getBuilder();
+// Config cfg = b.build();
+// ConfigContext ctx = ConfigContext.of(cfg);
+// assertNotNull(ctx);
+// assertTrue(ctx.getSources().isEmpty());
+// assertTrue(ctx.getPropertyFilters().isEmpty());
+// }
+//
+//}
\ No newline at end of file
[6/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/ConversionContext.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/ConversionContext.java b/code/compat/src/main/java/org/apache/tamaya/spi/ConversionContext.java
new file mode 100644
index 0000000..22c4d5b
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/ConversionContext.java
@@ -0,0 +1,266 @@
+/*
+ * 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.Configuration;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A conversion context containing all the required values for implementing conversion. Use the included #Builder
+ * for creating new instances of. This class is thread-safe to use. Adding supported formats is synchronized.
+ * @see PropertyConverter
+ */
+public class ConversionContext {
+
+ private final Configuration configuration;
+ private final String key;
+ private final TypeLiteral<?> targetType;
+ private final AnnotatedElement annotatedElement;
+ private final List<String> supportedFormats = new ArrayList<>();
+ private final ConfigurationContext configurationContext;
+
+ /**
+ * Private constructor used from builder.
+ * @param builder the builder, not {@code null}.
+ */
+ protected ConversionContext(Builder builder){
+ this.key = builder.key;
+ this.annotatedElement = builder.annotatedElement;
+ this.targetType = builder.targetType;
+ this.supportedFormats.addAll(builder.supportedFormats);
+ this.configuration = builder.configuration;
+ this.configurationContext = builder.configurationContext;
+ }
+
+ /**
+ * Get the key accessed. This information is very useful to evaluate additional metadata needed to determine/
+ * control further aspects of the conversion.
+ * @return the key. This may be null in case where a default value has to be converted and no unique underlying
+ * key/value configuration is present.
+ */
+ public String getKey(){
+ return key;
+ }
+
+ /**
+ * Get the target type required.
+ * @return the target type required.
+ */
+ public TypeLiteral<?> getTargetType(){
+ return targetType;
+ }
+
+ /**
+ * Get the annotated element, if conversion is performed using injection mechanisms.
+ * @return the annotated element, or {@code null}.
+ */
+ public AnnotatedElement getAnnotatedElement(){
+ return annotatedElement;
+ }
+
+ /**
+ * Get the configuration, which is targeted.
+ * @return the configuration instance, or {@code null}.
+ */
+ public Configuration getConfiguration(){
+ return configuration;
+ }
+
+ /**
+ * Allows to add information on the supported/tried formats, which can be shown to the user, especially when
+ * conversion failed. Adding of formats is synchronized, all formats are added in order to the overall list.
+ * This means formats should be passed in order of precedence.
+ * @param converterType the converters, which implements the formats provided.
+ * @param formatDescriptors the format descriptions in a human readable form, e.g. as regular expressions.
+ */
+ public void addSupportedFormats(@SuppressWarnings("rawtypes") Class<? extends PropertyConverter> converterType, String... formatDescriptors){
+ synchronized (supportedFormats){
+ for(String format: formatDescriptors) {
+ supportedFormats.add(format + " (" + converterType.getSimpleName() + ")");
+ }
+ }
+ }
+
+ /**
+ * Get the supported/tried formats in precedence order. The contents of this method depends on the
+ * {@link PropertyConverter} instances involved in a conversion.
+ * @return the supported/tried formats, never {@code null}.
+ */
+ public List<String> getSupportedFormats(){
+ synchronized (supportedFormats){
+ return new ArrayList<>(supportedFormats);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ConversionContext{" +
+ "configuration=" + configuration +
+ ", key='" + key + '\'' +
+ ", targetType=" + targetType +
+ ", annotatedElement=" + annotatedElement +
+ ", supportedFormats=" + supportedFormats +
+ '}';
+ }
+
+ public ConfigurationContext getConfigurationContext() {
+ return configurationContext;
+ }
+
+ /**
+ * Builder to create new instances of {@link ConversionContext}.
+ */
+ public static final class Builder{
+ /** The backing configuration. */
+ private Configuration configuration;
+ /** The configuration context. */
+ private ConfigurationContext configurationContext;
+ /** The accessed key, or null. */
+ private String key;
+ /** The target type. */
+ private TypeLiteral<?> targetType;
+ /** The injection target (only set with injection used). */
+ private AnnotatedElement annotatedElement;
+ /** The ordered list of formats tried. */
+ private final Set<String> supportedFormats = new HashSet<>();
+
+ /**
+ * Creates a new Builder instance.
+ * @param targetType the target type
+ */
+ public Builder(TypeLiteral<?> targetType) {
+ this(null, null, null, targetType);
+ }
+
+ /**
+ * Creates a new Builder instance.
+ * @param key the requested key, may be null.
+ * @param targetType the target type
+ */
+ public Builder(String key, TypeLiteral<?> targetType) {
+ this(null, null, key, targetType);
+ }
+
+ /**
+ * Creates a new Builder instance.
+ * @param configuration the configuration, not {@code null}.
+ * @param configurationContext configuration context, not {@code null}.
+ * @param key the requested key, may be {@code null}.
+ * @param targetType the target type
+ */
+ public Builder(Configuration configuration, ConfigurationContext configurationContext, String key, TypeLiteral<?> targetType){
+ this.key = key;
+ this.configuration = configuration;
+ this.configurationContext = configurationContext;
+ this.targetType = Objects.requireNonNull(targetType);
+ }
+
+ /**
+ * Sets the key.
+ * @param key the key, not {@code null}.
+ * @return the builder instance, for chaining
+ */
+ public Builder setKey(String key){
+ this.key = Objects.requireNonNull(key);
+ return this;
+ }
+
+ /**
+ * Sets the configuration.
+ * @param configuration the configuration, not {@code null}
+ * @return the builder instance, for chaining
+ */
+ public Builder setConfiguration(Configuration configuration){
+ this.configuration = Objects.requireNonNull(configuration);
+ return this;
+ }
+
+ /**
+ * Sets the configuration.
+ * @param configurationContext the configuration, not {@code null}
+ * @return the builder instance, for chaining
+ */
+ public Builder setConfigurationContext(ConfigurationContext configurationContext){
+ this.configurationContext = Objects.requireNonNull(configurationContext);
+ return this;
+ }
+
+ /**
+ * Sets the annotated element, when configuration is injected.
+ * @param annotatedElement the annotated element, not {@code null}
+ * @return the builder instance, for chaining
+ */
+ public Builder setAnnotatedElement(AnnotatedElement annotatedElement){
+ this.annotatedElement = Objects.requireNonNull(annotatedElement);
+ return this;
+ }
+
+ /**
+ * Sets the target type explicitly. This is required in some rare cases, e.g. injection of {@code Provider}
+ * instances, where the provider's result type must be produced.
+ * @param targetType the
+ * @return the builder for chaining.
+ */
+ public Builder setTargetType(@SuppressWarnings("rawtypes") TypeLiteral targetType) {
+ this.targetType = Objects.requireNonNull(targetType);
+ return this;
+ }
+
+ /**
+ * Add the formats provided by a {@link PropertyConverter}. This method should be called by each converters
+ * performing/trying conversion, so the user can be given feedback on the supported formats on failure.
+ * @param converterType the converters type, not {@code null}.
+ * @param formatDescriptors the formats supported in a human readable form, e.g. as regular expressions.
+ * @return the builder instance, for chaining
+ */
+ public Builder addSupportedFormats(@SuppressWarnings("rawtypes") Class<? extends PropertyConverter> converterType, String... formatDescriptors){
+ for(String format: formatDescriptors) {
+ supportedFormats.add(format + " (" + converterType.getSimpleName() + ")");
+ }
+ return this;
+ }
+
+ /**
+ * Builds a new context instance.
+ * @return a new context, never null.
+ */
+ public ConversionContext build(){
+ return new ConversionContext(this);
+ }
+
+ @Override
+ public String toString() {
+ return "Builder{" +
+ "configuration=" + configuration +
+ "context=" + configurationContext +
+ ", key='" + key + '\'' +
+ ", targetType=" + targetType +
+ ", annotatedElement=" + annotatedElement +
+ ", supportedFormats=" + supportedFormats +
+ '}';
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/FilterContext.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/FilterContext.java b/code/compat/src/main/java/org/apache/tamaya/spi/FilterContext.java
new file mode 100644
index 0000000..2851697
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/FilterContext.java
@@ -0,0 +1,140 @@
+/*
+ * 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.Configuration;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A filter context containing all the required values for implementing filtering.
+ *
+ * @see PropertyFilter
+ */
+public class FilterContext {
+ /** The key. */
+ private final PropertyValue value;
+ /** The current context. */
+ private final ConfigurationContext context;
+ @Experimental
+ private Map<String, PropertyValue> configEntries = new HashMap<>();
+ @Experimental
+ private boolean singlePropertyScoped;
+
+
+ /**
+ * Creates a new FilterContext, for filtering of a multi value access
+ * using {@link Configuration#getProperties()}.
+ *
+ * @param value the value under evaluation, not {@code null}.
+ * @param configEntries the raw configuration data available in the
+ * current evaluation context, not {@code null}.
+ * @param context the current context, not {@code null}.
+ */
+ public FilterContext(PropertyValue value, Map<String,PropertyValue> configEntries, ConfigurationContext context) {
+ Objects.requireNonNull(value, "Value must not be null.");
+ Objects.requireNonNull(configEntries, "Initial configuration entries must be not null.");
+ Objects.requireNonNull(context, "Context must be not null.");
+
+ this.singlePropertyScoped = false;
+ this.value = Objects.requireNonNull(value);
+ this.context = Objects.requireNonNull(context);
+ this.configEntries.putAll(configEntries);
+ this.configEntries = Collections.unmodifiableMap(this.configEntries);
+ }
+
+ /**
+ * Creates a new FilterContext, for filtering of a single value access
+ * using {@link Configuration#getProperties()}.
+ * @param value the value under evaluation, not {@code null}.
+ * @param context the current context, not {@code null}.
+ */
+ public FilterContext(PropertyValue value, ConfigurationContext context) {
+ Objects.requireNonNull(value, "Value must not be null.");
+ Objects.requireNonNull(context, "Context must be not null.");
+
+ this.singlePropertyScoped = true;
+ this.context = Objects.requireNonNull(context);
+ this.value = Objects.requireNonNull(value);
+ this.configEntries = Collections.unmodifiableMap(this.configEntries);
+ }
+
+ /**
+ * Get the current context.
+ * @return the current context, not {@code null}.
+ */
+ public ConfigurationContext getContext(){
+ return context;
+ }
+
+ /**
+ * Get the property value under evaluation. This information is very useful to evaluate additional metadata needed to determine/
+ * control further aspects of the conversion.
+ *
+ * @return the key. This may be null in case where a default value has to be converted and no unique underlying
+ * key/value configuration is present.
+ */
+ public PropertyValue getProperty() {
+ return value;
+ }
+
+ /**
+ * Method that determines if filtering is done for a single property accessed, or as part of call to
+ * {@code getProperties()}.
+ * @return true, if its scoped to a single property accessed.
+ */
+ @Experimental
+ public boolean isSinglePropertyScoped(){
+ return singlePropertyScoped;
+ }
+
+ /**
+ * This map contains the following keys:
+ * <ul>
+ * <li>the original value <b>before</b> any filters were applied on it.</li>
+ * <li>all values starting with an {@code _<key>.}, for example {@code a.value}
+ * may have a map set with {@code a.value} (oringinal value), {@code _a.value.origin,
+ * _a.value.type, etc}. The exact contents is determine by the {@link PropertySource}s
+ * active.</li>
+ * </ul>
+ * Also important to know is that this map given contains all the evaluated raw entries, regardless
+ * of the filters that are later applied. This ensures that met-information required by one filter is
+ * not hidden by another filter, because of an invalid filter ordering. In other words filters may remove
+ * key/value pairs, e.g. fir security reasons, by returning {@code null}, but the values in the raw map
+ * passed as input to the filter process will not be affected by any such removal (but the final properties
+ * returned are affected, of course).
+ *
+ * Finally, when a single property is accessed, e.g. by calling {@code Configuration.get(String)}.
+ *
+ * @return the configuration instance, or null.
+ */
+ @Experimental
+ public Map<String, PropertyValue> getConfigEntries() {
+ return configEntries;
+ }
+
+ @Override
+ public String toString() {
+ return "FilterContext{value='" + value + "', configEntries=" + configEntries.keySet() + '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertyConverter.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
new file mode 100644
index 0000000..ab96b6b
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+/**
+ * Interface for an property that converts a configured String into something else.
+ * This is used for implementing type conversion from a property (String) to a certain target
+ * type. Hereby the target type can be multi-value (e.g. collections) or complex if needed.
+ *
+ * @param <T> the type of the type literal
+ */
+@FunctionalInterface
+public interface PropertyConverter<T>{
+
+ /**
+ * Convert the given configuration keys from its String representation into the required target type.
+ * The context instance passed also allows to add a list of supported formats, which is very handy in case a
+ * value could not be converted. This list of supported formats can then shown to the user to give some hints
+ * how a value could be configured.
+ *
+ * @param value configuration key that needs to be converted
+ * @param context the {@link ConversionContext}, containing the String value and the requested configuration key.
+ * @return converted keys
+ * @see ConversionContext#addSupportedFormats(Class, String...)
+ */
+ T convert(String value, ConversionContext context);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertyFilter.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
new file mode 100644
index 0000000..3054496
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+
+/**
+ * <p>Interface for filtering the current map of properties during the evaluation of the chain of PropertySources.
+ * Filters can be registered using the {@link org.apache.tamaya.spi.ServiceContext}. The ordinal
+ * hereby is defined by the corresponding {@code @Priority} annotation.</p>
+ * <p>Filters </p>
+ */
+@FunctionalInterface
+public interface PropertyFilter {
+
+ /**
+ * <p>Maps the current {@code valueToBeFiltered} value to a new value. The resulting value will be used as the result
+ * passed to the user.</p>
+ * <p>If a filter is currently not available, it should just pass the input map to the method's
+ * output.</p>
+ * <p>Returning {@code null} will remove the entry.</p>
+ * <h3>Implementation specification</h3>
+ * Implementations of this class must be
+ * <ul>
+ * <li>reentrant</li>
+ * <li>thread-safe</li>
+ * </ul>
+ * @param value the value to be filtered, which also can be {@code null} if removed by another filter.
+ * @param context the filter context, not {@code null}.
+ * @return the filtered value, or {@code null} if the value should be removed alltogether.
+ * @see PropertyValue
+ * @see PropertyValueBuilder
+ */
+ PropertyValue filterProperty(PropertyValue value, FilterContext context);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertySource.java
new file mode 100644
index 0000000..e38e278
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertySource.java
@@ -0,0 +1,174 @@
+/*
+* 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.Configuration;
+
+import java.util.Collections;
+import java.util.Map;
+
+
+/**
+ * <p>This interface models a provider that serves configuration properties. The contained
+ * properties may be read from a Map of single or several sources (composite).
+ * PropertySources are the building blocks of the final configuration. </p>
+ * <h3>Implementation Requirements</h3>
+ * <p>Implementations of this interface must be</p>
+ * <ul>
+ * <li>Thread safe.</li>
+ * </ul>
+ *
+ * <p>A PropertySourceProvider will get picked up via the
+ * {@link java.util.ServiceLoader} mechanism and can be registered via
+ * {@code META-INF/services/org.apache.tamaya.spi.PropertySource}
+ * </p>
+ * <p>
+ * If you like to addSources multiple PropertySources at the same time
+ * you can use the {@link org.apache.tamaya.spi.PropertySourceProvider}
+ * interface.
+ * </p>
+ */
+public interface PropertySource {
+
+ /**
+ * property name to override default tamaya ordinals
+ */
+ String TAMAYA_ORDINAL = "tamaya.ordinal";
+
+ /**
+ * A resusable instance of an empty PropertySource.
+ */
+ PropertySource EMPTY = new PropertySource() {
+
+ @Override
+ public int getOrdinal() {
+ return Integer.MIN_VALUE;
+ }
+
+ @Override
+ public String getName() {
+ return "<empty>";
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ return null;
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public boolean isScannable() {
+ return false;
+ }
+
+ @Override
+ public String toString(){
+ return "PropertySource.EMPTY";
+ }
+ };
+
+
+ /**
+ * The ordinal value is the default ordering parameter which definines the default order of
+ * auto-discovered property sources. Ordering of property sources is important since values
+ * from property sources with higher ordinal values override values from less significant
+ * property sources.
+ *
+ * By default Tamaya includes the following property sources:
+ * <ol>
+ * <li>Properties file values (/META-INF/javaconfiguration.properties) (ordinal 100)</li>
+ * <li>JNDI values (ordinal 200, only when adding the {@code tamaya-jndi} extension module)</li>
+ * <li>Environment properties (ordinal 300)</li>
+ * <li>System properties (ordinal 1000)</li>
+ * </ol>
+ *
+ * <p><b>Important Hints for custom implementations</b>:</p>
+ * <p>
+ * If a custom implementation should be invoked <b>before</b> the default implementations, use a value > 1000
+ * </p>
+ * <p>
+ * If a custom implementation should be invoked <b>after</b> the default implementations, use a value < 100
+ * </p>
+ *
+ * <p>Reordering of the default order of the config-sources:</p>
+ * <p>Example: If the properties file/s should be used <b>before</b> the other implementations,
+ * you have to configure an ordinal > 1000. That means, you have to add e.g. tamaya.ordinal=401 to
+ * /META-INF/javaconfiguration.properties . Hint: In case of property files every file is handled as independent
+ * config-source, but all of them have ordinal 400 by default (and can be reordered in a fine-grained manner.</p>
+ *
+ * In cases where it is not possible to change a config sources ordinal value, you may have several options:
+ * <ul>
+ * <li>you can addSources an alternate implementation of {@link PropertyValueCombinationPolicy}.</li>
+ * <li>you can use a {@link ConfigurationContextBuilder} to redefine the source order and finally use
+ * {@link org.apache.tamaya.ConfigurationProvider#setConfiguration(Configuration)} to
+ * change the current default {@link Configuration}.</li>
+ * <li>finally, the imeplementor of this API may define alternate mechanism to reconfigure an ordinal
+ * in a vendor specific way.</li>
+ * </ul>
+ * @return the 'importance' aka ordinal of the configured values. The higher, the more important.
+ */
+ int getOrdinal();
+
+
+ /**
+ * Get the name of the property source. The name should be unique for the type of source, whereas the id is used
+ * to ensure unique identity, either locally or remotely.
+ * @return the configuration's name, never {@code null}.
+ */
+ String getName();
+
+ /**
+ * Access a property.
+ *
+ * @param key the property's key, not {@code null}.
+ * @return the property value map, where {@code map.get(key) == value}, including also any metadata. In case a
+ * value is null, simply return {@code null}.
+ */
+ PropertyValue get(String key);
+
+ /**
+ * Access the current properties as Set. The resulting Map may not return all items accessible, e.g.
+ * when the underlying storage does not support iteration of its entries.
+ {@code null}
+ * @return the corresponding map, never null.
+ */
+ Map<String, PropertyValue> getProperties();
+
+ /**
+ * Determines if this config source can be scanned for its list of properties.
+ *
+ * <p>
+ * PropertySources which are not scannable might not be able to find all the
+ * configured values to provide via {@link #getProperties()}. This might happen
+ * if the underlying storage doesn't support listing.
+ * </p>
+ *
+ * @return {@code true} if this PropertySource can be scanned for its list of properties,
+ * {@code false} if it cannot/should not be scanned.
+ */
+ default boolean isScannable(){
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java
new file mode 100644
index 0000000..aa09ad8
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java
@@ -0,0 +1,61 @@
+/*
+ * 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.util.Collection;
+import java.util.Collections;
+
+/**
+ * <p>Implement this interfaces to provide a PropertySource provider which
+ * is able to addSources multiple PropertySources. This is e.g. needed if
+ * there are multiple property files of a given config file name.</p>
+ *
+ * <p>If a PropertySource like JNDI only exists once, then there is no need
+ * to implement it via the PropertySourceProvider but should directly
+ * expose a {@link PropertySource}.</p>
+ *
+ * <p>A PropertySourceProvider will get picked up via the
+ * {@link java.util.ServiceLoader} mechanism and must get registered via
+ * META-INF/services/org.apache.tamaya.spi.PropertySourceProvider</p>
+ */
+@FunctionalInterface
+public interface PropertySourceProvider {
+
+ /**
+ * A resusable instance of an empty PropertySource.
+ */
+ PropertySourceProvider EMPTY = new PropertySourceProvider() {
+
+ @Override
+ public Collection<PropertySource> getPropertySources() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String toString(){
+ return "PropertySourceProvider(empty)";
+ }
+ };
+
+ /**
+ * @return For each e.g. property file, we return a single PropertySource
+ * or an empty list if no PropertySource exists.
+ */
+ Collection<PropertySource> getPropertySources();
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValue.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValue.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValue.java
new file mode 100644
index 0000000..c538de7
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValue.java
@@ -0,0 +1,232 @@
+/*
+ * 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.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Class modelling the result of a request for a property value. A property value is basically identified by its key.
+ * There might be reasons, where one want to further analyze, which PropertySources provided a value and which not, so
+ * it is possible to create a PropertyValue with a null value. Nevertheless in all cases the provider source (typically
+ * the name of the PropertySource) must be set.
+ */
+public final class PropertyValue implements Serializable{
+ private static final long serialVersionUID = 1L;
+ /** The requested key. */
+ private String key;
+ /** The value. */
+ private String value;
+ /** The source of the value. */
+ private String source;
+ /** Additional metadata provided by the provider. */
+ private Map<String,String> metaEntries = new HashMap<>();
+
+ PropertyValue(PropertyValueBuilder builder){
+ this.key = Objects.requireNonNull(builder.key);
+ this.value = builder.value;
+ this.source = Objects.requireNonNull(builder.source);
+ if(builder.metaEntries !=null) {
+ this.metaEntries.putAll(builder.metaEntries);
+ }
+ }
+
+ /**
+ * Creates a new instance
+ * @param key the key, not {@code null}.
+ * @param value the value, not {@code null}.
+ * @param source the source, typically the name of the {@link PropertySource} providing
+ * the value, not {@code null}.
+ */
+ private PropertyValue(String key, String value, String source){
+ this.key = Objects.requireNonNull(key, "Key is required.");
+ this.value = Objects.requireNonNull(value, "Value is required.");
+ this.source = Objects.requireNonNull(source, "Source is required.");
+ }
+
+ /**
+ * The requested key.
+ * @return the, key never {@code null}.
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * The source.
+ * @return the source, which provided the value, not {@code null}.
+ * @see PropertySource#getName() .
+ */
+ public String getSource() {
+ return this.source;
+ }
+
+
+ /**
+ * The value.
+ * @return the value, in case a value is null it is valid to return {#code null} as result for
+ * {@link PropertySource#get(String)}.
+ */
+ public String getValue() {
+ return this.value;
+ }
+
+ /**
+ * Creates a full configuration map for this key, value pair and all its meta context data. This map
+ * is also used for subsequent processing, like value filtering.
+ * @return the property value entry map.
+ */
+ public Map<String, String> getMetaEntries() {
+ return Collections.unmodifiableMap(metaEntries);
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @param key the key, not {@code null}.
+ * @param source the source, typically the name of the {@link PropertySource}
+ * providing the value, not {@code null}.
+ * @return a new builder instance.
+ */
+ public static PropertyValueBuilder builder(String key, String source){
+ Objects.requireNonNull(key, "Key must be given.");
+ Objects.requireNonNull(source, "Source must be given");
+
+ return new PropertyValueBuilder(key, source);
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @param key the key, not {@code null}.
+ * @param value the property value, not {@code null}.
+ * @param source the source, typically the name of the {@link PropertySource}
+ * providing the value, not {@code null}.
+ * @return a new builder instance.
+ */
+ public static PropertyValueBuilder builder(String key, String value, String source) {
+ Objects.requireNonNull(key, "Key must be given.");
+ Objects.requireNonNull(value, "Value must be given");
+ Objects.requireNonNull(source, "Source must be given.");
+
+ return new PropertyValueBuilder(key, value, source);
+ }
+
+
+ /**
+ * Creates a new PropertyValue without any metadata..
+ * @param key the key, not {@code null}.
+ * @param value the value.
+ * @param source the source, typically the name of the {@link PropertySource}
+ * providing the value, not {@code null}.
+ * @return a new property value instance, or {@code null},
+ * if the value passed is {@code null}..
+ */
+ public static PropertyValue of(String key, String value, String source) {
+ if (value==null) {
+ return null;
+ }
+ return new PropertyValue(key, value, source);
+ }
+
+ /**
+ * Access the given key from this value. Valid keys are the key or any meta-context key.
+ * @param key the key, not {@code null}.
+ * @return the value found, or {@code null}.
+ */
+ public String getMetaEntry(String key) {
+ return this.metaEntries.get(Objects.requireNonNull(key));
+ }
+
+ /**
+ * Creates a new builder instance based on this item.
+ * @return a new builder, never null.
+ */
+ public PropertyValueBuilder toBuilder() {
+ return new PropertyValueBuilder(this.getKey(), this.getSource())
+ .setValue(this.getValue())
+ .setMetaEntries(this.metaEntries);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PropertyValue)) return false;
+ PropertyValue that = (PropertyValue) o;
+ return Objects.equals(getKey(), that.getKey()) &&
+ Objects.equals(getValue(), that.getValue()) &&
+ Objects.equals(getSource(), that.getSource()) &&
+ Objects.equals(getMetaEntries(), that.getMetaEntries());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getKey(), getValue(), getSource(),
+ getMetaEntries());
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyValue{" +
+ "key='" + key + '\'' +
+ ", value='" + value + '\'' +
+ ", source='" + source + '\'' +
+ (metaEntries.isEmpty()?"":", metaEntries=" + metaEntries) +
+ '}';
+ }
+
+ /**
+ * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+ * @param config the String based map, not {@code null}.
+ * @param source the source name, not {@code null}.
+ * @return the corresponding value based map.
+ */
+ public static Map<String,PropertyValue> map(Map<String, String> config, String source) {
+ Map<String,PropertyValue> result = new HashMap<>(config.size());
+ for(Map.Entry<String,String> en:config.entrySet()){
+ result.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), source));
+ }
+ return result;
+ }
+
+ /**
+ * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+ *
+ * @param config the String based map, not {@code null}.
+ * @param source the source name, not {@code null}.
+ * @param metaData additional metadata, not {@code null}.
+ * @return the corresponding value based map.
+ */
+ public static Map<String,PropertyValue> map(Map<String, String> config, String source,
+ Map<String,String> metaData) {
+ Objects.requireNonNull(config, "Config must be given.");
+ Objects.requireNonNull(source, "Source must be given.");
+ Objects.requireNonNull(metaData, "Meta data must be given.");
+
+ Map<String,PropertyValue> result = new HashMap<>(config.size());
+
+ for(Map.Entry<String,String> en:config.entrySet()){
+ PropertyValue value = new PropertyValueBuilder(en.getKey(), source).setValue(en.getValue())
+ .addMetaEntries(metaData).build();
+ result.put(en.getKey(), value);
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
new file mode 100644
index 0000000..af01987
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
@@ -0,0 +1,196 @@
+/*
+ * 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.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Builder to create a {@link PropertyValue} instance.
+ */
+public class PropertyValueBuilder {
+ /** The key accessed. */
+ String key;
+ /** The property value. */
+ String value;
+ /** The property vaoue source. */
+ String source;
+ /** additional metadata entries (optional). */
+ Map<String,String> metaEntries = new HashMap<>();
+
+ /**
+ * Create a new builder instance, for a given set of parameters.
+ * Before calling build at least a {@link #value} and its {@link #source}
+ * must be set.
+ */
+ PropertyValueBuilder(String key){
+ this.key = Objects.requireNonNull(key);
+ }
+
+ /**
+ * Create a new builder instance, for a given set of parameters.
+ * @param key to access a property value, not {@code null}.
+ * @param source property source.
+ */
+ PropertyValueBuilder(String key, String source) {
+ this.key = Objects.requireNonNull(key);
+ this.source = Objects.requireNonNull(source);
+ }
+
+ /**
+ * Create a new builder instance, for a given set of parameters.
+ *
+ * @param key to access a property value.
+ * @param value the value, not {@code null}. If a value is {@code null}
+ * {@link PropertySource#get(String)} should return {@code null}.
+ * @param source property source.
+ */
+ PropertyValueBuilder(String key, String value, String source) {
+ this.key = Objects.requireNonNull(key);
+ this.value = value;
+ this.source = Objects.requireNonNull(source);
+ }
+
+ /**
+ * Replaces/sets the context data.
+ * @param metaEntries the context data to be applied, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setMetaEntries(Map<String, String> metaEntries) {
+ this.metaEntries.clear();
+ this.metaEntries.putAll(metaEntries);
+ return this;
+ }
+
+ /**
+ * Add an additional context data information.
+ * @param key the context data key, not {@code null}.
+ * @param value the context value, not {@code null} (will be converted to String).
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder addMetaEntry(String key, Object value) {
+ Objects.requireNonNull(key, "Meta key must be given.");
+ Objects.requireNonNull(value, "Meta value must be given.");
+
+ this.metaEntries.put(key, String.valueOf(value));
+ return this;
+ }
+
+ /**
+ * Adds the context data given.
+ * @param metaEntries the context data to be applied, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder addMetaEntries(Map<String, String> metaEntries) {
+ this.metaEntries.putAll(metaEntries);
+ return this;
+ }
+
+ /**
+ * Removes a meta entry.
+ * @param key the entry's key, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder removeMetaEntry(String key) {
+ Objects.requireNonNull(key, "Key must be given.");
+
+ this.metaEntries.remove(key);
+ return this;
+ }
+
+ /**
+ * Get the value's context data.
+ * @return the context data, not {@code null}.
+ */
+ public Map<String,String> getMetaEntries() {
+ return Collections.unmodifiableMap(this.metaEntries);
+ }
+
+ /**
+ * Changes the entry's key, mapping also corresponding context entries.
+ * @param key the new key, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder mapKey(String key) {
+ // todo obf if (1==1) throw new RuntimeException("No tests written.");
+ Map<String,String> newContext = new HashMap<>();
+ for(Map.Entry<String,String> en:this.metaEntries.entrySet()){
+ if(en.getKey().startsWith("_"+this.key)){
+ newContext.put("_"+key+'.'+ en.getKey().substring(this.key.length()+1), en.getValue());
+ }else{
+ newContext.put(en.getKey(), en.getValue());
+ }
+ }
+ this.metaEntries = newContext;
+ this.key = key;
+ return this;
+ }
+
+ /**
+ * Sets a new key.
+ * @param key the new key, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setKey(String key) {
+ this.key = Objects.requireNonNull(key);
+ return this;
+ }
+
+ /**
+ * Sets a new value.
+ * @param value the new value, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setValue(String value) {
+ this.value = Objects.requireNonNull(value, "Value must be given.");
+
+ return this;
+ }
+
+ /**
+ * Sets a new source.
+ * @param source the new source, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setSource(String source) {
+ // todo obf if (1==1) throw new RuntimeException("No tests written.");
+ this.source = Objects.requireNonNull(source);
+ return this;
+ }
+
+ /**
+ * Creates a new immutable {@link PropertyValue}.
+ * @return a new immutable {@link PropertyValue}, never {@code null}.
+ */
+ public PropertyValue build(){
+ return new PropertyValue(this);
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyValueBuilder{" +
+ "key='" + key + '\'' +
+ "value='" + value + '\'' +
+ ", metaEntries=" + metaEntries +
+ '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
new file mode 100644
index 0000000..14640e6
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+
+/**
+ * Policy that determines how the final value of a configuration entry is evaluated. An instances of this
+ * interface can be registered to get control how multiple PropertySources are combined. This is useful in cases
+ * where the default overriding policy as implemented in {@link #DEFAULT_OVERRIDING_POLICY} is not matching
+ * the need of the current application, e.g. then entries containing multiple values should be combined to new
+ * values instead of overridden.
+ */
+public interface PropertyValueCombinationPolicy {
+
+ /**
+ * Default overriding collector, where each existing entry ({@code current} is overridden by a subsequent non-null
+ * entry evaluated by {@code propertySource.get(key)}.
+ */
+ PropertyValueCombinationPolicy DEFAULT_OVERRIDING_POLICY = new PropertyValueCombinationPolicy(){
+
+ @Override
+ public PropertyValue collect(PropertyValue currentValue, String key, PropertySource propertySource) {
+ PropertyValue value = propertySource.get(key);
+ return value!=null?value:currentValue;
+ }
+ };
+
+ /**
+ * @deprecated Use {@linkplain #DEFAULT_OVERRIDING_POLICY} instead. Will be removed in 1.0.
+ */
+ @Deprecated
+ PropertyValueCombinationPolicy DEFAULT_OVERRIDING_COLLECTOR = DEFAULT_OVERRIDING_POLICY;
+
+
+ /**
+ * Method that is called for each value evaluated by a PropertySource for the given key. This method is called
+ * either when a single key is accessed, e.g. by calling {@code org.apache.tamaya.Configuration.getXXX}, but also
+ * when the full configuration property map is accessed by calling
+ * {@link org.apache.tamaya.Configuration#getProperties()}.
+ *
+ * @param currentValue the current value, including metadata entries. If no such key is present the current value
+ * is null.
+ * The collector should either combine the existing value with value from {@code currentValue}
+ * or replace the value in {@code currentValue} with {@code valueRead}, hereby returning the
+ * result to be used as new {@code currentValue}.
+ * @param key The current key to be evaluated.
+ * @param propertySource The PropertySource that may return an value for the given key. The PropertySource given
+ * may be evaluated for additional meta-data, how the given values are to be combined.
+ * Note that the value returned by a PropertySource can be null. In that case
+ * {@code currentValue} should be returned in almost all cases.
+ * @return the value to be used for future evaluation, including metadata entries.
+ */
+ PropertyValue collect(PropertyValue currentValue, String key, PropertySource propertySource);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/package-info.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/package-info.java b/code/compat/src/main/java/org/apache/tamaya/spi/package-info.java
new file mode 100644
index 0000000..49dbab9
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * This package contains the Apache Tamaya SPI artifacts.
+ */
+@org.osgi.annotation.versioning.Version("0.4")
+package org.apache.tamaya.spi;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/ConfigValueEvaluator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/ConfigValueEvaluator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/ConfigValueEvaluator.java
new file mode 100644
index 0000000..92fd614
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/ConfigValueEvaluator.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spi.ConfigurationContext;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Map;
+
+
+/**
+ * Component SPI which encapsulates the evaluation of a single or full <b>raw</b>value
+ * for a {@link ConfigurationContext}.
+ */
+public interface ConfigValueEvaluator {
+
+ /**
+ * Evaluates single value using a {@link ConfigurationContext}.
+ * @param key the config key, not null.
+ * @param context the context, not null.
+ * @return the value, or null.
+ */
+ PropertyValue evaluteRawValue(String key, ConfigurationContext context);
+
+ /**
+ * Evaluates all property values from a {@link ConfigurationContext}.
+ * @param context the context, not null.
+ * @return the value, or null.
+ */
+ Map<String, PropertyValue> evaluateRawValues(ConfigurationContext context);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigValueEvaluator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigValueEvaluator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigValueEvaluator.java
new file mode 100644
index 0000000..d50ed7d
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigValueEvaluator.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.spisupport;
+
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the
+ * chain of {@link PropertySource} and {@link PropertyFilter}
+ * instance to evaluate the current Configuration.
+ */
+public class DefaultConfigValueEvaluator implements ConfigValueEvaluator{
+
+ @Override
+ public PropertyValue evaluteRawValue(String key, ConfigurationContext context) {
+ PropertyValue unfilteredValue = null;
+ for (PropertySource propertySource : context.getPropertySources()) {
+ unfilteredValue = context.getPropertyValueCombinationPolicy().
+ collect(unfilteredValue, key, propertySource);
+ }
+ if(unfilteredValue==null || unfilteredValue.getValue()==null){
+ return null;
+ }
+ return unfilteredValue;
+ }
+
+ @Override
+ public Map<String, PropertyValue> evaluateRawValues(ConfigurationContext context) {
+ Map<String, PropertyValue> result = new HashMap<>();
+ for (PropertySource propertySource : context.getPropertySources()) {
+ for (Map.Entry<String,PropertyValue> propEntry: propertySource.getProperties().entrySet()) {
+ PropertyValue unfilteredValue = result.get(propEntry.getKey());
+ unfilteredValue = context.getPropertyValueCombinationPolicy().
+ collect(unfilteredValue, propEntry.getKey(), propertySource);
+ if(unfilteredValue!=null){
+ result.put(unfilteredValue.getKey(), unfilteredValue);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultConfigEvaluator{}";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
new file mode 100644
index 0000000..bdbd09c
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spisupport;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.ConfigOperator;
+import org.apache.tamaya.ConfigQuery;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.spi.TypeLiteral;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spi.PropertyValueCombinationPolicy;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the
+ * chain of {@link PropertySource} and {@link org.apache.tamaya.spi.PropertyFilter}
+ * instance to evaluate the current Configuration.
+ */
+public class DefaultConfiguration implements Configuration {
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(DefaultConfiguration.class.getName());
+
+ /**
+ * The current {@link ConfigurationContext} of the current instance.
+ */
+ private final ConfigurationContext configurationContext;
+
+ /**
+ * EvaluationStrategy
+ */
+ private ConfigValueEvaluator configEvaluator = loadConfigValueEvaluator();
+
+ private ConfigValueEvaluator loadConfigValueEvaluator() {
+ ConfigValueEvaluator eval = null;
+ try{
+ eval = ServiceContextManager.getServiceContext()
+ .getService(ConfigValueEvaluator.class);
+ }catch(Exception e){
+ LOG.log(Level.WARNING, "Failed to load ConfigValueEvaluator from ServiceContext, using default.", e);
+ }
+ if(eval==null){
+ eval = new DefaultConfigValueEvaluator();
+ }
+ return eval;
+ }
+
+
+ /**
+ * Constructor.
+ * @param configurationContext The configuration Context to be used.
+ */
+ public DefaultConfiguration(ConfigurationContext configurationContext){
+ this.configurationContext = Objects.requireNonNull(configurationContext);
+ }
+
+ /**
+ * Get a given value, filtered with the context's filters as needed.
+ * @param key the property's key, not null.
+ * @return the filtered value, or null.
+ */
+ @Override
+ public String get(String key) {
+ Objects.requireNonNull(key, "Key must not be null.");
+
+ PropertyValue value = configEvaluator.evaluteRawValue(key, configurationContext);
+ if(value==null || value.getValue()==null){
+ return null;
+ }
+ value = PropertyFiltering.applyFilter(value, configurationContext);
+ if(value!=null){
+ return value.getValue();
+ }
+ return null;
+ }
+
+ /**
+ * Evaluates the raw value using the context's PropertyValueCombinationPolicy.
+ * @param key the key, not null.
+ * @return the value, before filtering is applied.
+ */
+ protected PropertyValue evaluteRawValue(String key) {
+ List<PropertySource> propertySources = configurationContext.getPropertySources();
+ PropertyValue filteredValue = null;
+ PropertyValueCombinationPolicy combinationPolicy = this.configurationContext
+ .getPropertyValueCombinationPolicy();
+ for (PropertySource propertySource : propertySources) {
+ filteredValue = combinationPolicy.collect(filteredValue, key, propertySource);
+ }
+ return filteredValue;
+ }
+
+
+ @Override
+ public String getOrDefault(String key, String defaultValue) {
+ Objects.requireNonNull(key, "Key must not be null.");
+
+ String val = get(key);
+ if(val==null){
+ return defaultValue;
+ }
+ return val;
+ }
+
+ @Override
+ public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
+ Objects.requireNonNull(key, "Key must not be null.");
+ Objects.requireNonNull(type, "Target type must not be null");
+
+ T val = get(key, type);
+ if(val==null){
+ return defaultValue;
+ }
+ return val;
+ }
+
+ /**
+ * Get the current properties, composed by the loaded {@link PropertySource} and filtered
+ * by registered {@link org.apache.tamaya.spi.PropertyFilter}.
+ *
+ * @return the final properties.
+ */
+ @Override
+ public Map<String, String> getProperties() {
+ Map<String, PropertyValue> filtered = PropertyFiltering.applyFilters(
+ configEvaluator.evaluateRawValues(configurationContext),
+ configurationContext);
+ Map<String,String> result = new HashMap<>();
+ for(PropertyValue val:filtered.values()){
+ if(val.getValue()!=null) {
+ result.put(val.getKey(), val.getValue());
+ // TODO: Discuss metadata handling...
+ result.putAll(val.getMetaEntries());
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Accesses the current String value for the given key and tries to convert it
+ * using the {@link PropertyConverter} instances provided by the current
+ * {@link ConfigurationContext}.
+ *
+ * @param key the property's absolute, or relative path, e.g. @code
+ * a/b/c/d.myProperty}, never {@code null}.
+ * @param type The target type required, not {@code null}.
+ * @param <T> the value type
+ * @return the converted value, never {@code null}.
+ */
+ @Override
+ public <T> T get(String key, Class<T> type) {
+ return get(key, TypeLiteral.of(type));
+ }
+
+ /**
+ * Accesses the current String value for the given key and tries to convert it
+ * using the {@link PropertyConverter} instances provided by the current
+ * {@link ConfigurationContext}.
+ *
+ * @param key the property's absolute, or relative path, e.g. @code
+ * a/b/c/d.myProperty}.
+ * @param type The target type required, not null.
+ * @param <T> the value type
+ * @return the converted value, never null.
+ */
+ @Override
+ public <T> T get(String key, TypeLiteral<T> type) {
+ Objects.requireNonNull(key, "Key must not be null.");
+ Objects.requireNonNull(type, "Target type must not be null");
+
+ return convertValue(key, get(key), type);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> T convertValue(String key, String value, TypeLiteral<T> type) {
+ if (value != null) {
+ List<PropertyConverter<T>> converters = configurationContext.getPropertyConverters(type);
+ ConversionContext context = new ConversionContext.Builder(this, this.configurationContext, key, type)
+ .build();
+ for (PropertyConverter<T> converter : converters) {
+ try {
+ T t = converter.convert(value, context);
+ if (t != null) {
+ return t;
+ }
+ } catch (Exception e) {
+ LOG.log(Level.FINEST, "PropertyConverter: " + converter + " failed to convert value: " + value, e);
+ }
+ }
+ // if the target type is a String, we can return the value, no conversion required.
+ if(type.equals(TypeLiteral.of(String.class))){
+ return (T)value;
+ }
+ // unsupported type, throw an exception
+ throw new ConfigException("Unparseable config value for type: " + type.getRawType().getName() + ": " + key +
+ ", supported formats: " + context.getSupportedFormats());
+ }
+ return null;
+ }
+
+ @Override
+ public <T> T getOrDefault(String key, TypeLiteral<T> type, T defaultValue) {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(type);
+
+ T val = get(key, type);
+ if(val==null){
+ return defaultValue;
+ }
+ return val;
+ }
+
+ @Override
+ public Configuration with(ConfigOperator operator) {
+ return operator.operate(this);
+ }
+
+ @Override
+ public <T> T query(ConfigQuery<T> query) {
+ return query.query(this);
+ }
+
+ @Override
+ public ConfigurationContext getContext() {
+ return this.configurationContext;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ DefaultConfiguration that = (DefaultConfiguration) o;
+
+ if (!configurationContext.equals(that.configurationContext)) return false;
+ return configEvaluator.getClass().equals(that.configEvaluator.getClass());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = configurationContext.hashCode();
+ result = 31 * result + configEvaluator.getClass().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Configuration{\n " +
+ configurationContext +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
new file mode 100644
index 0000000..1b3f1ce
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
@@ -0,0 +1,239 @@
+/*
+ * 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.*;
+import org.apache.tamaya.spi.ConfigurationBuilder;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Default implementation of {@link ConfigurationBuilder}.
+ */
+public class DefaultConfigurationBuilder implements ConfigurationBuilder {
+
+ protected final DefaultConfigurationContextBuilder contextBuilder;
+
+ /**
+ * Creates a new builder instance.
+ */
+ public DefaultConfigurationBuilder() {
+ this.contextBuilder = new DefaultConfigurationContextBuilder();
+ }
+
+ /**
+ * Creates a new builder instance.
+ */
+ public DefaultConfigurationBuilder(ConfigurationContext context) {
+ this.contextBuilder = new DefaultConfigurationContextBuilder(context);
+ }
+
+ /**
+ * Creates a new builder instance initializing it with the given context.
+ * @param configuration the configuration to be used, not null.
+ */
+ public DefaultConfigurationBuilder(Configuration configuration) {
+ this.contextBuilder = new DefaultConfigurationContextBuilder(configuration.getContext());
+ }
+
+ /**
+ * Allows to set configuration context during unit tests.
+ */
+ public ConfigurationBuilder setConfiguration(Configuration configuration) {
+ this.contextBuilder.setContext(configuration.getContext());
+ return this;
+ }
+
+
+ @Override
+ public ConfigurationBuilder setContext(ConfigurationContext context) {
+ this.contextBuilder.setContext(context);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder addPropertySources(PropertySource... sources){
+ this.contextBuilder.addPropertySources(sources);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder addPropertySources(Collection<PropertySource> sources){
+ this.contextBuilder.addPropertySources(sources);
+ return this;
+ }
+
+ public ConfigurationBuilder addDefaultPropertyFilters() {
+ this.contextBuilder.addDefaultPropertyFilters();
+ return this;
+ }
+
+ public ConfigurationBuilder addDefaultPropertySources() {
+ this.contextBuilder.addDefaultPropertySources();
+ return this;
+ }
+
+ public ConfigurationBuilder addDefaultPropertyConverters() {
+ this.contextBuilder.addDefaultPropertyConverters();
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder removePropertySources(PropertySource... propertySources) {
+ this.contextBuilder.removePropertySources(propertySources);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder removePropertySources(Collection<PropertySource> propertySources) {
+ this.contextBuilder.removePropertySources(propertySources);
+ return this;
+ }
+
+ @Override
+ public List<PropertySource> getPropertySources() {
+ return this.contextBuilder.getPropertySources();
+ }
+
+ @Override
+ public ConfigurationBuilder increasePriority(PropertySource propertySource) {
+ this.contextBuilder.increasePriority(propertySource);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder decreasePriority(PropertySource propertySource) {
+ this.contextBuilder.decreasePriority(propertySource);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder highestPriority(PropertySource propertySource) {
+ this.contextBuilder.highestPriority(propertySource);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder lowestPriority(PropertySource propertySource) {
+ this.contextBuilder.lowestPriority(propertySource);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder addPropertyFilters(Collection<PropertyFilter> filters){
+ this.contextBuilder.addPropertyFilters(filters);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder addPropertyFilters(PropertyFilter... filters){
+ this.contextBuilder.addPropertyFilters(filters);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder removePropertyFilters(PropertyFilter... filters) {
+ this.contextBuilder.removePropertyFilters(filters);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder removePropertyFilters(Collection<PropertyFilter> filters) {
+ this.contextBuilder.removePropertyFilters(filters);
+ return this;
+ }
+
+
+ @Override
+ public <T> ConfigurationBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ PropertyConverter<T>... converters) {
+ this.contextBuilder.removePropertyConverters(typeToConvert, converters);
+ return this;
+ }
+
+ @Override
+ public <T> ConfigurationBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> converters) {
+ this.contextBuilder.removePropertyConverters(typeToConvert, converters);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder removePropertyConverters(TypeLiteral<?> typeToConvert) {
+ this.contextBuilder.removePropertyConverters(typeToConvert);
+ return this;
+ }
+
+
+ @Override
+ public ConfigurationBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy combinationPolicy){
+ this.contextBuilder.setPropertyValueCombinationPolicy(combinationPolicy);
+ return this;
+ }
+
+ @Override
+ public <T> ConfigurationBuilder addPropertyConverters(TypeLiteral<T> type, PropertyConverter<T>... propertyConverters){
+ this.contextBuilder.addPropertyConverters(type, propertyConverters);
+ return this;
+ }
+
+ @Override
+ public <T> ConfigurationBuilder addPropertyConverters(TypeLiteral<T> type, Collection<PropertyConverter<T>> propertyConverters){
+ this.contextBuilder.addPropertyConverters(type, propertyConverters);
+ return this;
+ }
+
+ /**
+ * Builds a new configuration based on the configuration of this builder instance.
+ *
+ * @return a new {@link org.apache.tamaya.Configuration configuration instance},
+ * never {@code null}.
+ */
+ @Override
+ public Configuration build() {
+ return new DefaultConfiguration(this.contextBuilder.build());
+ }
+
+ @Override
+ public ConfigurationBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator) {
+ this.contextBuilder.sortPropertyFilter(comparator);
+ return this;
+ }
+
+ @Override
+ public ConfigurationBuilder sortPropertySources(Comparator<PropertySource> comparator) {
+ this.contextBuilder.sortPropertySources(comparator);
+ return this;
+ }
+
+ @Override
+ public List<PropertyFilter> getPropertyFilters() {
+ return this.contextBuilder.getPropertyFilters();
+ }
+
+ @Override
+ public Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter() {
+ return this.contextBuilder.getPropertyConverter();
+ }
+}
[7/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Posted by an...@apache.org.
Reimplemented (also simjplified) Tamaya core completely based on latest JSR API. Moved prior Tamaya API into compat module.
Signed-off-by: Anatole Tresch <an...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/d0e14ed7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/d0e14ed7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/d0e14ed7
Branch: refs/heads/configjsr
Commit: d0e14ed705b464f3d15f3bae5979cc90df275dc9
Parents: 9bc56a3
Author: Anatole Tresch <an...@apache.org>
Authored: Sun Dec 10 23:06:52 2017 +0100
Committer: Anatole Tresch <an...@apache.org>
Committed: Sun Dec 10 23:06:53 2017 +0100
----------------------------------------------------------------------
code/base/bnd.bnd | 31 ++
code/base/pom.xml | 91 ++++
code/compat/bnd.bnd | 34 ++
code/compat/pom.xml | 70 +++
.../java/org/apache/tamaya/ConfigException.java | 44 ++
.../java/org/apache/tamaya/ConfigOperator.java | 38 ++
.../java/org/apache/tamaya/ConfigQuery.java | 37 ++
.../java/org/apache/tamaya/Configuration.java | 180 +++++++
.../apache/tamaya/ConfigurationProvider.java | 138 ++++++
.../java/org/apache/tamaya/package-info.java | 23 +
.../apache/tamaya/spi/ConfigurationBuilder.java | 347 ++++++++++++++
.../apache/tamaya/spi/ConfigurationContext.java | 172 +++++++
.../tamaya/spi/ConfigurationContextBuilder.java | 334 +++++++++++++
.../tamaya/spi/ConfigurationProviderSpi.java | 128 +++++
.../apache/tamaya/spi/ConversionContext.java | 266 +++++++++++
.../org/apache/tamaya/spi/FilterContext.java | 140 ++++++
.../apache/tamaya/spi/PropertyConverter.java | 44 ++
.../org/apache/tamaya/spi/PropertyFilter.java | 51 ++
.../org/apache/tamaya/spi/PropertySource.java | 174 +++++++
.../tamaya/spi/PropertySourceProvider.java | 61 +++
.../org/apache/tamaya/spi/PropertyValue.java | 232 +++++++++
.../apache/tamaya/spi/PropertyValueBuilder.java | 196 ++++++++
.../spi/PropertyValueCombinationPolicy.java | 71 +++
.../org/apache/tamaya/spi/package-info.java | 24 +
.../tamaya/spisupport/ConfigValueEvaluator.java | 48 ++
.../spisupport/DefaultConfigValueEvaluator.java | 70 +++
.../tamaya/spisupport/DefaultConfiguration.java | 281 +++++++++++
.../spisupport/DefaultConfigurationBuilder.java | 239 ++++++++++
.../spisupport/DefaultConfigurationContext.java | 277 +++++++++++
.../DefaultConfigurationContextBuilder.java | 431 +++++++++++++++++
.../apache/tamaya/spisupport/EnumConverter.java | 39 ++
.../spisupport/PriorityServiceComparator.java | 84 ++++
.../spisupport/PropertyConverterManager.java | 472 +++++++++++++++++++
.../spisupport/PropertyFilterComparator.java | 72 +++
.../tamaya/spisupport/PropertyFiltering.java | 123 +++++
.../spisupport/PropertySourceComparator.java | 120 +++++
.../tamaya/spisupport/RegexPropertyFilter.java | 84 ++++
.../propertysource/BasePropertySource.java | 172 +++++++
.../propertysource/BuildablePropertySource.java | 231 +++++++++
.../BuildablePropertySourceProvider.java | 114 +++++
.../propertysource/CLIPropertySource.java | 137 ++++++
.../EnvironmentPropertySource.java | 287 +++++++++++
.../JavaConfigurationPropertySource.java | 134 ++++++
.../propertysource/MapPropertySource.java | 102 ++++
.../PropertiesResourcePropertySource.java | 109 +++++
.../propertysource/SimplePropertySource.java | 284 +++++++++++
.../propertysource/SystemPropertySource.java | 199 ++++++++
.../propertysource/WrappedPropertySource.java | 126 +++++
.../spisupport/propertysource/package-info.java | 23 +
.../compat/src/main/resources/tamaya-banner.txt | 11 +
.../org/apache/tamaya/ConfigExceptionTest.java | 45 ++
.../org/apache/tamaya/ConfigurationTest.java | 63 +++
.../org/apache/tamaya/TestConfiguration.java | 138 ++++++
.../tamaya/TestConfigurationProvider.java | 76 +++
.../java/org/apache/tamaya/TypeLiteralTest.java | 91 ++++
.../tamaya/spi/ConversionContextTest.java | 193 ++++++++
.../apache/tamaya/spi/FilterContextTest.java | 157 ++++++
.../tamaya/spi/ServiceContextManagerTest.java | 105 +++++
.../apache/tamaya/spi/ServiceContextTest.java | 128 +++++
.../apache/tamaya/spi/TestServiceContext.java | 120 +++++
.../tamaya/spisupport/RegexFilterTest.java | 75 +++
...g.apache.tamaya.spi.ConfigurationProviderSpi | 19 +
.../org.apache.tamaya.spi.ServiceContext | 19 +
.../org/apache/tamaya/core/BannerManager.java | 163 +++++++
.../tamaya/core/OSGIServiceComparator.java | 70 +++
.../apache/tamaya/core/OSGIServiceContext.java | 187 ++++++++
.../apache/tamaya/core/OSGIServiceLoader.java | 254 ++++++++++
.../core/TamayaConfigProviderResolver.java | 92 ++++
.../core/converters/BigDecimalConverter.java | 78 +++
.../core/converters/BigIntegerConverter.java | 107 +++++
.../core/converters/BooleanConverter.java | 74 +++
.../tamaya/core/converters/ByteConverter.java | 84 ++++
.../tamaya/core/converters/CharConverter.java | 81 ++++
.../tamaya/core/converters/ClassConverter.java | 79 ++++
.../tamaya/core/converters/ConvertQuery.java | 81 ++++
.../core/converters/CurrencyConverter.java | 103 ++++
.../tamaya/core/converters/DoubleConverter.java | 94 ++++
.../core/converters/DurationConverter.java | 60 +++
.../tamaya/core/converters/FileConverter.java | 63 +++
.../tamaya/core/converters/FloatConverter.java | 94 ++++
.../core/converters/InstantConverter.java | 58 +++
.../core/converters/IntegerConverter.java | 87 ++++
.../core/converters/LocalDateConverter.java | 58 +++
.../core/converters/LocalDateTimeConverter.java | 58 +++
.../core/converters/LocalTimeConverter.java | 58 +++
.../tamaya/core/converters/LongConverter.java | 84 ++++
.../tamaya/core/converters/NumberConverter.java | 85 ++++
.../converters/OffsetDateTimeConverter.java | 58 +++
.../core/converters/OffsetTimeConverter.java | 58 +++
.../core/converters/OptionalConverter.java | 78 +++
.../tamaya/core/converters/PathConverter.java | 64 +++
.../tamaya/core/converters/ShortConverter.java | 85 ++++
.../core/converters/SupplierConverter.java | 70 +++
.../tamaya/core/converters/URIConverter.java | 63 +++
.../tamaya/core/converters/URLConverter.java | 63 +++
.../tamaya/core/converters/package-info.java | 23 +
.../javax.config.spi.ConfigProviderResolver | 19 +
.../services/javax.config.spi.ConfigSource | 22 +
.../services/javax.config.spi.Converter | 44 ++
.../org.apache.tamaya.spi.ConfigValueEvaluator | 19 +
code/core/src/main/resources/tamaya-banner.txt | 11 +
.../apache/tamaya/core/BannerManagerTest.java | 89 ++++
.../apache/tamaya/core/ConfigBuilderTest.java | 94 ++++
.../tamaya/core/ConfigContextBuilderTest.java | 424 +++++++++++++++++
.../tamaya/core/ExtConfigBuilderTest.java | 447 ++++++++++++++++++
.../core/TamayaConfigProviderResolverTest.java | 69 +++
.../apache/tamaya/core/TestConfigSource.java | 67 +++
.../core/testdata/TestConfigNamesSource.java | 51 ++
.../apache/tamaya/core/testdata/TestFilter.java | 42 ++
.../core/testdata/TestRemovingFilter.java | 47 ++
.../resources/META-INF/javaconfig.properties | 22 +
.../src/test/resources/META-INF/javaconfig.xml | 25 +
.../services/javax.config.spi.ConfigSource | 21 +
.../javax.config.spi.ConfigSourceProvider | 19 +
.../services/javax.config.spi.Converter | 19 +
.../services/org.apache.tamaya.spi.Filter | 20 +
116 files changed, 12809 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/base/bnd.bnd
----------------------------------------------------------------------
diff --git a/code/base/bnd.bnd b/code/base/bnd.bnd
new file mode 100644
index 0000000..cc6472d
--- /dev/null
+++ b/code/base/bnd.bnd
@@ -0,0 +1,31 @@
+-buildpath: \
+ osgi.annotation; version=6.0.0,\
+ osgi.core; version=6.0,\
+ osgi.cmpn; version=6.0
+
+-testpath: \
+ ${junit}
+
+javac.source: 1.8
+javac.target: 1.8
+
+Bundle-Version: ${version}.${tstamp}
+Bundle-Name: Apache Tamaya - SPI Support
+Bundle-SymbolicName: org.apache.tamaya.spisupport
+Bundle-Description: Apacha Tamaya Config - SPI Support
+Bundle-Category: Implementation
+Bundle-Copyright: (C) Apache Foundation
+Bundle-License: Apache Licence version 2
+Bundle-Vendor: Apache Software Foundation
+Bundle-ContactAddress: dev-tamaya@incubator.apache.org
+Bundle-DocURL: http://tamaya.apache.org
+Export-Package: \
+ org.apache.tamaya.base,\
+ org.apache.tamaya.base.configsource,\
+ org.apache.tamaya.base.convert,\
+ org.apache.tamaya.base.filter,\
+ org.apache.tamaya.spi
+Import-Package: \
+ javax.config,\
+ javax.config.spi,\
+ javax.annotation
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/base/pom.xml
----------------------------------------------------------------------
diff --git a/code/base/pom.xml b/code/base/pom.xml
new file mode 100644
index 0000000..dc16016
--- /dev/null
+++ b/code/base/pom.xml
@@ -0,0 +1,91 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy current the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.tamaya</groupId>
+ <artifactId>tamaya-code</artifactId>
+ <version>0.4-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>tamaya-base</artifactId>
+ <name>Apache Tamaya JavaConfig SPI Base Support</name>
+ <description>Apache Tamaya Base Classes useful when implementing the JavaConfig SPI.</description>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tamaya</groupId>
+ <artifactId>tamaya-spisupport</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-annotation_1.2_spec</artifactId>
+ <version>1.0-alpha-1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.annotation</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>java-hamcrest</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <!--
+ ! See https://issues.apache.org/jira/browse/TAMAYA-318
+ !-->
+ <groupId>org.pitest</groupId>
+ <artifactId>pitest-maven</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/bnd.bnd
----------------------------------------------------------------------
diff --git a/code/compat/bnd.bnd b/code/compat/bnd.bnd
new file mode 100644
index 0000000..0409b56
--- /dev/null
+++ b/code/compat/bnd.bnd
@@ -0,0 +1,34 @@
+-buildpath: \
+ osgi.annotation; version=6.0.0,\
+ osgi.core; version=6.0,\
+ osgi.cmpn; version=6.0
+
+-testpath: \
+ ${junit}
+
+javac.source: 1.8
+javac.target: 1.8
+
+Bundle-Version: ${version}.${tstamp}
+Bundle-SymbolicName: org.apache.tamaya.compat
+Bundle-Name: Apache Tamaya - API
+Bundle-Description: Apacha Tamaya Configuration Java API
+Bundle-Category: API
+Bundle-Copyright: (C) Apache Foundation
+Bundle-License: Apache Licence version 2
+Bundle-Vendor: Apache Software Foundation
+Bundle-ContactAddress: dev-tamaya@incubator.apache.org
+Bundle-DocURL: http://tamaya.apache.org
+Export-Package: \
+ org.apache.tamaya,\
+ org.apache.tamaya.spisupport,\
+ org.apache.tamaya.spi,\
+ org.apache.tamaya.spisupport.propertysource
+Import-Package: \
+ javax.config,\
+ javax.config.spi,\
+ org.apache.tamaya.base,\
+ org.apache.tamaya.base.configsource,\
+ org.apache.tamaya.base.convert,\
+ org.apache.tamaya.base.filter,\
+ org.apache.tamaya.spi
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/pom.xml
----------------------------------------------------------------------
diff --git a/code/compat/pom.xml b/code/compat/pom.xml
new file mode 100644
index 0000000..c48131b
--- /dev/null
+++ b/code/compat/pom.xml
@@ -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 current the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.tamaya</groupId>
+ <artifactId>tamaya-code</artifactId>
+ <version>0.4-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>tamaya-compat</artifactId>
+ <name>Apache Tamaya Compatibility API</name>
+ <packaging>jar</packaging>
+
+ <description>
+ The compatibility API from former Tamaya versions.
+ </description>
+
+
+ <url>http://tamaya.incubator.apache.org</url>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tamaya</groupId>
+ <artifactId>tamaya-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>java-hamcrest</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.annotation</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/ConfigException.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/ConfigException.java b/code/compat/src/main/java/org/apache/tamaya/ConfigException.java
new file mode 100644
index 0000000..38b0801
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/ConfigException.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+/**
+ * Exception class (runtime exception) for configuration issues.
+ */
+public class ConfigException extends RuntimeException{
+
+ private static final long serialVersionUID = -5886094818057522680L;
+
+ /**
+ * Creates a new configuration exception.
+ * @param message the exception message, not {@code null}.
+ */
+ public ConfigException(String message){
+ super(message);
+ }
+
+ /**
+ * Creates a new configuration exception.
+ * @param message the exception message, not {@code null}.
+ * @param t the throwable.
+ */
+ public ConfigException(String message, Throwable t){
+ super(message, t);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/ConfigOperator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/ConfigOperator.java b/code/compat/src/main/java/org/apache/tamaya/ConfigOperator.java
new file mode 100644
index 0000000..b14c155
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/ConfigOperator.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Models a function that maps a given {@link org.apache.tamaya.Configuration} to another {@link org.apache.tamaya.Configuration}. This can be used
+ * to modell additional functionality and applying it to a given {@link org.apache.tamaya.Configuration} instance by calling
+ * the {@link org.apache.tamaya.Configuration#with(org.apache.tamaya.ConfigOperator)} method.
+ */
+@FunctionalInterface
+public interface ConfigOperator {
+
+ /**
+ * Creates a new {@link org.apache.tamaya.Configuration} based on the given Configuration. Operators basically acts similar to
+ * decorators, whereas operated instances may have non compatible behaviour, e.g. by applying security constraints
+ * or view restrictions.
+ *
+ * @param config the input configuration, not {@code null}.
+ * @return the operated configuration, never {@code null}.
+ */
+ Configuration operate(Configuration config);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/ConfigQuery.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/ConfigQuery.java b/code/compat/src/main/java/org/apache/tamaya/ConfigQuery.java
new file mode 100644
index 0000000..28b8b93
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/ConfigQuery.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+/**
+ * Models a function that maps a given {@link Configuration} to something else. This can be used
+ * to model additional functionality and applying it to a given {@link Configuration} instance by
+ * calling the {@link Configuration#query(ConfigQuery)} method.
+ */
+@FunctionalInterface
+public interface ConfigQuery<T> {
+
+ /**
+ * Creates a result based on the given Configuration. Queries basically acts similar to
+ * operators, whereas they returns any kind of result.
+ *
+ * @param config the input configuration, not {@code null}.
+ * @return the query result.
+ */
+ T query(Configuration config);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/Configuration.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/Configuration.java b/code/compat/src/main/java/org/apache/tamaya/Configuration.java
new file mode 100644
index 0000000..3cf57f7
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/Configuration.java
@@ -0,0 +1,180 @@
+/*
+ * 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;
+
+import org.apache.tamaya.spi.ConfigurationBuilder;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.TypeLiteral;
+
+import java.util.Map;
+
+
+/**
+ * <p>A configuration models a aggregated set current properties, identified by
+ * a unique key, but adds higher level access functions to
+ * a {@link org.apache.tamaya.spi.PropertySource}. Hereby in most
+ * cases a configuration is a wrapper around a composite
+ * {@link org.apache.tamaya.spi.PropertySource} instance, which may combine
+ * multiple child config in well defined tree like structure,
+ * where nodes define logically the rules current priority, filtering,
+ * combination and overriding.
+ * </p>
+ * <h3>Implementation Requirements</h3>
+ * Implementations current this interface must be
+ * <ul>
+ * <li>Thread safe</li>
+ * <li>Immutable</li>
+ * </ul>
+ *
+ * <p>It is not recommended that implementations also are serializable, since the any configuration can be <i>frozen</i>
+ * by reading out its complete configuration map into a serializable and remotable structure. This helps significantly
+ * simplifying the development current this interface, e.g. for being backed up by systems and stores that are not part current
+ * this library at all.</p>
+ */
+public interface Configuration {
+
+ /**
+ * Access a property.
+ *
+ * @param key the property's key, not {@code null}.
+ * @return the property's value.
+ */
+ default String get(String key){
+ return get(key, org.apache.tamaya.spi.TypeLiteral.of(String.class));
+ }
+
+ /**
+ * Access a property.
+ *
+ * @param key the property's key, not {@code null}.
+ * @param defaultValue value to be returned, if no value is present, not {@code null}
+ * @return the property's keys.
+ */
+ default String getOrDefault(String key, String defaultValue){
+ return getOrDefault(key, org.apache.tamaya.spi.TypeLiteral.of(String.class), defaultValue);
+ }
+
+ /**
+ * Get the property keys as type T. This will implicitly require a corresponding {@link
+ * org.apache.tamaya.spi.PropertyConverter} to be available that is capable current providing type T
+ * fromMap the given String keys.
+ *
+ * @param <T> the type of the class modeled by the type parameter
+ * @param key the property's absolute, or relative path, e.g. @code
+ * a/b/c/d.myProperty}, not {@code null}.
+ * @param type The target type required, not {@code null}.
+ * @param defaultValue value to be used, if no value is present, not {@code null}
+ * @return the property value, never {@code null}.
+ * @throws ConfigException if the keys could not be converted to the required target type.
+ */
+ default <T> T getOrDefault(String key, Class<T> type, T defaultValue){
+ return getOrDefault(key, org.apache.tamaya.spi.TypeLiteral.of(type), defaultValue);
+ }
+
+ /**
+ * Get the property keys as type T. This will implicitly require a corresponding {@link
+ * org.apache.tamaya.spi.PropertyConverter} to be available that is capable current providing type T
+ * fromMap the given String keys.
+ *
+ * @param <T> the type of the class modeled by the type parameter
+ * @param key the property's absolute, or relative path, e.g. @code
+ * a/b/c/d.myProperty}.
+ * @param type The target type required, not {@code null}.
+ * @return the property value, never {@code null}.
+ * @throws ConfigException if the keys could not be converted to the required target type.
+ */
+ default <T> T get(String key, Class<T> type){
+ return get(key, org.apache.tamaya.spi.TypeLiteral.of(type));
+ }
+
+ /**
+ * Get the property keys as type T. This will implicitly require a corresponding {@link
+ * org.apache.tamaya.spi.PropertyConverter} to be available that is capable current providing type T
+ * fromMap the given String keys.
+ *
+ * @param <T> the type of the type literal
+ * @param key the property's absolute, or relative path, e.g. @code
+ * a/b/c/d.myProperty}, not {@code null}.
+ * @param type The target type required, not {@code null}.
+ * @return the property value, never {@code null}.
+ * @throws ConfigException if the keys could not be converted to the required target type.
+ */
+ <T> T get(String key, org.apache.tamaya.spi.TypeLiteral<T> type);
+
+ /**
+ * Get the property keys as type T. This will implicitly require a corresponding {@link
+ * org.apache.tamaya.spi.PropertyConverter} to be available that is capable current providing type T
+ * fromMap the given String keys.
+ *
+ * @param <T> the type of the type literal
+ * @param key the property's absolute, or relative path, e.g.
+ * {@code a/b/c/d.myProperty}, not {@code null}.
+ * @param type The target type required, not {@code null}.
+ * @param defaultValue default value to be used, if no value is present.
+ * @return the property value, never null.
+ * @throws ConfigException if the keys could not be converted to the required target type.
+ */
+ <T> T getOrDefault(String key, TypeLiteral<T> type, T defaultValue);
+
+ /**
+ * Access all currently known configuration properties as a full {@code Map<String,String>}.
+ * Be aware that entries from non scannable parts of the registered {@link org.apache.tamaya.spi.PropertySource}
+ * instances may not be contained in the result, but nevertheless be accessible calling one of the
+ * {@code get(...)} methods.
+ * @return all currently known configuration properties.
+ */
+ Map<String,String> getProperties();
+
+ /**
+ * Extension point for adjusting configuration.
+ *
+ * @param operator A configuration operator, e.g. a filter, or an adjuster
+ * combining configurations, never {@code null}.
+ * @return the new adjusted configuration returned by the {@code operator}, never {@code null}.
+ */
+ default Configuration with(ConfigOperator operator){
+ return operator.operate(this);
+ }
+
+ /**
+ * Query a configuration.
+ *
+ * @param <T> the type of the configuration.
+ * @param query the query, not {@code null}.
+ * @return the result returned by the {@code query}.
+ */
+ default <T> T query(ConfigQuery<T> query){
+ return query.query(this);
+ }
+
+ /**
+ * Access a configuration's context.
+ * @return the configuration context, never null.
+ */
+ ConfigurationContext getContext();
+
+ /**
+ * Create a new builder using this instance as it's base.
+ * @return a new builder, never null.
+ */
+ default ConfigurationBuilder toBuilder() {
+ return ConfigurationProvider.getConfigurationBuilder().setConfiguration(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/ConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/ConfigurationProvider.java b/code/compat/src/main/java/org/apache/tamaya/ConfigurationProvider.java
new file mode 100644
index 0000000..bacb944
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/ConfigurationProvider.java
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import org.apache.tamaya.spi.*;
+
+import java.util.logging.Logger;
+
+/**
+ * Static access to the {@link Configuration} for the very application.
+ */
+public final class ConfigurationProvider {
+
+ private static final Logger LOG = Logger.getLogger(ConfigurationProvider.class.getName());
+
+ private static ConfigurationProviderSpi spi() {
+ ConfigurationProviderSpi spi = ServiceContextManager.getServiceContext()
+ .getService(ConfigurationProviderSpi.class);
+ if(spi==null){
+ throw new IllegalStateException("ConfigurationProviderSpi not available.");
+ }
+ return spi;
+ }
+
+ private ConfigurationProvider() {
+ // just to prevent initialisation
+ }
+
+ /**
+ * Access the current configuration.
+ *
+ * @return the corresponding Configuration instance, never {@code null}.
+ */
+ public static Configuration getConfiguration() {
+ return spi().getConfiguration();
+ }
+
+ /**
+ * Creates a new configuration instance based on the given context.
+ *
+ * @param context the configuration context, not {@code null}.
+ * @return a new Configuration instance, never {@code null}.
+ */
+ public static Configuration createConfiguration(ConfigurationContext context) {
+ return spi().createConfiguration(context);
+ }
+
+ /**
+ * Get access to the current ConfigurationContext.
+ *
+ * @return the current ConfigurationContext, never null.
+ * @deprecated Use {@link Configuration#getContext()} instead of.
+ */
+ @Deprecated
+ public static ConfigurationContext getConfigurationContext() {
+ return spi().getConfigurationContext();
+ }
+
+ /**
+ * This method allows to replace the current {@link org.apache.tamaya.spi.ConfigurationContext} with a new
+ * instance. This can be used to update the context with a new one, e.g. because some of the configuration
+ * data has changed and should be updated. It is the responsibility of the ConfigurationProvider to trigger
+ * corresponding update events for the current {@link org.apache.tamaya.Configuration}, so observing
+ * listeners can do whatever is appropriate to react to any given configuration changes.
+ *
+ * @param context the new ConfigurationContext to be applied.
+ * @throws java.lang.UnsupportedOperationException if the current provider is read-only and does not support
+ * applying a new ConfigurationContext.
+ * @deprecated Use #setConfiguration(Configuration) instead of.
+ */
+ @Deprecated
+ public static void setConfigurationContext(ConfigurationContext context) {
+ spi().setConfigurationContext(context);
+ }
+
+ /**
+ * This method allows to replace the current default {@link org.apache.tamaya.Configuration} with a new
+ * instance. It is the responsibility of the ConfigurationProvider to trigger
+ * corresponding update events for the current {@link org.apache.tamaya.Configuration}, so observing
+ * listeners can do whatever is appropriate to react to any given configuration change.
+ *
+ * @param config the new Configuration to be applied, not {@code null}
+ * @throws java.lang.UnsupportedOperationException if the current provider is read-only and
+ * does not support
+ * applying a new Configuration.
+ */
+ public static void setConfiguration(Configuration config) {
+ LOG.info("TAMAYA Applying new Configuration: " + config);
+ spi().setConfiguration(config);
+ }
+
+ /**
+ * Create a new {@link ConfigurationBuilder} instance. This method creates
+ * a new builder instance that is not related to any concrete {@link org.apache.tamaya.spi.ConfigurationContext}.
+ * You can use {@link #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)} to change the
+ * current configuration context.
+ *
+ * @return a new, empty {@link ConfigurationBuilder}, never null.
+ * @see #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)
+ * @see org.apache.tamaya.spi.ConfigurationContext
+ * @deprecated Will be removed.
+ */
+ @Deprecated
+ public static ConfigurationContextBuilder getConfigurationContextBuilder() {
+ return spi().getConfigurationContextBuilder();
+ }
+
+ /**
+ * Create a new {@link ConfigurationBuilder} instance. This method creates
+ * a new builder instance that is not related to any concrete {@link org.apache.tamaya.spi.ConfigurationContext}.
+ * You can use {@link #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)} to change the
+ * current configuration context.
+ *
+ * @return a new, empty {@link ConfigurationBuilder}, never null.
+ * @see #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)
+ * @see org.apache.tamaya.spi.ConfigurationContext
+ */
+ public static ConfigurationBuilder getConfigurationBuilder() {
+ return spi().getConfigurationBuilder();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/package-info.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/package-info.java b/code/compat/src/main/java/org/apache/tamaya/package-info.java
new file mode 100644
index 0000000..486116a
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * This package contains the Apache Tamaya API.
+ */
+package org.apache.tamaya;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
new file mode 100644
index 0000000..ac3e3b9
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
@@ -0,0 +1,347 @@
+/*
+ * 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.Configuration;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A builder for creating new instance of {@link Configuration}.
+ * Builders can be obtained in exactly two ways:
+ * <ol>
+ * <li>By accessing a preinitialized builder from an existing {@link Configuration},
+ * by calling {@link org.apache.tamaya.Configuration#toBuilder()}.</li>
+ * <li>By accessing an empty builder instance from
+ * {@link org.apache.tamaya.ConfigurationProvider#getConfigurationBuilder()}.</li>
+ * </ol>
+ * After all changes are applied to a builder a new {@link Configuration} instance can
+ * be created and can be applied by calling
+ * {@link #build()}}.
+ *
+ */
+public interface ConfigurationBuilder {
+
+ /**
+ * Init this builder instance with the given {@link Configuration} instance. This
+ * method will use any existing property sources, filters, converters and the combination
+ * policy of the given {@link Configuration} and initialize the current builder
+ * with them. All previous property sources, filters, converters and the combination
+ * policy of this instance will be replaced.
+ *
+ * @param config the {@link Configuration} instance to be used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder setConfiguration(Configuration config);
+
+ /**
+ * Init this builder instance with the given {@link ConfigurationContext} instance. This
+ * method will use any existing property sources, filters, converters and the combination
+ * policy of the given {@link ConfigurationContext} and initialize the current builder
+ * with them. All previous property sources, filters, converters and the combination
+ * policy of this instance will be replaced.
+ *
+ * @param context the {@link ConfigurationContext} instance to be used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder setContext(ConfigurationContext context);
+
+ /**
+ * This method can be used for adding {@link PropertySource}s.
+ * Hereby the property source is added to the tail of property sources with
+ * lowest priority regardless of its current ordinal value. To sort the property
+ * sources based on their ordinals call {@link #sortPropertySources}.
+ *
+ * @param propertySources the PropertySources to add
+ * @return this builder, for chaining, never null.
+ * @throws IllegalArgumentException If a property source with a given name already
+ * exists.
+ */
+ ConfigurationBuilder addPropertySources(PropertySource... propertySources);
+
+ /**
+ * This method can be used for programmatically adding {@link PropertySource}s.
+ * Hereby the property source is added to the tail of property sources with
+ * lowest priority regardless of its current ordinal value. To sort the property
+ * sources based on their ordinals call {@link #sortPropertySources}.
+ *
+ * @param propertySources the PropertySources to add
+ * @return this builder, for chaining, never null.
+ * @throws IllegalArgumentException If a property source with a given name already
+ * exists.
+ */
+ ConfigurationBuilder addPropertySources(Collection<PropertySource> propertySources);
+
+ /**
+ * Add all registered (default) property sources to the context built. The sources are ordered
+ * based on their ordinal values and added to the chain of property sources with
+ * higher priority.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder addDefaultPropertySources();
+
+ /**
+ * Removes the given property sources, if existing. The existing order of property
+ * sources is preserved.
+ *
+ * @param propertySources the property sources to remove, not {@code null}.
+ * @return the builder for chaining.
+ */
+ ConfigurationBuilder removePropertySources(PropertySource... propertySources);
+
+ /**
+ * Removes the given property sources, if existing. The existing order of property
+ * sources is preserved.
+ *
+ * @param propertySources the property sources to remove, not {@code null}.
+ * @return the builder for chaining.
+ */
+ ConfigurationBuilder removePropertySources(Collection<PropertySource> propertySources);
+
+ /**
+ * Access the current chain of property sources. Items at the end of the list have
+ * precedence/more significance.
+ *
+ * @return the property source chain, never {@code null}.
+ */
+ List<PropertySource> getPropertySources();
+
+ /**
+ * Access the current chain of property filters. Items at the end of the list have
+ * precedence/more significance.
+ *
+ * @return the property filter chain, never {@code null}.
+ */
+ List<PropertyFilter> getPropertyFilters();
+
+ /**
+ * Access the current registered property converters.
+ *
+ * @return the current registered property converters.
+ */
+ Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter();
+
+ /**
+ * Increases the priority of the given property source, by moving it towards the end
+ * of the chain of property sources. If the property source given is already at the end
+ * this method has no effect. This operation does not change any ordinal values.
+ *
+ * @param propertySource the property source to be incresed regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationBuilder increasePriority(PropertySource propertySource);
+
+ /**
+ * Decreases the priority of the given property source, by moving it towards the start
+ * of the chain of property sources. If the property source given is already the first
+ * this method has no effect. This operation does not change any ordinal values.
+ *
+ * @param propertySource the property source to be decresed regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationBuilder decreasePriority(PropertySource propertySource);
+
+ /**
+ * Increases the priority of the given property source to be maximal, by moving it to
+ * the tail of the of property source chain. If the property source given is
+ * already the last item this method has no effect. This operation does not change
+ * any ordinal values.
+ *
+ * @param propertySource the property source to be maximized regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationBuilder highestPriority(PropertySource propertySource);
+
+ /**
+ * Decreases the priority of the given property source to be minimal, by moving it to
+ * the start of the chain of property source chain. If the property source given is
+ * already the first item this method has no effect. This operation does not change
+ * any ordinal values.
+ *
+ * @param propertySource the property source to be minimized regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationBuilder lowestPriority(PropertySource propertySource);
+
+ /**
+ * Adds the given PropertyFilter instances, hereby the instances are added
+ * to the end of the list with highest priority. The ordering of existing
+ * property filters remains unchanged. To sort the property
+ * filters call {@link #sortPropertyFilter}.
+ *
+ * @param filters the filters to add
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder addPropertyFilters(PropertyFilter... filters);
+
+ /**
+ * Adds the given PropertyFilter instances, hereby the instances are added
+ * to the end of the list with highest priority. The ordering of existing
+ * property filters remains unchanged. To sort the property
+ * filters call {@link #sortPropertyFilter}.
+ *
+ * @param filters the filters to add
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder addPropertyFilters(Collection<PropertyFilter> filters);
+
+ /**
+ * Add all auto-discoverable property filters to the context built.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder addDefaultPropertyFilters();
+
+
+ /**
+ * Removes the given PropertyFilter instances, if existing. The order of the remaining
+ * filters is preserved.
+ *
+ * @param filters the filter to remove
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder removePropertyFilters(PropertyFilter... filters);
+
+ /**
+ * Removes the given PropertyFilter instances, if existing. The order of the remaining
+ * filters is preserved.
+ *
+ * @param filters the filter to remove
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder removePropertyFilters(Collection<PropertyFilter> filters);
+
+ /**
+ * This method can be used for adding {@link PropertyConverter}s.
+ * Converters are added at the end after any existing converters.
+ * For converters already registered for the current target type the
+ * method has no effect.
+ *
+ * @param typeToConvert the type for which the converter is for
+ * @param propertyConverters the PropertyConverters to add for this type
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationBuilder addPropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... propertyConverters);
+
+ /**
+ * This method can be used for adding {@link PropertyConverter}s.
+ * Converters are added at the end after any existing converters.
+ * For converters already registered for the current target type the
+ * method has no effect.
+ *
+ * @param typeToConvert the type for which the converter is for
+ * @param propertyConverters the PropertyConverters to add for this type
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationBuilder addPropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> propertyConverters);
+
+ /**
+ * Add all auto-discoverable property converters to the context built.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder addDefaultPropertyConverters();
+
+ /**
+ * Removes the given PropertyConverter instances for the given type,
+ * if existing.
+ *
+ * @param typeToConvert the type which the converter is for
+ * @param propertyConverters the converter to remove
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... propertyConverters);
+
+ /**
+ * Removes the given PropertyConverter instances for the given type,
+ * if existing.
+ *
+ * @param typeToConvert the type which the converter is for
+ * @param propertyConverters the converter to remove
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> propertyConverters);
+
+ /**
+ * Removes all converters for the given type, which actually renders a given type
+ * unsupported for type conversion.
+ *
+ * @param typeToConvert the type which the converter is for
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder removePropertyConverters(TypeLiteral<?> typeToConvert);
+
+ /**
+ * Sorts the current registered property sources using the given comparator.
+ *
+ * NOTE: property sources at the beginning have minimal significance.
+ *
+ * @param comparator the comparator to be used, not {@code null}.
+ * @return this instance for chaining.
+ */
+ ConfigurationBuilder sortPropertySources(Comparator<PropertySource> comparator);
+
+ /**
+ * Sorts the current registered property filters using the given comparator.
+ *
+ * NOTE: property filters at the beginning have minimal significance.
+ *
+ * @param comparator the comparator to be used, not {@code null}.
+ * @return this instance for chaining.
+ */
+ ConfigurationBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator);
+
+ /**
+ * Sets the {@link PropertyValueCombinationPolicy} used to evaluate the final
+ * property values.
+ *
+ * @param policy the {@link PropertyValueCombinationPolicy} used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy);
+
+ /**
+ * Builds a new {@link Configuration} based on the data in this builder. The ordering of property
+ * sources and property filters is not changed, regardless of their ordinals. For ensure a certain
+ * ordering/significance use {@link #sortPropertyFilter(Comparator)} and/or {@link #sortPropertySources(Comparator)}
+ * before building the context.
+ *
+ * @return the final configuration, never null.
+ */
+ Configuration build();
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
new file mode 100644
index 0000000..43f7ea0
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
@@ -0,0 +1,172 @@
+/*
+ * 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.util.List;
+import java.util.Map;
+
+/**
+ * Central SPI for programmatically dealing with the setup of the configuration system.
+ * This includes adding and enlisting {@link org.apache.tamaya.spi.PropertySource}s,
+ * managing {@link PropertyConverter}s, ConfigFilters, etc.
+ */
+public interface ConfigurationContext {
+
+ /**
+ * This method can be used for programmatically adding {@link PropertySource}s.
+ * It is not needed for normal 'usage' by end users, but only for Extension Developers!
+ *
+ * @param propertySources the PropertySources to add
+ * @deprecated Use {@link ConfigurationContextBuilder} to create a new {@link ConfigurationContext}.
+ * @see #toBuilder()
+ */
+ @Deprecated
+ void addPropertySources(PropertySource... propertySources);
+
+ /**
+ * This method returns the current list of registered PropertySources ordered via their ordinal.
+ * PropertySources with a lower ordinal come last. The PropertySource with the
+ * highest ordinal comes first.
+ * If two PropertySources have the same ordinal number they will get sorted
+ * using their class name just to ensure the user at least gets the same ordering
+ * after a JVM restart, hereby names before are added last.
+ * PropertySources are loaded when this method is called the first time, which basically is
+ * when the first time configuration is accessed.
+ *
+ * @return a sorted list of registered PropertySources. The returned list need not be modifiable
+ */
+ List<PropertySource> getPropertySources();
+
+ /**
+ * Access a {@link PropertySource} using its (unique) name.
+ * @param name the propoerty source's name, not {@code null}.
+ * @return the propoerty source found, or {@code null}.
+ */
+ PropertySource getPropertySource(String name);
+
+ /**
+ * This method can be used for programmatically adding {@link PropertyConverter}s.
+ * It is not needed for normal 'usage' by end users, but only for Extension Developers!
+ *
+ * @param <T> the type of the type literal
+ * @param type the type which the converters is for
+ * @param propertyConverter the PropertyConverters to add for this type
+ * @deprecated Use {@link ConfigurationContextBuilder} to create a new {@link ConfigurationContext}.
+ * @see #toBuilder()
+ */
+ @Deprecated
+ <T> void addPropertyConverter(TypeLiteral<T> type, PropertyConverter<T> propertyConverter);
+
+
+ /**
+ * <p>
+ * This method returns the Map of registered PropertyConverters
+ * per type.
+ * The List for each type is ordered via their {@link javax.annotation.Priority} and
+ * cladd name.
+ * </p>
+ *
+ * <p>A simplified scenario could be like:</p>
+ * <pre>
+ * {
+ * Date.class -> {StandardDateConverter, TimezoneDateConverter, MyCustomDateConverter }
+ * Boolean.class -> {StandardBooleanConverter, FrenchBooleanConverter}
+ * Integer.class -> {DynamicDefaultConverter}
+ * }
+ * </pre>
+ *
+ * @return map with sorted list of registered PropertySources per type.
+ */
+ Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters();
+
+ /**
+ * <p>
+ * This method returns the registered PropertyConverters for a given type.
+ * The List for each type is ordered via their {@link javax.annotation.Priority}.
+ * </p>
+ *
+ * <p>
+ * PropertyConverters with a higher Priority come first. The PropertyConverter with the
+ * lowest Priority comes last.
+ * If two PropertyConverter have the same ordinal number they will get sorted
+ * using their class name just to ensure the user at least gets the same ordering
+ * after a JVM restart.
+ * </p>
+ *
+ * <p>
+ * Additionally if a PropertyProvider is accessed, which is not registered the implementation
+ * should try to figure out, if there could be a default implementation as follows:</p>
+ * <ol>
+ * <li>Look for static factory methods: {@code of(String), valueOf(String), getInstance(String),
+ * instanceOf(String), fomr(String)}</li>
+ * <li>Look for a matching constructor: {@code T(String)}.</li>
+ * </ol>
+ *
+ * <p>
+ * If a correspoding factory method or constructor could be found, a corresponding
+ * PropertyConverter should be created and registered automatically for the given
+ * type.
+ * </p>
+ *
+ * <p> The scenario could be like:</p>
+ *
+ * <pre>
+ * {
+ * Date.class -> {MyCustomDateConverter,StandardDateConverter, TimezoneDateConverter}
+ * Boolean.class -> {StandardBooleanConverter, FrenchBooleanConverter}
+ * Integer.class -> {DynamicDefaultConverter}
+ * }
+ * </pre>
+ *
+ * <p>
+ * The converters returned for a type should be used as a chain, whereas the result of the
+ * first converters that is able to convert the configured value, is taken as the chain's result.
+ * No more converters are called after a converters has successfully converted the input into
+ * the required target type.
+ * </p>
+ *
+ * @param <T> the type of the type literal
+ * @param type type of the desired converters
+ * @return a sorted list of registered PropertySources per type.
+ */
+ <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> type);
+
+ /**
+ * Access the current PropertyFilter instances.
+ * @return the list of registered PropertyFilters, never null.
+ */
+ List<PropertyFilter> getPropertyFilters();
+
+ /**
+ * Access the {@link org.apache.tamaya.spi.PropertyValueCombinationPolicy} used to evaluate the final
+ * property values.
+ * @return the {@link org.apache.tamaya.spi.PropertyValueCombinationPolicy} used, never null.
+ */
+ PropertyValueCombinationPolicy getPropertyValueCombinationPolicy();
+
+ /**
+ * Creates a {@link ConfigurationContextBuilder} preinitialized with the data from this instance.
+ * @return a new builder instance, never null.
+ * @deprecated Will be removed.
+ */
+ @Deprecated
+ ConfigurationContextBuilder toBuilder();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java
new file mode 100644
index 0000000..8e3f307
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java
@@ -0,0 +1,334 @@
+/*
+ * 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.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A builder for creating new or adapting instances of {@link ConfigurationContext}.
+ * Builders can be obtained in exactly two ways:
+ * <ol>
+ * <li>By accessing a preinitialized builder from an existing {@link ConfigurationContext},
+ * by calling {@link org.apache.tamaya.spi.ConfigurationContext#toBuilder()}.</li>
+ * <li>By accessing an empty builder instance from
+ * {@link org.apache.tamaya.ConfigurationProvider#getConfigurationContextBuilder()}.</li>
+ * </ol>
+ * After all changes are applied to a builder a new {@link ConfigurationContext} instance can
+ * be created and can be applied by calling
+ * {@link org.apache.tamaya.ConfigurationProvider#setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)}.
+ * @deprecated Use {@link ConfigurationBuilder} instead.
+ */
+@Deprecated
+public interface ConfigurationContextBuilder {
+
+ /**
+ * Init this builder instance with the given {@link ConfigurationContext} instance. This
+ * method will use any existing property sources, filters, converters and the combination
+ * policy of the given {@link ConfigurationContext} and initialize the current builder
+ * with them.
+ *
+ * @param context the {@link ConfigurationContext} instance to be used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder setContext(ConfigurationContext context);
+
+ /**
+ * This method can be used for adding {@link PropertySource}s.
+ * Hereby the property source is added to the tail of property sources with
+ * lowest priority regardless of its current ordinal value. To sort the property
+ * sources based on their ordinals call {@link #sortPropertySources}.
+ *
+ * @param propertySources the PropertySources to add
+ * @return this builder, for chaining, never null.
+ * @throws IllegalArgumentException If a property source with a given name already
+ * exists.
+ */
+ ConfigurationContextBuilder addPropertySources(PropertySource... propertySources);
+
+ /**
+ * This method can be used for programmatically adding {@link PropertySource}s.
+ * Hereby the property source is added to the tail of property sources with
+ * lowest priority regardless of its current ordinal value. To sort the property
+ * sources based on their ordinals call {@link #sortPropertySources}.
+ *
+ * @param propertySources the PropertySources to add
+ * @return this builder, for chaining, never null.
+ * @throws IllegalArgumentException If a property source with a given name already
+ * exists.
+ */
+ ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySources);
+
+ /**
+ * Add all registered (default) property sources to the context built. The sources are ordered
+ * based on their ordinal values and added to the chain of property sources with
+ * higher priority.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addDefaultPropertySources();
+
+ /**
+ * Removes the given property sources, if existing. The existing order of property
+ * sources is preserved.
+ *
+ * @param propertySources the property sources to remove, not {@code null}.
+ * @return the builder for chaining.
+ */
+ ConfigurationContextBuilder removePropertySources(PropertySource... propertySources);
+
+ /**
+ * Removes the given property sources, if existing. The existing order of property
+ * sources is preserved.
+ *
+ * @param propertySources the property sources to remove, not {@code null}.
+ * @return the builder for chaining.
+ */
+ ConfigurationContextBuilder removePropertySources(Collection<PropertySource> propertySources);
+
+ /**
+ * Access the current chain of property sources. Items at the end of the list have
+ * precedence/more significance.
+ *
+ * @return the property source chain, never {@code null}.
+ */
+ List<PropertySource> getPropertySources();
+
+ /**
+ * Access the current chain of property filters. Items at the end of the list have
+ * precedence/more significance.
+ *
+ * @return the property source chain, never {@code null}.
+ */
+ List<PropertyFilter> getPropertyFilters();
+
+ /**
+ * Access the current registered property converters.
+ *
+ * @return the current registered property converters.
+ */
+ Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter();
+
+ /**
+ * Increases the priority of the given property source, by moving it towards the end
+ * of the chain of property sources. If the property source given is already at the end
+ * this method has no effect. This operation does not change any ordinal values.
+ *
+ * @param propertySource the property source to be incresed regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder increasePriority(PropertySource propertySource);
+
+ /**
+ * Decreases the priority of the given property source, by moving it towards the start
+ * of the chain of property sources. If the property source given is already the first
+ * this method has no effect. This operation does not change any ordinal values.
+ *
+ * @param propertySource the property source to be decresed regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder decreasePriority(PropertySource propertySource);
+
+ /**
+ * Increases the priority of the given property source to be maximal, by moving it to
+ * the tail of the of property source chain. If the property source given is
+ * already the last item this method has no effect. This operation does not change
+ * any ordinal values.
+ *
+ * @param propertySource the property source to be maximized regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder highestPriority(PropertySource propertySource);
+
+ /**
+ * Decreases the priority of the given property source to be minimal, by moving it to
+ * the start of the chain of property source chain. If the property source given is
+ * already the first item this method has no effect. This operation does not change
+ * any ordinal values.
+ *
+ * @param propertySource the property source to be minimized regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder lowestPriority(PropertySource propertySource);
+
+ /**
+ * Adds the given PropertyFilter instances, hereby the instances are added
+ * to the end of the list with highest priority. The ordering of existing
+ * property filters remains unchanged. To sort the property
+ * filters call {@link #sortPropertyFilter}.
+ *
+ * @param filters the filters to add
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters);
+
+ /**
+ * Adds the given PropertyFilter instances, hereby the instances are added
+ * to the end of the list with highest priority. The ordering of existing
+ * property filters remains unchanged. To sort the property
+ * filters call {@link #sortPropertyFilter}.
+ *
+ * @param filters the filters to add
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters);
+
+ /**
+ * Add all registered (default) property filters to the context built.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addDefaultPropertyFilters();
+
+
+ /**
+ * Removes the given PropertyFilter instances, if existing. The order of the remaining
+ * filters is preserved.
+ *
+ * @param filters the filter to remove
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder removePropertyFilters(PropertyFilter... filters);
+
+ /**
+ * Removes the given PropertyFilter instances, if existing. The order of the remaining
+ * filters is preserved.
+ *
+ * @param filters the filter to remove
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters);
+
+ /**
+ * This method can be used for adding {@link PropertyConverter}s.
+ * Converters are added at the end after any existing converters.
+ * For converters already registered for the current target type the
+ * method has no effect.
+ *
+ * @param typeToConvert the type for which the converters is for
+ * @param propertyConverters the PropertyConverters to add for this type
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... propertyConverters);
+
+ /**
+ * This method can be used for adding {@link PropertyConverter}s.
+ * Converters are added at the end after any existing converters.
+ * For converters already registered for the current target type the
+ * method has no effect.
+ *
+ * @param typeToConvert the type for which the converters is for
+ * @param propertyConverters the PropertyConverters to add for this type
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> propertyConverters);
+
+ /**
+ * Add all registered (default) property converters to the context built.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addDefaultPropertyConverters();
+
+ /**
+ * Removes the given PropertyConverter instances for the given type,
+ * if existing.
+ *
+ * @param typeToConvert the type which the converters is for
+ * @param propertyConverters the converters to remove
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... propertyConverters);
+
+ /**
+ * Removes the given PropertyConverter instances for the given type,
+ * if existing.
+ *
+ * @param typeToConvert the type which the converters is for
+ * @param propertyConverters the converters to remove
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> propertyConverters);
+
+ /**
+ * Removes all converters for the given type, which actually renders a given type
+ * unsupported for type conversion.
+ *
+ * @param typeToConvert the type which the converters is for
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert);
+
+ /**
+ * Sorts the current registered property sources using the given comparator.
+ *
+ * NOTE: property sources at the beginning have minimal significance.
+ *
+ * @param comparator the comparator to be used, not {@code null}.
+ * @return this instance for chaining.
+ */
+ ConfigurationContextBuilder sortPropertySources(Comparator<PropertySource> comparator);
+
+ /**
+ * Sorts the current registered property filters using the given comparator.
+ *
+ * NOTE: property filters at the beginning have minimal significance.
+ *
+ * @param comparator the comparator to be used, not {@code null}.
+ * @return this instance for chaining.
+ */
+ ConfigurationContextBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator);
+
+ /**
+ * Sets the {@link PropertyValueCombinationPolicy} used to evaluate the final
+ * property values.
+ *
+ * @param policy the {@link PropertyValueCombinationPolicy} used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy);
+
+ /**
+ * Builds a new {@link ConfigurationContext} based on the data in this builder. The ordering of property
+ * sources and property filters is not changed, regardless of their ordinals. For ensure a certain
+ * ordering/significance call {@link #sortPropertyFilter(Comparator)} and/or {@link #sortPropertySources(Comparator)}
+ * before building the context.
+ *
+ * @return the final context to be used to create a configuration.
+ * @see org.apache.tamaya.ConfigurationProvider#createConfiguration(ConfigurationContext)
+ */
+ ConfigurationContext build();
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java
new file mode 100644
index 0000000..fb93ab4
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.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 org.apache.tamaya.Configuration;
+
+/**
+ * SPI that must be implemented to provide the component that manages all {@link org.apache.tamaya.Configuration}
+ * instances in a system. In SE this may be a true singleton containing exact one {@link org.apache.tamaya.Configuration}
+ * instance, whereas in Java EE and other more complex environments instances may be returned depending the current
+ * runtime context.
+ */
+public interface ConfigurationProviderSpi {
+
+ /**
+ * Access the current {@link org.apache.tamaya.Configuration}.
+ *
+ * @return the current {@link org.apache.tamaya.Configuration} instance, never null.
+ */
+ Configuration getConfiguration();
+
+ /**
+ * Create a {@link Configuration} instance using the given context. The configuration
+ * created hereby must respect the artifacts provided by its context (property sources,
+ * filters, converters, policies etc), including their ordering and significance.
+ * @param context the context to be used, not {@code null}.
+ * @return the corresponding configuration instance.
+ */
+ Configuration createConfiguration(ConfigurationContext context);
+
+ /**
+ * Creates a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder} instance.
+ *
+ * @return a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder}, never null.
+ * @deprecated Will be removed
+ */
+ @Deprecated
+ ConfigurationContextBuilder getConfigurationContextBuilder();
+
+ /**
+ * Creates a new {@link org.apache.tamaya.spi.ConfigurationBuilder} instance.
+ *
+ * @return a new {@link org.apache.tamaya.spi.ConfigurationBuilder}, never null.
+ */
+ ConfigurationBuilder getConfigurationBuilder();
+
+ /**
+ * This method allows to replace the current {@link org.apache.tamaya.Configuration} with a new
+ * instance. This can be used to update the configuration with a new one, e.g. because some of the
+ * data has changed and must be updated. It is the responsibility of the ConfigurationProvider to trigger
+ * corresponding update events for the current {@link org.apache.tamaya.Configuration}.
+ *
+ * @param config the new Configuration to be applied.
+ * @throws java.lang.UnsupportedOperationException if the current provider is read-only.
+ */
+ void setConfiguration(Configuration config);
+
+ /**
+ * Method that allows to determine if a new {@link org.apache.tamaya.Configuration} can be applied
+ * programmatically.
+ *
+ * @return true, if {@link #setConfiguration(org.apache.tamaya.Configuration)} is supported
+ * by the current implementation.
+ * @see #setConfiguration(org.apache.tamaya.Configuration)
+ */
+ default boolean isConfigurationSettable(){
+ return true;
+ }
+
+ /**
+ * Get access to the current {@link ConfigurationContext}.
+ *
+ * @return the current {@link ConfigurationContext}, never null.
+ * @deprecated Will be removed in favour of {@link Configuration#getContext()}.
+ */
+ @Deprecated
+ default ConfigurationContext getConfigurationContext(){
+ return getConfiguration().getContext();
+ }
+
+ /**
+ * This method allows to replace the current {@link org.apache.tamaya.spi.ConfigurationContext} with a new
+ * instance. This can be used to update the context with a new one, e.g. because some of the configuration
+ * data has changed and must be updated. It is the responsibility of the ConfigurationProvider to trigger
+ * corresponding update event for the current {@link org.apache.tamaya.spi.ConfigurationContext} or
+ * {@link org.apache.tamaya.Configuration}.
+ *
+ * @param context the new ConfigurationContext to be applied.
+ * @throws java.lang.UnsupportedOperationException if the current provider is read-only.
+ * @deprecated use {@link #setConfiguration(Configuration)}
+ */
+ @Deprecated
+ default void setConfigurationContext(ConfigurationContext context){
+ setConfiguration(createConfiguration(context));
+ }
+
+ /**
+ * Method that allows to determine if a new {@link org.apache.tamaya.spi.ConfigurationContext} can be applied
+ * programmatically.
+ *
+ * @return true, if {@link #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)} is supported
+ * by the current implementation.
+ * @see #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)
+ * @deprecated use {@link #isConfigurationSettable()}
+ */
+ @Deprecated
+ default boolean isConfigurationContextSettable(){
+ return isConfigurationSettable();
+ }
+
+
+}
[3/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Posted by an...@apache.org.
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 >
+ * = 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();
+ }
+}
[4/7] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySourceProvider.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySourceProvider.java
new file mode 100644
index 0000000..1becb50
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySourceProvider.java
@@ -0,0 +1,114 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+
+import java.util.*;
+
+/**
+ * A Buildable property source.
+ */
+public class BuildablePropertySourceProvider implements PropertySourceProvider{
+
+ private List<PropertySource> sources = new ArrayList<>();
+
+ @Override
+ public Collection<PropertySource> getPropertySources() {
+ return Collections.unmodifiableCollection(sources);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BuildablePropertySourceProvider that = (BuildablePropertySourceProvider) o;
+
+ return sources.equals(that.sources);
+ }
+
+ @Override
+ public int hashCode() {
+ return sources.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "BuildablePropertySourceProvider{" +
+ "sources=" + sources +
+ '}';
+ }
+
+ /**
+ * Builder builder.
+ *
+ * @return the builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+
+
+ /**
+ * The type Builder.
+ */
+ public static final class Builder {
+ private List<PropertySource> sources = new ArrayList<>();
+
+ private Builder() {
+ }
+
+ /**
+ * With propertySources.
+ *
+ * @param propertySources the propertySources
+ * @return the builder
+ */
+ public Builder withPropertySourcs(PropertySource... propertySources) {
+ this.sources.addAll(Arrays.asList(propertySources));
+ return this;
+ }
+
+ /**
+ * With property sources builder.
+ *
+ * @param sources the property sources
+ * @return the builder
+ */
+ public Builder withPropertySourcs(Collection<PropertySource> sources) {
+ this.sources.addAll(sources);
+ return this;
+ }
+
+ /**
+ * Build buildable property source.
+ *
+ * @return the buildable property source
+ */
+ public BuildablePropertySourceProvider build() {
+ BuildablePropertySourceProvider buildablePropertySource = new BuildablePropertySourceProvider();
+ buildablePropertySource.sources.addAll(this.sources);
+ return buildablePropertySource;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java
new file mode 100644
index 0000000..a83722f
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java
@@ -0,0 +1,137 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.*;
+
+/**
+ * PropertySource that allows to add the programs main arguments as configuration entries. Unix syntax using '--' and
+ * '-' params is supported.
+ */
+public class CLIPropertySource extends BasePropertySource {
+
+ /** The original main arguments. */
+ private static String[] args = new String[0];
+
+ /** The map of parsed main arguments. */
+ private static Map<String,PropertyValue> mainArgs;
+
+ /** Initializes the initial state. */
+ static{
+ initMainArgs(args);
+ }
+
+ /**
+ * Creates a new instance.
+ */
+ public CLIPropertySource(){
+ this((String[])null);
+ }
+
+ /**
+ * Creates a new instance, allows optionally to pass the main arguments.
+ * @param args the args, or null.
+ */
+ public CLIPropertySource(String... args){
+ super("CLI");
+ if(args!=null){
+ initMainArgs(args);
+ }
+ }
+
+ /**
+ * Creates a new instance, allows optionally to pass the main arguments.
+ * @param args the args, or null.
+ * @param ordinal the ordinal to be applied.
+ */
+ public CLIPropertySource(int ordinal, String... args){
+ if(args!=null){
+ initMainArgs(args);
+ }
+ setOrdinal(ordinal);
+ }
+
+
+
+ /**
+ * Configure the main arguments, hereby parsing and mapping the main arguments into
+ * configuration propertiesi as key-value pairs.
+ * @param args the main arguments, not null.
+ */
+ public static void initMainArgs(String... args){
+ CLIPropertySource.args = Objects.requireNonNull(args);
+ // TODO is there a way to figure out the args?
+ String argsProp = System.getProperty("main.args");
+ if(argsProp!=null){
+ CLIPropertySource.args = argsProp.split("\\s");
+ }
+ Map<String,String> result = null;
+ if(CLIPropertySource.args==null){
+ result = Collections.emptyMap();
+ }else{
+ result = new HashMap<>();
+ String prefix = System.getProperty("main.args.prefix");
+ if(prefix==null){
+ prefix="";
+ }
+ String key = null;
+ for(String arg:CLIPropertySource.args){
+ if(arg.startsWith("--")){
+ arg = arg.substring(2);
+ int index = arg.indexOf("=");
+ if(index>0){
+ key = arg.substring(0,index).trim();
+ result.put(prefix+key, arg.substring(index+1).trim());
+ key = null;
+ }else{
+ result.put(prefix+arg, arg);
+ }
+ }else if(arg.startsWith("-")){
+ key = arg.substring(1);
+ }else{
+ if(key!=null){
+ result.put(prefix+key, arg);
+ key = null;
+ }else{
+ result.put(prefix+arg, arg);
+ }
+ }
+ }
+ }
+ Map<String,PropertyValue> finalProps = new HashMap<>();
+ for(Map.Entry<String,String> en:result.entrySet()) {
+ finalProps.put(en.getKey(),
+ PropertyValue.of(en.getKey(), en.getValue(), "main-args"));
+ }
+ CLIPropertySource.mainArgs = Collections.unmodifiableMap(finalProps);
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return Collections.unmodifiableMap(mainArgs);
+ }
+
+ @Override
+ protected String toStringValues() {
+ return super.toStringValues() +
+ " args=" + Arrays.toString(args) + '\n';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java
new file mode 100644
index 0000000..920f37b
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java
@@ -0,0 +1,287 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>{@link PropertySource} to access environment variables via Tamaya
+ * which are set via {@code export VARIABLE=value} on UNIX systems or
+ * {@code set VARIABLE=value} on Windows systems.</p>
+ *
+ * <p>Using the {@linkplain EnvironmentPropertySource} without any
+ * additional configuration gives access to all existing environment
+ * variables available to the Java process Tamaya is running in.</p>
+ *
+ * <h1>Simple usage example</h1>
+ *
+ * <pre>
+ * $ export OPS_MODE=production
+ * $ export COLOR=false
+ * $ java -jar application.jar
+ * </pre>
+ *
+ * <p>To access {@code OPS_MODE} and {@code COLOR} with the following code
+ * fragment could be used:</p>
+ *
+ * <pre>
+ * PropertySource ps = new EnvironmentPropertySource();
+ * PropertyValue opsMode = ps.get("OPS_MODE");
+ * PropertyValue color = ps.get("COLOR");
+ * </pre>
+ *
+ * <h1>Application specific environmet variables with prefix</h1>
+ *
+ * <p>Given the case where to instances of the same application are running on
+ * a single machine but need different values for the environment variable
+ * {@code CUSTOMER}. The {@linkplain EnvironmentPropertySource} allows you
+ * to prefix the environment variable with an application specific prefix
+ * and to access it by the non-prefixed variable name.</p>
+ *
+ * <pre>
+ * $ export CUSTOMER=none
+ * $ export a81.CUSTOMER=moon
+ * $ export b78.CUSTOMER=luna
+ * </pre>
+ *
+ * <p>Given an environment with these tree variables the application running
+ * for the customer called Moon could be started with the following command:</p>
+ *
+ * <pre>
+ * $ java -Dtamaya.envprops.prefix=a81 -jar application.jar
+ * </pre>
+ *
+ * <p>The application specific value can now be accessed from the code of the
+ * application like this:</p>
+ *
+ * <pre>
+ * PropertySource ps = new EnvironmentPropertySource();
+ * PropertyValue pv = ps.get("CUSTOMER");
+ * System.out.println(pv.getValue());
+ * </pre>
+ *
+ * <p>The output of application would be {@code moon}.</p>
+ *
+ * <h1>Disabling the access to environment variables</h1>
+ *
+ * <p>The access to environment variables could be simply
+ * disabled by the setting the systemproperty {@code tamaya.envprops.disable}
+ * or {@code tamaya.defaults.disable} to {@code true}.</p>
+ */
+public class EnvironmentPropertySource extends BasePropertySource {
+ private static final String TAMAYA_ENVPROPS_PREFIX = "tamaya.envprops.prefix";
+ private static final String TAMAYA_ENVPROPS_DISABLE = "tamaya.envprops.disable";
+ private static final String TAMAYA_DEFAULT_DISABLE = "tamaya.defaults.disable";
+
+ /**
+ * Default ordinal for {@link EnvironmentPropertySource}
+ */
+ public static final int DEFAULT_ORDINAL = 300;
+
+ /**
+ * Prefix that allows environment properties to virtually be mapped on specified sub section.
+ */
+ private String prefix;
+
+ /**
+ * If true, this property source does not return any properties. This is useful since this
+ * property source is applied by default, but can be switched off by setting the
+ * {@code tamaya.envprops.disable} system/environment property to {@code true}.
+ */
+ private boolean disabled = false;
+
+ private SystemPropertiesProvider propertiesProvider = new SystemPropertiesProvider();
+
+ /**
+ * Creates a new instance. Also initializes the {@code prefix} and {@code disabled} properties
+ * from the system-/ environment properties:
+ * <pre>
+ * tamaya.envprops.prefix
+ * tamaya.envprops.disable
+ * </pre>
+ */
+ public EnvironmentPropertySource(){
+ initFromSystemProperties();
+ }
+
+ /**
+ * Initializes the {@code prefix} and {@code disabled} properties from the system-/
+ * environment properties:
+ * <pre>
+ * tamaya.envprops.prefix
+ * tamaya.envprops.disable
+ * </pre>
+ */
+ private void initFromSystemProperties() {
+ String value = System.getProperty("tamaya.envprops.prefix");
+ if(value==null){
+ prefix = System.getenv("tamaya.envprops.prefix");
+ }
+ value = System.getProperty("tamaya.envprops.disable");
+ if(value==null){
+ value = System.getenv("tamaya.envprops.disable");
+ }
+ if(value==null){
+ value = System.getProperty("tamaya.defaults.disable");
+ }
+ if(value==null){
+ value = System.getenv("tamaya.defaults.disable");
+ }
+ if(value!=null && !value.isEmpty()) {
+ this.disabled = Boolean.parseBoolean(value);
+ }
+ }
+
+ /**
+ * Creates a new instance using a fixed ordinal value.
+ * @param ordinal the ordinal number.
+ */
+ public EnvironmentPropertySource(int ordinal){
+ this(null, ordinal);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the prefix to be used, or null.
+ * @param ordinal the ordinal to be used.
+ */
+ public EnvironmentPropertySource(String prefix, int ordinal){
+ super("environment-properties");
+ this.prefix = prefix;
+ setOrdinal(ordinal);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the prefix to be used, or null.
+ */
+ public EnvironmentPropertySource(String prefix){
+ this.prefix = prefix;
+ }
+
+ @Override
+ public int getDefaultOrdinal() {
+ return DEFAULT_ORDINAL;
+ }
+
+ @Override
+ public String getName() {
+ if (isDisabled()) {
+ return "environment-properties(disabled)";
+ }
+ return "environment-properties";
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ if (isDisabled()) {
+ return null;
+ }
+
+ String effectiveKey = hasPrefix() ? getPrefix() + "." + key
+ : key;
+
+ String value = getPropertiesProvider().getenv(effectiveKey);
+
+ return PropertyValue.of(key, value, getName());
+ }
+
+ private boolean hasPrefix() {
+ return null != prefix;
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ if(disabled){
+ return Collections.emptyMap();
+ }
+ String prefix = this.prefix;
+ if(prefix==null) {
+ Map<String, PropertyValue> entries = new HashMap<>(System.getenv().size());
+ for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
+ entries.put(entry.getKey(), PropertyValue.of(entry.getKey(), entry.getValue(), getName()));
+ }
+ return entries;
+ }else{
+ Map<String, PropertyValue> entries = new HashMap<>(System.getenv().size());
+ for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
+ entries.put(prefix + entry.getKey(), PropertyValue.of(prefix + entry.getKey(), entry.getValue(), getName()));
+ }
+ return entries;
+ }
+ }
+
+
+ @Override
+ protected String toStringValues() {
+ return super.toStringValues() +
+ " prefix=" + prefix + '\n' +
+ " disabled=" + disabled + '\n';
+ }
+
+ void setPropertiesProvider(SystemPropertiesProvider spp) {
+ propertiesProvider = spp;
+ initFromSystemProperties();
+ }
+
+ SystemPropertiesProvider getPropertiesProvider() {
+ return propertiesProvider;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ /**
+ * <p>Provides access to the system properties used to configure
+ * {@linkplain EnvironmentPropertySource}.</p>
+ *
+ * <p>This implementation delegates all property lookups
+ * to {@linkplain System#getProperty(String)}.</p>
+ */
+ static class SystemPropertiesProvider {
+ String getEnvPropsPrefix() {
+ return System.getenv(TAMAYA_ENVPROPS_PREFIX);
+ }
+
+ String getEnvPropsDisable() {
+ return System.getenv(TAMAYA_ENVPROPS_DISABLE);
+ }
+
+ String getDefaultsDisable() {
+ return System.getenv(TAMAYA_DEFAULT_DISABLE);
+ }
+
+ String getenv(String name) {
+ return System.getenv(name);
+ }
+
+ Map<String, String> getenv() {
+ return System.getenv();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java
new file mode 100644
index 0000000..92f520e
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java
@@ -0,0 +1,134 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.spisupport.PropertySourceComparator;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
+import static java.lang.String.format;
+import static java.lang.Thread.currentThread;
+
+/**
+ * Provider which reads all {@value DEFAULT_SIMPLE_PROPERTIES_FILE_NAME} and
+ * {@value DEFAULT_XML_PROPERTIES_FILE_NAME} files found in the
+ * classpath. By setting
+ * {@code tamaya.defaultprops.disable} or {@code tamaya.defaults.disable}
+ * as system or environment property this feature can be disabled.
+ */
+public class JavaConfigurationPropertySource extends BasePropertySource {
+ /**
+ * Default location in the classpath, where Tamaya looks for simple line based configuration by default.
+ */
+ public static final String DEFAULT_SIMPLE_PROPERTIES_FILE_NAME="META-INF/javaconfiguration.properties";
+
+ /**
+ * Default location in the classpath, where Tamaya looks for XML based configuration by default.
+ */
+ public static final String DEFAULT_XML_PROPERTIES_FILE_NAME = "META-INF/javaconfiguration.xml";
+
+ private static final int DEFAULT_ORDINAL = 900;
+
+ private boolean enabled = evaluateEnabled();
+
+ public JavaConfigurationPropertySource(){
+ super("resource:META-INF/javaconfiguration.*", DEFAULT_ORDINAL);
+ }
+
+ private boolean evaluateEnabled() {
+ String value = System.getProperty("tamaya.defaultprops.disable");
+ if(value==null){
+ value = System.getenv("tamaya.defaultprops.disable");
+ }
+ if(value==null){
+ value = System.getProperty("tamaya.defaults.disable");
+ }
+ if(value==null){
+ value = System.getenv("tamaya.defaults.disable");
+ }
+ if(value==null){
+ return true;
+ }
+ return value.isEmpty() || !Boolean.parseBoolean(value);
+ }
+
+ private List<PropertySource> getPropertySources() {
+ List<PropertySource> propertySources = new ArrayList<>();
+ propertySources.addAll(loadPropertySourcesByName(DEFAULT_SIMPLE_PROPERTIES_FILE_NAME));
+ propertySources.addAll(loadPropertySourcesByName(DEFAULT_XML_PROPERTIES_FILE_NAME));
+ Collections.sort(propertySources, PropertySourceComparator.getInstance());
+ return propertySources;
+ }
+
+ private Collection<? extends PropertySource> loadPropertySourcesByName(String filename) {
+ List<PropertySource> propertySources = new ArrayList<>();
+ Enumeration<URL> propertyLocations;
+ try {
+ propertyLocations = ServiceContextManager.getServiceContext()
+ .getResources(filename, currentThread().getContextClassLoader());
+ } catch (IOException e) {
+ String msg = format("Error while searching for %s", filename);
+
+ throw new ConfigException(msg, e);
+ }
+
+ while (propertyLocations.hasMoreElements()) {
+ URL currentUrl = propertyLocations.nextElement();
+ SimplePropertySource sps = new SimplePropertySource(currentUrl);
+
+ propertySources.add(sps);
+ }
+
+ return propertySources;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled){
+ this.enabled = enabled;
+ }
+
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ if (!isEnabled()) {
+ return Collections.emptyMap();
+ }
+ Map<String,PropertyValue> result = new HashMap<>();
+ for(PropertySource ps:getPropertySources()){
+ result.putAll(ps.getProperties());
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "JavaConfigurationPropertySource{" +
+ "enabled=" + enabled +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java
new file mode 100644
index 0000000..0cabb35
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java
@@ -0,0 +1,102 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Simple PropertySource implementation that just takes a Map and an (optional) priority.
+ * Optionally the entries passed can be mapped to a different rootContext.
+ */
+public class MapPropertySource extends BasePropertySource {
+
+ /**
+ * The current properties.
+ */
+ private final Map<String, PropertyValue> props = new HashMap<>();
+
+ /**
+ * Creates a new instance, hereby using the default mechanism for evaluating the property source's
+ * priority.
+ *
+ * @param name unique name of this source.
+ * @param props the properties
+ */
+ public MapPropertySource(String name, Map<String, String> props) {
+ this(name, props, null);
+ }
+
+ /**
+ * Creates a new instance, hereby using the default mechanism for evaluating the property source's
+ * priority, but applying a custom mapping {@code prefix} to the entries provided.
+ *
+ * @param name unique name of this source.
+ * @param props the properties
+ * @param prefix the prefix context mapping, or null (for no mapping).
+ */
+ public MapPropertySource(String name, Map<String, String> props, String prefix) {
+ super(name);
+ if (prefix == null) {
+ for (Map.Entry<String, String> en : props.entrySet()) {
+ this.props.put(en.getKey(),
+ PropertyValue.of(en.getKey(), en.getValue(), name));
+ }
+ } else {
+ for (Map.Entry<String, String> en : props.entrySet()) {
+ this.props.put(prefix + en.getKey(),
+ PropertyValue.of(prefix + en.getKey(), en.getValue(), name));
+ }
+ }
+ }
+
+ /**
+ * Creates a new instance, hereby using the default mechanism for evaluating the property source's
+ * priority, but applying a custom mapping {@code rootContext} to the entries provided.
+ *
+ * @param name unique name of this source.
+ * @param props the properties
+ * @param prefix the prefix context mapping, or null (for no mapping).
+ */
+ public MapPropertySource(String name, Properties props, String prefix) {
+ this(name, getMap(props), prefix);
+ }
+
+ /**
+ * Simple method to convert Properties into a Map instance.
+ * @param props the properties, not null.
+ * @return the corresponding Map instance.
+ */
+ public static Map<String, String> getMap(Properties props) {
+ Map<String, String> result = new HashMap<>();
+ for (Map.Entry en : props.entrySet()) {
+ result.put(en.getKey().toString(), en.getValue().toString());
+ }
+ return result;
+ }
+
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return Collections.unmodifiableMap(this.props);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java
new file mode 100644
index 0000000..27b6e4b
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java
@@ -0,0 +1,109 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Simple PropertySource, with a fixed ordinal that reads a .properties file from a given URL.
+ */
+public class PropertiesResourcePropertySource extends MapPropertySource {
+ /** The logger used. */
+ private static final Logger LOGGER = Logger.getLogger(PropertiesResourcePropertySource.class.getName());
+
+ /**
+ * Creates a new instance.
+ * @param url the resource URL, not null.
+ */
+ public PropertiesResourcePropertySource(URL url){
+ this(url, null);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the (optional) prefix context for mapping (prefixing) the properties loaded.
+ * @param url the resource URL, not null.
+ */
+ public PropertiesResourcePropertySource(URL url, String prefix){
+ super(url.toExternalForm(), loadProps(url), prefix);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the (optional) prefix context for mapping (prefixing) the properties loaded.
+ * @param path the resource path, not null.
+ */
+ public PropertiesResourcePropertySource(String path, String prefix){
+ super(path, loadProps(path, null), prefix);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the (optional) prefix context for mapping (prefixing) the properties loaded.
+ * @param path the resource path, not null.
+ */
+ public PropertiesResourcePropertySource(String path, String prefix, ClassLoader cl){
+ super(path, loadProps(path, cl), prefix);
+ }
+
+ /**
+ * Loads the properties using the JDK's Property loading mechanism.
+ * @param path the resource classpath, not null.
+ * @return the loaded properties.
+ */
+ private static Map<String, String> loadProps(String path, ClassLoader cl) {
+ if(cl==null){
+ cl = PropertiesResourcePropertySource.class.getClassLoader();
+ }
+ URL url = ServiceContextManager.getServiceContext().getResource(path, cl);
+ return loadProps(url);
+ }
+
+ /**
+ * Loads the properties using the JDK's Property loading mechanism.
+ * @param url the resource URL, not null.
+ * @return the loaded properties.
+ */
+ private static Map<String, String> loadProps(URL url) {
+ Map<String,String> result = new HashMap<>();
+ if(url!=null) {
+ try (InputStream is = url.openStream()) {
+ Properties props = new Properties();
+ props.load(is);
+ for (Map.Entry en : props.entrySet()) {
+ result.put(en.getKey().toString(), en.getValue().toString());
+ }
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING, "Failed to read properties from " + url, e);
+ }
+ }else{
+ LOGGER.log(Level.WARNING, "No properties found at " + url);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java
new file mode 100644
index 0000000..070a564
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java
@@ -0,0 +1,284 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+/**
+ * Simple implementation of a {@link org.apache.tamaya.spi.PropertySource} for
+ * simple property files and XML property files.
+ */
+public class SimplePropertySource extends BasePropertySource {
+
+ private static final Logger LOG = Logger.getLogger(SimplePropertySource.class.getName());
+
+ /**
+ * The current properties.
+ */
+ private Map<String, PropertyValue> properties = new HashMap<>();
+
+ /**
+ * Creates a new Properties based PropertySource based on the given URL.
+ *
+ * @param propertiesLocation the URL encoded location, not null.
+ */
+ public SimplePropertySource(File propertiesLocation) {
+ super(propertiesLocation.toString(), 0);
+ try {
+ this.properties = load(propertiesLocation.toURI().toURL());
+ } catch (IOException e) {
+ throw new ConfigException("Failed to load properties from " + propertiesLocation, e);
+ }
+ }
+
+ /**
+ * Creates a new Properties based PropertySource based on the given URL.
+ *
+ * @param propertiesLocation the URL encoded location, not null.
+ */
+ public SimplePropertySource(URL propertiesLocation) {
+ super(propertiesLocation.toString(), 0);
+ this.properties = load(Objects.requireNonNull(propertiesLocation));
+ }
+
+ /**
+ * Creates a new Properties based PropertySource.
+ *
+ * @param name the property source name, not null.
+ * @param properties the properties, not null
+ * @param defaultOrdinal the default ordinal
+ */
+ public SimplePropertySource(String name, Map<String, String> properties, int defaultOrdinal){
+ super(name, defaultOrdinal);
+ for(Map.Entry<String,String> en: properties.entrySet()) {
+ this.properties.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), name));
+ }
+ }
+
+ /**
+ * Creates a new Properties based PropertySource based on the given properties map.
+ *
+ * @param name the name, not null.
+ * @param properties the properties, not null.
+ */
+ public SimplePropertySource(String name, Map<String, String> properties) {
+ this(name, properties, 0);
+ }
+
+ /**
+ * Creates a new Properties based PropertySource based on the given URL.
+ *
+ * @param name The property source name
+ * @param propertiesLocation the URL encoded location, not null.
+ */
+ public SimplePropertySource(String name, URL propertiesLocation) {
+ super(name, 0);
+ this.properties = load(propertiesLocation);
+ }
+
+ private SimplePropertySource(Builder builder) {
+ properties = builder.properties;
+ if(builder.defaultOrdinal!=null){
+ setDefaultOrdinal(builder.defaultOrdinal);
+ }
+ if(builder.ordinal!=null){
+ setOrdinal(builder.ordinal);
+ }
+ setName(builder.name);
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return this.properties;
+ }
+
+ /**
+ * loads the Properties from the given URL
+ *
+ * @param propertiesFile {@link URL} to load Properties from
+ * @return loaded {@link Properties}
+ * @throws IllegalStateException in case of an error while reading properties-file
+ */
+ private static Map<String, PropertyValue> load(URL propertiesFile) {
+ boolean isXML = isXMLPropertieFiles(propertiesFile);
+
+ Map<String, PropertyValue> properties = new HashMap<>();
+ try (InputStream stream = propertiesFile.openStream()) {
+ Properties props = new Properties();
+ if (stream != null) {
+ if (isXML) {
+ props.loadFromXML(stream);
+ } else {
+ props.load(stream);
+ }
+ }
+ String source = propertiesFile.toString();
+ for (String key : props.stringPropertyNames()) {
+ properties.put(key, PropertyValue.of(key, props.getProperty(key), source));
+ }
+ } catch (IOException e) {
+ throw new ConfigException("Error loading properties from " + propertiesFile, e);
+ }
+
+ return properties;
+ }
+
+ private static boolean isXMLPropertieFiles(URL url) {
+ return url.getFile().endsWith(".xml");
+ }
+
+
+ /**
+ * {@code SimplePropertySource} builder static inner class.
+ */
+ public static final class Builder {
+ private String name;
+ private Integer defaultOrdinal;
+ private Integer ordinal;
+ private Map<String, PropertyValue> properties = new HashMap<>();
+
+ private Builder() {
+ }
+
+ /**
+ * Sets the {@code name} to a new UUID and returns a reference to this Builder so that the methods
+ * can be chained together.
+ *
+ * @return a reference to this Builder
+ */
+ public Builder withUuidName() {
+ this.name = UUID.randomUUID().toString();
+ return this;
+ }
+
+ /**
+ * Sets the {@code name} and returns a reference to this Builder so that the methods
+ * can be chained together.
+ *
+ * @param val the {@code name} to set, not null.
+ * @return a reference to this Builder
+ */
+ public Builder withName(String val) {
+ this.name = Objects.requireNonNull(name);
+ return this;
+ }
+
+ /**
+ * Sets the {@code ordinal} and returns a reference to this Builder so that the methods
+ * can be chained together.
+ *
+ * @param val the {@code ordinal} to set
+ * @return a reference to this Builder
+ */
+ public Builder withOrdinal(int val) {
+ this.ordinal = val;
+ return this;
+ }
+
+ /**
+ * Sets the {@code defaultOrdinal} and returns a reference to this Builder so that the methods
+ * can be chained together.
+ *
+ * @param val the {@code defaultOrdinal} to set
+ * @return a reference to this Builder
+ */
+ public Builder withDefaultOrdinal(int val) {
+ this.defaultOrdinal = val;
+ return this;
+ }
+
+ /**
+ * Reads the {@code properties} from the given resource and returns a reference
+ * to this Builder so that the methods can be chained together.
+ *
+ * @param resource the {@code resource} to read
+ * @return a reference to this Builder
+ */
+ public Builder withProperties(URL resource) {
+ this.properties.putAll(load(resource));
+ return this;
+ }
+
+ /**
+ * Reads the {@code properties} from the given resource and returns a reference
+ * to this Builder so that the methods can be chained together.
+ *
+ * @param file the {@code file} to read from (xml or properties format).
+ * @return a reference to this Builder
+ */
+ public Builder withProperties(File file) {
+ try {
+ this.properties.putAll(load(file.toURI().toURL()));
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Failed to read file: " + file, e);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the {@code properties} and returns a reference to this Builder so that the methods can be chained together.
+ *
+ * @param val the {@code properties} to set
+ * @return a reference to this Builder
+ */
+ public Builder withProperties(Map<String, String> val) {
+ for(Map.Entry<String,String> en: val.entrySet()) {
+ this.properties.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), name));
+ }
+ return this;
+ }
+
+ /**
+ * Sets the {@code properties} and returns a reference to this Builder so that the methods can be chained together.
+ *
+ * @param val the {@code properties} to set
+ * @return a reference to this Builder
+ */
+ public Builder withProperty(String key, String val) {
+ this.properties.put(key, PropertyValue.of(key, val, name));
+ return this;
+ }
+
+ /**
+ * Returns a {@code SimplePropertySource} built from the parameters previously set.
+ *
+ * @return a {@code SimplePropertySource} built with parameters of this {@code SimplePropertySource.Builder}
+ */
+ public SimplePropertySource build() {
+ return new SimplePropertySource(this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java
new file mode 100644
index 0000000..cfc60bb
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java
@@ -0,0 +1,199 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * This {@link org.apache.tamaya.spi.PropertySource} manages the system properties. You can disable this feature by
+ * setting {@code tamaya.envprops.disable} or {@code tamaya.defaults.disable}.
+ */
+public class SystemPropertySource extends BasePropertySource {
+
+ /**
+ * default ordinal used.
+ */
+ public static final int DEFAULT_ORDINAL = 1000;
+
+ private volatile Map<String,PropertyValue> cachedProperties;
+
+ /**
+ * previous System.getProperties().hashCode()
+ * so we can check if we need to reload
+ */
+ private volatile int previousHash;
+
+ /**
+ * Prefix that allows system properties to virtually be mapped on specified sub section.
+ */
+ private String prefix;
+
+ /**
+ * If true, this property source does not return any properties. This is useful since this
+ * property source is applied by default, but can be switched off by setting the
+ * {@code tamaya.envprops.disable} system/environment property to {@code true}.
+ */
+ private boolean disabled = false;
+
+ /**
+ * Creates a new instance. Also initializes the {@code prefix} and {@code disabled} properties
+ * from the system-/ environment properties:
+ * <pre>
+ * tamaya.envprops.prefix
+ * tamaya.envprops.disable
+ * </pre>
+ */
+ public SystemPropertySource(){
+ super("system-properties", DEFAULT_ORDINAL);
+ initFromSystemProperties();
+ if(!disabled){
+ cachedProperties = Collections.unmodifiableMap(loadProperties());
+ }
+ }
+
+ /**
+ * Initializes the {@code prefix} and {@code disabled} properties from the system-/
+ * environment properties:
+ * <pre>
+ * tamaya.envprops.prefix
+ * tamaya.envprops.disable
+ * </pre>
+ */
+ private void initFromSystemProperties() {
+ String value = System.getProperty("tamaya.sysprops.prefix");
+ if(value==null){
+ prefix = System.getenv("tamaya.sysprops.prefix");
+ }
+ value = System.getProperty("tamaya.sysprops.disable");
+ if(value==null){
+ value = System.getenv("tamaya.sysprops.disable");
+ }
+ if(value==null){
+ value = System.getProperty("tamaya.defaults.disable");
+ }
+ if(value==null){
+ value = System.getenv("tamaya.defaults.disable");
+ }
+ if(value!=null && !value.isEmpty()) {
+ this.disabled = Boolean.parseBoolean(value);
+ }
+ }
+
+ /**
+ * Creates a new instance using a fixed ordinal value.
+ * @param ordinal the ordinal number.
+ */
+ public SystemPropertySource(int ordinal){
+ this(null, ordinal);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the prefix to be used, or null.
+ * @param ordinal the ordinal to be used.
+ */
+ public SystemPropertySource(String prefix, int ordinal){
+ this.prefix = prefix;
+ setOrdinal(ordinal);
+ }
+
+ /**
+ * Creates a new instance.
+ * @param prefix the prefix to be used, or null.
+ */
+ public SystemPropertySource(String prefix){
+ this.prefix = prefix;
+ }
+
+
+ private Map<String, PropertyValue> loadProperties() {
+ Properties sysProps = System.getProperties();
+ previousHash = System.getProperties().hashCode();
+ final String prefix = this.prefix;
+ Map<String, PropertyValue> entries = new HashMap<>();
+ for (Map.Entry<Object,Object> entry : sysProps.entrySet()) {
+ if(entry.getKey() instanceof String && entry.getValue() instanceof String) {
+ if (prefix == null) {
+ entries.put((String) entry.getKey(),
+ PropertyValue.of((String) entry.getKey(),
+ (String) entry.getValue(),
+ getName()));
+ } else {
+ entries.put(prefix + entry.getKey(),
+ PropertyValue.of(prefix + entry.getKey(),
+ (String) entry.getValue(),
+ getName()));
+ }
+ }
+ }
+ return entries;
+ }
+
+ @Override
+ public String getName() {
+ if(disabled){
+ return super.getName() + "(disabled)";
+ }
+ return super.getName();
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ if(disabled){
+ return null;
+ }
+ String prefix = this.prefix;
+ if(prefix==null) {
+ return PropertyValue.of(key, System.getProperty(key), getName());
+ }
+ return PropertyValue.of(key, System.getProperty(key.substring(prefix.length())), getName());
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ if(disabled){
+ return Collections.emptyMap();
+ }
+ // only need to reload and fill our map if something has changed
+ // synchronization was removed, Instance was marked as volatile. In the worst case it
+ // is reloaded twice, but the values will be the same.
+ if (previousHash != System.getProperties().hashCode()) {
+ Map<String, PropertyValue> properties = loadProperties();
+ this.cachedProperties = Collections.unmodifiableMap(properties);
+ }
+ return this.cachedProperties;
+ }
+
+ @Override
+ public boolean isScannable() {
+ return true;
+ }
+
+ @Override
+ protected String toStringValues() {
+ return super.toStringValues() +
+ " prefix=" + prefix + '\n' +
+ " disabled=" + disabled + '\n';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySource.java
new file mode 100644
index 0000000..feaaf7b
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySource.java
@@ -0,0 +1,126 @@
+/*
+ * 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.propertysource;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spisupport.PropertySourceComparator;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Property source effectively managed by the configuration context, allowing resetting of ordinal and its
+ * delegate (e.g. in case of refresh).
+ */
+class WrappedPropertySource implements PropertySource{
+
+ private Integer ordinal;
+ private PropertySource delegate;
+ private long loaded = System.currentTimeMillis();
+
+ private WrappedPropertySource(PropertySource delegate) {
+ this(delegate, null);
+ }
+
+ private WrappedPropertySource(PropertySource delegate, Integer ordinal) {
+ this.delegate = Objects.requireNonNull(delegate);
+ this.ordinal = ordinal;
+ }
+
+ public static WrappedPropertySource of(PropertySource ps) {
+ if(ps instanceof WrappedPropertySource){
+ return (WrappedPropertySource)ps;
+ }
+ return new WrappedPropertySource(ps);
+ }
+
+ public static WrappedPropertySource of(PropertySource ps, Integer ordinal) {
+ if(ps instanceof WrappedPropertySource){
+ return new WrappedPropertySource(((WrappedPropertySource)ps).getDelegate(), ordinal);
+ }
+ return new WrappedPropertySource(ps, ordinal);
+ }
+
+ public int getOrdinal() {
+ if(this.ordinal!=null){
+ return this.ordinal;
+ }
+ return PropertySourceComparator.getOrdinal(delegate);
+ }
+
+ public void setOrdinal(Integer ordinal) {
+ this.ordinal = ordinal;
+ }
+
+ public void setDelegate(PropertySource delegate) {
+ this.delegate = Objects.requireNonNull(delegate);
+ this.loaded = System.currentTimeMillis();
+ }
+
+ @Override
+ public String getName() {
+ return delegate.getName();
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ return delegate.get(key);
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return delegate.getProperties();
+ }
+
+ @Override
+ public boolean isScannable() {
+ return delegate.isScannable();
+ }
+
+ public PropertySource getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof WrappedPropertySource)) return false;
+
+ WrappedPropertySource that = (WrappedPropertySource) o;
+
+ return getDelegate().getName().equals(that.getDelegate().getName());
+ }
+
+ @Override
+ public int hashCode() {
+ return getDelegate().getName().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "WrappedPropertySource{" +
+ "name=" + getName() +
+ ", ordinal=" + getOrdinal() +
+ ", scannable=" + isScannable() +
+ ", loadedAt=" + loaded +
+ ", delegate-class=" + delegate.getClass().getName() +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/package-info.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/package-info.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/package-info.java
new file mode 100644
index 0000000..21e5aec
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Contains internal implementations artifacts registered as services.
+ */
+package org.apache.tamaya.spisupport.propertysource;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/resources/tamaya-banner.txt
----------------------------------------------------------------------
diff --git a/code/compat/src/main/resources/tamaya-banner.txt b/code/compat/src/main/resources/tamaya-banner.txt
new file mode 100644
index 0000000..b4ceca4
--- /dev/null
+++ b/code/compat/src/main/resources/tamaya-banner.txt
@@ -0,0 +1,11 @@
+
+ █████╗ ██████╗ █████╗ ██████╗██╗ ██╗███████╗ ████████╗ █████╗ ███╗ ███╗ █████╗ ██╗ ██╗ █████╗
+██╔══██╗██╔══██╗██╔══██╗██╔════╝██║ ██║██╔════╝ ╚══██╔══╝██╔══██╗████╗ ████║██╔══██╗╚██╗ ██╔╝██╔══██╗
+███████║██████╔╝███████║██║ ███████║█████╗ ██║ ███████║██╔████╔██║███████║ ╚████╔╝ ███████║
+██╔══██║██╔═══╝ ██╔══██║██║ ██╔══██║██╔══╝ ██║ ██╔══██║██║╚██╔╝██║██╔══██║ ╚██╔╝ ██╔══██║
+██║ ██║██║ ██║ ██║╚██████╗██║ ██║███████╗ ██║ ██║ ██║██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║
+╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
+
+Apache Tamaya Configuration API: http://tamaya.incubator.apache.org
+
+
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/ConfigExceptionTest.java
----------------------------------------------------------------------
diff --git a/code/compat/src/test/java/org/apache/tamaya/ConfigExceptionTest.java b/code/compat/src/test/java/org/apache/tamaya/ConfigExceptionTest.java
new file mode 100644
index 0000000..fa7da0a
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/ConfigExceptionTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests instantiating {@link ConfigException}.
+ */
+public class ConfigExceptionTest {
+
+ @Test
+ public void testCreationMessage(){
+ ConfigException ex = new ConfigException("test");
+ assertNull(ex.getCause());
+ assertEquals(ex.getMessage(), "test");
+ }
+
+ @Test
+ public void testCreationMessageThrowable(){
+ Exception e = new IllegalStateException("blabla");
+ ConfigException ex = new ConfigException("test", e);
+ assertTrue(ex.getCause() == e);
+ assertEquals("test", ex.getMessage());
+ }
+
+}
\ 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/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/code/compat/src/test/java/org/apache/tamaya/ConfigurationTest.java b/code/compat/src/test/java/org/apache/tamaya/ConfigurationTest.java
new file mode 100644
index 0000000..ecbb75c
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/ConfigurationTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * Test class that tests the default methods implemented on {@link org.apache.tamaya.Configuration}. The provided
+ * {@link org.apache.tamaya.TestConfiguration} is implemeted with maximal use of the default methods.
+ */
+public class ConfigurationTest {
+
+ @Test
+ public void testget() throws Exception {
+ assertEquals(Boolean.TRUE, ConfigurationProvider.getConfiguration().get("booleanTrue", Boolean.class));
+ assertEquals(Boolean.FALSE, ConfigurationProvider.getConfiguration().get("booleanFalse", Boolean.class));
+ assertEquals((int)Byte.MAX_VALUE, (int)ConfigurationProvider.getConfiguration().get("byte", Byte.class));
+ assertEquals(Integer.MAX_VALUE, (int)ConfigurationProvider.getConfiguration().get("int", Integer.class));
+ assertEquals(Long.MAX_VALUE, (long)ConfigurationProvider.getConfiguration().get("long", Long.class));
+ assertEquals(Float.MAX_VALUE, (double)ConfigurationProvider.getConfiguration().get("float", Float.class), 0.0d);
+ assertEquals(Double.MAX_VALUE, ConfigurationProvider.getConfiguration().get("double", Double.class), 0.0d);
+ }
+
+ @Test
+ public void testGetBoolean() throws Exception {
+ assertTrue(ConfigurationProvider.getConfiguration().get("booleanTrue", Boolean.class));
+ assertFalse(ConfigurationProvider.getConfiguration().get("booleanFalse", Boolean.class));
+ assertFalse(ConfigurationProvider.getConfiguration().get("foorBar", Boolean.class));
+ }
+
+ @Test
+ public void testGetInteger() throws Exception {
+ assertEquals(Integer.MAX_VALUE,(int) ConfigurationProvider.getConfiguration().get("int", Integer.class));
+ }
+
+ @Test
+ public void testGetLong() throws Exception {
+ assertEquals(Long.MAX_VALUE,(long) ConfigurationProvider.getConfiguration().get("long", Long.class));
+ }
+
+ @Test
+ public void testGetDouble() throws Exception {
+ assertEquals(Double.MAX_VALUE,ConfigurationProvider.getConfiguration().get("double", Double.class), 0.0d);
+ }
+
+}
\ 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/TestConfiguration.java
----------------------------------------------------------------------
diff --git a/code/compat/src/test/java/org/apache/tamaya/TestConfiguration.java b/code/compat/src/test/java/org/apache/tamaya/TestConfiguration.java
new file mode 100644
index 0000000..a035467
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/TestConfiguration.java
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.TypeLiteral;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Test Configuration class, that is used to testdata the default methods provided by the API.
+ */
+public class TestConfiguration implements Configuration{
+
+ private static final Map<String, String> VALUES;
+ static {
+ VALUES = new HashMap<>();
+ VALUES.put("long", String.valueOf(Long.MAX_VALUE));
+ VALUES.put("int", String.valueOf(Integer.MAX_VALUE));
+ VALUES.put("double", String.valueOf(Double.MAX_VALUE));
+ VALUES.put("float", String.valueOf(Float.MAX_VALUE));
+ VALUES.put("short", String.valueOf(Short.MAX_VALUE));
+ VALUES.put("byte", String.valueOf(Byte.MAX_VALUE));
+ VALUES.put("booleanTrue", "true");
+ VALUES.put("booleanFalse", "false");
+ VALUES.put("String", "aStringValue");
+ }
+
+ @Override
+ public String get(String key) {
+ return VALUES.get(key);
+ }
+
+ @Override
+ public String getOrDefault(String key, String defaultValue) {
+ String val = get(key);
+ if(val==null){
+ return defaultValue;
+ }
+ return val;
+ }
+
+ @Override
+ public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
+ T val = get(key, type);
+ if(val==null){
+ return defaultValue;
+ }
+ return val;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T get(String key, Class<T> type) {
+ if(type.equals(Long.class)){
+ return (T)(Object)Long.MAX_VALUE;
+ }
+ else if(type.equals(Integer.class)){
+ return (T)(Object) Integer.MAX_VALUE;
+ }
+ else if(type.equals(Double.class)){
+ return (T)(Object) Double.MAX_VALUE;
+ }
+ else if(type.equals(Float.class)){
+ return (T)(Object) Float.MAX_VALUE;
+ }
+ else if(type.equals(Short.class)){
+ return (T)(Object) Short.MAX_VALUE;
+ }
+ else if(type.equals(Byte.class)){
+ return (T)(Object) Byte.MAX_VALUE;
+ }
+ else if(type.equals(Boolean.class)){
+ if("booleanTrue".equals(key)) {
+ return (T)Boolean.TRUE;
+ }
+ else{
+ return (T)Boolean.FALSE;
+ }
+ }
+ else if(type.equals(String.class)){
+ return (T)"aStringValue";
+ }
+ throw new ConfigException("No such property: " + key);
+ }
+
+ @Override
+ public <T> T get(String key, org.apache.tamaya.spi.TypeLiteral<T> type) {
+ throw new RuntimeException("Method not implemented yet.");
+ }
+
+ @Override
+ public <T> T getOrDefault(String key, TypeLiteral<T> type, T defaultValue) {
+ T val = get(key, type);
+ if(val==null){
+ return defaultValue;
+ }
+ return val;
+ }
+
+ @Override
+ public Configuration with(ConfigOperator operator) {
+ return null;
+ }
+
+ @Override
+ public <T> T query(ConfigQuery<T> query) {
+ throw new RuntimeException("Method not implemented yet.");
+ }
+
+ @Override
+ public ConfigurationContext getContext() {
+ return null;
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ throw new RuntimeException("Method not implemented yet.");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/TestConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/code/compat/src/test/java/org/apache/tamaya/TestConfigurationProvider.java b/code/compat/src/test/java/org/apache/tamaya/TestConfigurationProvider.java
new file mode 100644
index 0000000..cc1e2c3
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/TestConfigurationProvider.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import javax.annotation.Priority;
+
+import org.apache.tamaya.spi.*;
+
+/**
+ * Test Configuration class, that is used to testdata the default methods provided by the API.
+ */
+@Priority(-1)
+public class TestConfigurationProvider implements ConfigurationProviderSpi {
+
+ private static final Configuration config = new TestConfiguration();
+
+ @Override
+ public Configuration getConfiguration() {
+ return config;
+ }
+
+ @Override
+ public Configuration createConfiguration(ConfigurationContext context) {
+ return config;
+ }
+
+ @Override
+ public ConfigurationContext getConfigurationContext() {
+ return config.getContext();
+ }
+
+ @Override
+ public void setConfigurationContext(ConfigurationContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isConfigurationContextSettable() {
+ return false;
+ }
+
+ @Override
+ public ConfigurationBuilder getConfigurationBuilder() {
+ return null;
+ }
+
+ @Override
+ public ConfigurationContextBuilder getConfigurationContextBuilder() {
+ return null;
+ }
+
+ @Override
+ public void setConfiguration(Configuration config) {
+ }
+
+ @Override
+ public boolean isConfigurationSettable() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/TypeLiteralTest.java
----------------------------------------------------------------------
diff --git a/code/compat/src/test/java/org/apache/tamaya/TypeLiteralTest.java b/code/compat/src/test/java/org/apache/tamaya/TypeLiteralTest.java
new file mode 100644
index 0000000..8e2ddc6
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/TypeLiteralTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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;
+
+import static org.apache.tamaya.spi.TypeLiteral.getGenericInterfaceTypeParameters;
+import static org.apache.tamaya.spi.TypeLiteral.getTypeParameters;
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tamaya.spi.TypeLiteral;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link org.apache.tamaya.spi.TypeLiteral} class.
+ */
+@SuppressWarnings("serial")
+public class TypeLiteralTest {
+
+ @Test(expected = NullPointerException.class)
+ public void constructorRequiresNonNullParameter() {
+ new org.apache.tamaya.spi.TypeLiteral<List<String>>(null){};
+ }
+
+ @Test
+ public void test_constrcutor(){
+ org.apache.tamaya.spi.TypeLiteral<List<String>> listTypeLiteral = new org.apache.tamaya.spi.TypeLiteral<List<String>>(){};
+ assertEquals(List.class, listTypeLiteral.getRawType());
+ assertEquals(String.class, org.apache.tamaya.spi.TypeLiteral.getTypeParameters(listTypeLiteral.getType())[0]);
+ }
+
+ @Test
+ public void test_of(){
+ class MyListClass extends ArrayList<String>{}
+ org.apache.tamaya.spi.TypeLiteral<MyListClass> listTypeLiteral = org.apache.tamaya.spi.TypeLiteral.of(MyListClass.class);
+ assertEquals(MyListClass.class, listTypeLiteral.getRawType());
+ assertEquals(MyListClass.class, listTypeLiteral.getType());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void ofDoesNotAcceptNullAsParamter() {
+ org.apache.tamaya.spi.TypeLiteral.of(null);
+ }
+
+ @Test
+ public void test_getTypeParameter(){
+ org.apache.tamaya.spi.TypeLiteral<List<String>> listTypeLiteral = new org.apache.tamaya.spi.TypeLiteral<List<String>>(){};
+ assertEquals(List.class, listTypeLiteral.getRawType());
+ assertEquals(String.class, TypeLiteral.getTypeParameters(listTypeLiteral.getType())[0]);
+ }
+
+ @Test
+ public void test_getGenericInterfaceTypeParameter(){
+ class MyListClass extends ArrayList<String> implements List<String>{}
+ assertEquals(String.class, getGenericInterfaceTypeParameters(MyListClass.class, List.class)[0]);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getGenericInterfaceTypeParametersRequiredNonNullValueForClassParameter() {
+ getGenericInterfaceTypeParameters(null, Iterator.class);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getGenericInterfaceTypeParametersRequiredNonNullValueForInterfaceParameter() {
+ getGenericInterfaceTypeParameters(String.class, null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getTypeParametersRequiresNonNullParameter() {
+ getTypeParameters(null);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
----------------------------------------------------------------------
diff --git a/code/compat/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java b/code/compat/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
new file mode 100644
index 0000000..42673f8
--- /dev/null
+++ b/code/compat/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.ConfigOperator;
+import org.apache.tamaya.ConfigQuery;
+import org.apache.tamaya.Configuration;
+import org.junit.Test;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link org.apache.tamaya.base.convert.ConversionContext}, created by atsticks on 20.08.16.
+ */
+public class ConversionContextTest {
+ @Test
+ public void getKey() throws Exception {
+ ConversionContext ctx = new org.apache.tamaya.spi.ConversionContext.Builder("getKey", TypeLiteral.of(String.class)).build();
+ assertEquals("getKey", ctx.getKey());
+ }
+
+ @Test
+ public void getTargetType() throws Exception {
+ ConversionContext ctx = new ConversionContext.Builder("getTargetType", TypeLiteral.of(String.class)).build();
+ assertEquals(TypeLiteral.of(String.class), ctx.getTargetType());
+ }
+
+ @Test
+ public void getAnnotatedElement() throws Exception {
+ ConversionContext ctx = new ConversionContext.Builder("getAnnotatedElement", TypeLiteral.of(List.class)).build();
+ assertNull(ctx.getAnnotatedElement());
+ }
+
+ @Test
+ public void testConfiguration() throws Exception {
+ Configuration config = new MyConfiguration();
+ ConversionContext ctx = new ConversionContext.Builder("testConfiguration", TypeLiteral.of(List.class))
+ .setConfiguration(config).build();
+ assertEquals(config, ctx.getConfiguration());
+ }
+
+ @Test
+ public void testSupportedFormats() throws Exception {
+ ConversionContext ctx = new ConversionContext.Builder("getAnnotatedElement", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn").build();
+ assertTrue(ctx.getSupportedFormats().contains("0.0.0.0/nnn (MyConverter)"));
+ }
+
+ @Test
+ public void testToString() throws Exception {
+ ConversionContext ctx = new ConversionContext.Builder("getAnnotatedElement", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn").build();
+ assertEquals("ConversionContext{configuration=null, key='getAnnotatedElement', targetType=TypeLiteral{type=interface java.util.List}, annotatedElement=null, supportedFormats=[0.0.0.0/nnn (MyConverter)]}", ctx.toString());
+ }
+
+ @Test
+ public void getConfigurationContext() throws Exception {
+ ConfigurationContext context = new MyConfigurationContext();
+ ConversionContext ctx = new ConversionContext.Builder("getAnnotatedElement", TypeLiteral.of(List.class))
+ .setConfigurationContext(context).build();
+ assertEquals(context, ctx.getConfigurationContext());
+ }
+
+
+ private static final class MyConverter implements PropertyConverter<InetAddress>{
+ @Override
+ public InetAddress convert(String value, ConversionContext context) {
+ return null;
+ }
+ }
+
+ private static final class MyConfigurationContext 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> typeToConvert, 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;
+ }
+ }
+
+ private static final class MyConfiguration implements Configuration{
+
+ @Override
+ public String get(String key) {
+ return null;
+ }
+
+ @Override
+ public String getOrDefault(String key, String defaultValue) {
+ return null;
+ }
+
+ @Override
+ public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
+ return null;
+ }
+
+ @Override
+ public <T> T get(String key, Class<T> type) {
+ return null;
+ }
+
+ @Override
+ public <T> T get(String key, TypeLiteral<T> type) {
+ return null;
+ }
+
+ @Override
+ public <T> T getOrDefault(String key, TypeLiteral<T> type, T defaultValue) {
+ return null;
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ return null;
+ }
+
+ @Override
+ public Configuration with(ConfigOperator operator) {
+ return null;
+ }
+
+ @Override
+ public <T> T query(ConfigQuery<T> query) {
+ return null;
+ }
+
+ @Override
+ public ConfigurationContext getContext() {
+ return null;
+ }
+ }
+
+}
\ No newline at end of file